How do I stop overcomplicating my code?
Posted by Innovator-X@reddit | learnprogramming | View on Reddit | 39 comments
I always overcomplicate things when I code. The following scenario always happens:
-
I need to find a solution to a problem.
-
I make a very very terrible overcomplicated and ugly solution.
-
I look for another way to solve the exact same problem online only to find out it was very simple to begin with. Solution is elegant, very succinct and short.
I know that with experience things will get better but my question is: do I need to deliberately practice this or will it come naturally? Thanks.
HashDefTrueFalse@reddit
I often see juniors trying too hard to express everything very generically and make everything extremely configurable to the point where they end up with lots of code and a result that doesn't excel at anything in particular. They've been told that all the code they write should be reusable and will be reused etc. despite very little of that happening in the real world. University grads in particular seem to have been taught to write a ton of boilerplate when using object oriented languages. Getters/setters for every field, an interface for every class, etc.
I usually tell them to just focus on writing code that solves the problem that they need to solve, give the solution a simple interface, and for anything that they needed to change often when testing, make the solution receive it from the caller, or read it from some config file/var somewhere. If we need to change the code later, we will. Simple as that. Our task right now isn't to solve future problems we might never have.
Innovator-X@reddit (OP)
Oh my god you are exactly right. These habits are what really stuck with me from college. I really like your advice. I should write code that does one thing and one thing well. Refactoring can always come later if needed. Thanks for your input.Â
marrsd@reddit
It's a useful exercise to go back to a problem you just solved and see if you can simplify it. Then try and simplify it again. You often don't fully understand a problem until after you've implemented a solution, by which point the better solution often reveals itself to you.
It's worth taking a break between iterations. A good night's sleep gives your subconscious time to process what you've learnt.
You should also try not to be clever. A lot of people start by learning object oriented programming, which is perhaps the most overrated - and most complicated - paradigm in computer science. Stick with simple procedural code. Read your code back, see where you're repeating yourself, and refactor the duplicate code into functions.
NatoBoram@reddit
There are a few tricks and shortcuts you can use to make your code less complicated. You often learn these by pair programming with experienced developers, by reading online articles about some coding techniques or watching some videos on YouTube.
For example, I have a few of them here that can help you almost deterministically.
aqua_regis@reddit
It all boils down to experience. That's it. It will come more natural with time and experience.
You're doing the right approach, though, by first trying to develop your own solutions, no matter how convoluted and complicated they may be and then looking for other solutions.
There is an old saying in programming:
You have to come to terms with "any working solution is better than no solution and great ideas". You can always refactor the code later and you actually should from time to time visit your old programs and refactor or even rewrite with your newly acquired knowledge and experience.
Sometimes when learning you simply lack the knowledge of what is available in the language and once you seek out and see a different solution, you will get an "Eureka" moment. That's nothing to worry about.
Innovator-X@reddit (OP)
Thanks for you input this is pure gold
ihateTheCheeeeese@reddit
it's not just experience. knowledge about language capabilities and libraries would help you enhance your code.
don't be afraid to break stuff or try weird sytax, approachs or whatever. actually, do break stuff. that would help you gain knowledge and experience.
icepopper@reddit
This 👌🏽
FooWho@reddit
In The Mythical Man Month, Brooks advises you to, "Plan to throw one away, you will any how."
I think this is just as true in little projects as it is in bigger projects. I doubt that many people have ever been happy with the first version of something. I know that for me, I will commonly realize halfway through something that there is a better way.
Crypt0Nihilist@reddit
You're doing it right. You are coming up with your own solution. You're identifying that it is sub-optimal. You are discovering a better way of doing it. Over time your initial solutions will approach the elegant solution.
Arrow_@reddit
Make it work, then make it pretty.
JGhostThing@reddit
It really will come with experience, but you could still actively look for a better solution. Studying design patterns will help you.
Innovator-X@reddit (OP)
What resources would you recommend?
KandevDev@reddit
couple of things that helped me with this same pattern:
(1) write the dumbest possible solution FIRST, even if you "know" it is bad. before that solution exists, your brain has nothing concrete to optimize against, so it invents complexity hypothetically. once the bad solution is on screen, you can actually see what is worth simplifying.
(2) when you find the elegant solution online and think "i should have known", read it twice and then close the tab. do not copy. write the elegant version yourself from memory. that is the practice that actually changes how you will think next time. just reading the elegant version teaches you "this exists" but not "how to find this".
Innovator-X@reddit (OP)
Thanks this really helped me :) (especially your final sentence)
MikeUsesNotion@reddit
I've noticed I'm more prone to this problem if I'm in a "work, damn you" loop. Especially when combined with "I just want this one stupid thing to work before I quit for the day". I've gotten better over the years (20+ at this point), but it still happens.
Part of it is being self aware about your coding and knowing when you should stop and disentangle your mess before moving on.
Innovator-X@reddit (OP)
Yeah when this happens I just delete everything and start from scratch. I think “disentangling my mess” is the better option.Â
Frolo_NA@reddit
practice TDD. stop when you can't think of new tests to write.
Aggressive_Ad_5454@reddit
My young friend, you have stumbled across the way we programmers work. You’re doing it right.
Just keep programming. Eventually you’ll get the experience you need to skip the step of keying in and testing the first solution you dream up and you’ll be able to just key in and test the simpler one. In the meantime, keep a pencil, a pad of paper, and a wastebasket handy. You can use those things to sketch out your first solutions. The wastebasket is possibly the most important of those tools.
Innovator-X@reddit (OP)
I love this answer so much. Thanks for your input!
Scared-Push3893@reddit
honestly most people write the cursed overcomplicated version first lol. half the battle is figuring out what problem youre even actually solving. my notes started turning into chaos from this so ive been throwing messy thoughts/tasks into Runable to sort it out
mxldevs@reddit
There are two kinds of over complications
You don't really know any other way to solve it, so your over complicated solution is the only solution you can come up with
You know how to solve it. You just think you need a million layered of abstractions to decouple every single piece of logic, and you end up with enterprise fizzbuzz.
If you couldn't come up with the clean solution, that's not an issue. Having gone through the process of figuring out how to solve it yourself, you may be able to understand the simpler solution better and figure out what they did differently, and apply it to your future problem solving.
If you simply looked up a solution, you likely won't get any insight from it.
mredding@reddit
To add, experience is intuition. Let's break it down. Dunning and Kruger have an effect named after them, but really their seminal paper focused on how information is internalized in the mind. It comes down to 4 quadrants:
The things you know you know. The things you know you DON'T know. The things you DON'T know that you DO know. And the things you don't know you don't even know.
Intuition moves from a known-known, to an unknown-known. From rote memory to intuitive memory.
The former is inferior - because it's only by active recall. You haven't internalized it. You can't act on it but with an extreme amount of effort and help. Yes, you can recall it, exactly as it was presented to you, but so what?
The latter is when you stop thinking about it. You're just using it. Intuition is informing your decision making and consideration without you having to actively do it - this frees your mind, capacity, and resources, to more immediate tasks and unknowns. But it's there... It's helping you...
The difference between you and me is I've got 37 years of experience. When you watch me work, I make it look easy. I get straight to work with designs and solutions, right to code without having demonstrated any prior consideration for why I'm already doing what I'm doing.
That's because I'm not making decisions - not now; I've already decided. Up to 37 years ago.
This is what you're trying to train your brain to achieve. You're trying to get the known-knowns into known-unknowns. If you recall in earlier education where you're supposed to read a book and write a report "in your own words", what the exercise was trying to do was help you move rote knowledge into intuition. Once it passes that barrier, once you forget the memorization but still retain the knowledge, THEN you can speak the truth in your own words. This is what it is to have expert knowledge - it's breadth, it's depth, AND it's intuition. This is why you can never keep up with a domain expert, because while you're swatting at facts and figures and rote knowledge, they've made neural pathways and inroads and unconscious deep consideration for years and decades on the subject, that they can pull knowledge structures from deep within that expertise that you cannot possibly do yourself, unless you're also a domain expert in specifically that field, too.
We're just trying to get you there. Now time is the almighty critical factor, but exercising these neural pathways is a big component in making that happen, so just keep going. If we could ever figure out a FASTER way of doing it, we'd all be experts sooner, and possibly richer for having discovered such a technique - it'd revolutionize education, but alas, no one actually knows how to make this process go faster. Just be in it. All the time. Saturated, but not, perhaps, to the point of exhaustion though...
My other bit of advice - my philosophy is that I'm not very smart, that 99% of what I want to do has already been done 40-60 years ago. Usually this is true. Very few of us ever invent anything new, most of the job is business logic, which is almost entirely established; you've got industries catering to markets, that means everyone is doing the same basic business practices, I'm just implementing a given business process HERE, as it's never been done before, HERE...
Ok, so typically what I do is a fair amount of googling. Typically, there are libraries and standards that already exist JUST FOR what I want. You need to get good at searching and recognizing when you find it. Sounds like an impossible task, but it really is just another skill. My most common example is logging - everyone writes their own logging code like logging doesn't already exist. The code tends to look like what Eric Allman did for Sendmail in 1983 - the pattern EVERYONE copies. Very poorly. But no one bothers to acknowledge Eric also invented system logging and RFC-5424. Everything you need your logging code to accomplish is in this standard, and anything you do that is less is buggy, incomplete, unstable, ad-hoc, and incompatible with industry standards, which has more damning consequences. Everything everyone does with their own logging is wrong. Drives me FUCKING crazy.
Your ass is slow. If your logging was actually complete, and compatible, it'd be just as fast. Ubuntu uses rsyslog, which is asynchronous and can handle something like ~6m messages a second on this old-ass x86 clone embedded bullshit no-name processor we're looking to replace here - it's plenty fast for your shit.
This leads into my next philosophical point: Presume you're wrong. Stupidly, retardedly wrong.
If your logging is slow - flip the premise and thus the question: logging is fast, so why is my logging slow? Have you ever considered you're logging wrong? Have you ever considered that the way you're doing things, the way you think you want to do things, is the wrong way? Industry wide standards - and it just so happens to be too slow to be usable for ::checks notes:: everyone? And yet all our most foundational and performance critical software - the OS and system, all use it..? I mean, if the OS is slow because of logging, isn't that dragging down your software? So why are you on that platform? Why does the platform even use syslog? Make it make sense...
It took me DECADES to understand C++ and OOP, because I discovered literally ALMOST NO ONE understands it, and those who do are essentially impossible to find. It took decades of learning OOP from ancient whitepapers and seminal works, languages like ALGOL-68 and Smalltalk to understand what it was, learning about Bjarne and his works to understand what the hell he was thinking, what Jerry Schwarz (the forgotten father) was getting at.
Now days my code is what our C++ founders intended, OOP or FP, and it's entirely alien to my colleagues across my career. It's a curse.
So I always recommend people stay curious about software history, because the context gets lost, but understanding it makes technology make sense. So much of our shit is backward compatible with 1850s telegraph equipment on purpose, and maybe if you understood more of that a lot more would make sense about what's going on and why. It'll help you build the future from first principles.
Also what's old is new again. We're always solving for the slowest part of the system. When the next new thing comes out, that part is no longer the slowest. That means the NEXT slowest part is now the slowest, so we're solving for THAT. The old techniques become forgotten as they become abandoned due to the focus on the next new slowest problem. Alright, well give that 10 years, and wouldn't you know it? But what was once the fastest part is NOW THE SLOWEST PART, and how we once solved for that is relevant again! But we've all forgotten, so now we have to rediscover those techniques again. Data Oriented Design used to be called "batch processing". Edge Computing was once called "thin client". What we all know as Docker today is actually built upon namespaces in the Linux kernel which was a concept first invented in the late 1980s with 11th edition Unix aka PLAN 9...
If only we never forgot...
Embarrassed-Pen-2937@reddit
Plan.
flowchart or sequence diagram or pseudo or whatever works for you. Plan -> review -> implement
crawlpatterns@reddit
honestly i think almost every programmer goes through this phase and its kinda part of learning how to think in code. alot of the “clean simple solutions” people post online usually come after they already made the same overcomplicated version first lol. what helped me was slowing down and asking “what is the dumbest possible solution that still works” before trying to be clever. over time you start recognizing patterns naturally, so i wouldnt stress too much about it rn
opentabs-dev@reddit
honestly the thing that helped me most was writing the problem out in plain english before touching code. like literally "for each user, find their most recent order, then group by region". if you can say it in one sentence, the code usually falls out of that sentence. when i skip that step i end up inventing nested loops and flag variables for stuff that's really just a filter+map.
the other thing — your "ugly first draft" is doing real work. youre learning the shape of the problem. the elegant solutions you find online were also someone's 3rd or 4th draft, you just dont see the first ones.
ScholarNo5983@reddit
Study that code, understand that code, try to figure out where you went wrong and next time tell yourself, you need to do better.
With time and that simple approach eventually you should see better outcomes.
bestjakeisbest@reddit
First make things simple as possible, there are overcomplications allowed like making things extensible, or avoiding hard coding things in your "library logic" side of your program, hardcoding certain things in the business logic side of things is sometimes best but you should aim to make your code generalizable, like say you were making a program to draw shapes it would be bad practice to declare an array of say 5000 shapes to hold everything the user will make because what if they use 5001 shapes? So instead use a list or a vector.
Next if you have an idea there could be merit to it, so test it (unit testing is good to verify the code does what you need, but also integration test with toy examples and benchmark), if it does not give you an increase in speed in your test, or it doesnt make coding any easier or it introduces too much mental load while programming, get rid of it or refactor it.
Far_Swordfish5729@reddit
It comes with experience. Also complexity and efficiency are not the same thing. Many of my single pass iteration loops or hash table reference loops are much longer than an equivalent nested loop solution but execute much faster. Focus on trying to touch data fewer times, organize your workspace to do so, and trying to visualize all the possible things you need to account for and which matter where. That will suggest how to collapse it down as you plan it.
Also as you get better you learn patterns and make variations of them. Without the starting pattern a lot of what I’d try would be messier.
Finally don’t confuse abstraction for simplicity. A lot of what we do is complex and is just hidden behind a method call or shorthand. JS does this a lot.
itijara@reddit
It's almost never possible to find the most elegant solution the first time around unless you have done something similar before. You should always iterate on a solution, ideally before you start coding, to address problems. My go to is to start with the simplest (and not optimal) solution, then think through what would make it better and add things but by bit instead of going for the complete solution first. Usually, that means making something that actually solves a much simpler problem first, then adding bits to solve the real one.
Experience helps a lot as you will almost always have seen something like this before and will recognize the pattern. Studying abstract data types and design patterns is also a good idea as it builds the pattern recognition into you.
kinkyaboutjewelry@reddit
You keep doing what you have been doing, including the part where you look up how you can do it better next time. You learn and the next time you do a little better on that angle. You fail in a different way. Rinse and repeat.
judyflorence@reddit
The ugly first version is usually how you learn the shape of the problem. What helped me was treating “make it work” and “make it simple enough to explain” as two separate passes, not one magical first attempt.
AdityaVerma609@reddit
One thing that helps is solving the problem first, then refactoring after.
Your first solution doesn’t need to be elegant.
Clean code usually comes from iteration.
KC918273645@reddit
That know-how comes gradually. You just need to keep programming. The more you program, the sooner you'll start developing that know-how / experience.
Sir_lordtwiggles@reddit
People only post the final version of the solution.
You are missing 2 things:
Admirable_Sir_7511@reddit
Just enjoy the process of learning.
We all started thinking complex is better, if it looks difficult it means your better - then you swiftly learn simplicity first.
Pseduo code your work, look at the process' at play - identify pain points and think of a structure needed for your code, as many stated before code is iterative, and alot of times subjective - you will eventually find your feet.
Anonymity6584@reddit
keep practising problem solving on languuage you are trying to learn. You start get to those more elegant solutions when youlearn more and gain experience.
autophage@reddit
Practice.
One thing that will help you get better at this quickly is to set aside a bit of time to do hardcore test-driven development - write a test, write code that passes the test, see if you can refactor, then start the loop again by writing a new test.
DrShocker@reddit
You make the bad version better. It's fine for coding to be iterative. There's no expectation that your first implementation is the ideal one.