7 ms·
In my experience, I have seen much more problems because of over engineering by well meaning people than because of technical debt. Simple but under engineered
by solomatov 6y ago
In my experience, I have seen much more problems because of over engineering by well meaning people than because of technical debt.
Simple but under engineered systems are much easier to rewrite than to simplify over engineered ones.
- didibus 6y agoI would totally count over engineered a technical dept. Any design choices and implementation choices that make a code base limited in its future abilities to change and evolve, and which causes it to require more time and effort to be understood, I consider technical dept. The dept is that you take time and effort from your future to save time and effort in your present.
- solomatov 6y agoI would call it bad investment not a technical debt. As an investor you could invest in a lot of businesses which fail if we use finance metaphor.
- mrmrcoleman 6y agoAgreed. I once worked on a project which was a microservices based system for managing various types of infrastructure. Progress was painfully slow. There was a separate testing client that was used for a lot of the demos. The demos on the 'real system' would fail so often that somebody came up with the idea to just take a lot of the code from the microservices and drop it straight alongside the testing client, as a monolith. It was so much more stable that after becoming the default way to demo, it became the default way to use the tool. 5 years on and I believe it's still running that way. In this case microservices were massive over engineering.
- 35fbe7d3d5b9 6y ago> In this case microservices were massive over engineering. They often are. Well-meaning engineers and architects seem to reach for them while forgetting that microservices are about scaling your organization, not your software. There are very few technical deficiencies in a monolith that are solved by microservices. Indeed, they typically bring technical hurdles: distributed systems are hard to reason through and IPC over the network introduces latency. And you need a very strong ops team to implement them without major headaches. But where they really start to shine is when regression testing takes ~days and your development cycles are screeching to a halt because you've got too many in flight features and not enough runway to land them. What takes real skill is recognizing which of your monoliths should be grown and which ones need to be sliced down the middle.
- spaetzleesser 6y agoI think a lot of today's massively tested, microservice and dependency injected systems will end up as huge piles of technical debt in the future. If you think modifying a COBOL codebase today is hard, wait another 20 years and see how much "fun" it will be to rework today's systems once their platforms are viewed as outdated.
- foobarian 6y agoI'm sure you would love working with currency conversion in a Kubernetes operator :)
- spamizbad 6y agoOne thing I've learned is that what often looks like overengineering is actually underengineering -- it's much "easier" to throw together a complicated system than really think things through and develop something that accomplishes the same objectives in a simpler (but possibly more complex) manner.
- m463 6y agoSometimes it's hard to tell the difference. for instance one smart and experienced guy I knew said if there was an error, your program should just fail instead of giving a ton of messages and recovering. and if you're just throwing code together, that might be what you do. on the other end of the scale, a well written "second pass through everything with cleanup" might have tastefully written code, a few relevant comments and consistency. and then I've seen a lot of code that appears to look like that, but is copy/paste garbage. (sort of the coding equivalent of a wordpress theme)
- darkerside 6y ago> your program should just fail instead of giving a ton of messages and recovering I would bet that he was right in that situation, but that he was also making a nuanced statement. Not all code should fail loudly, but when it should, "recovering" can sometimes be a distraction from a very real problem that needs to be addressed by the right person.
- pjc50 6y agoI've come round to the "fail hard and early" view, provided you can be sure in your design that it doesn't leave junk lying around. Because otherwise contaminated data and invalid states start propagating everywhere..
- quicklyfrozen 6y agoThis can be fun if it's a particular client request that causes a hard failure, and the client retries several times before giving up. Before you know it, all your instances are restarting and no traffic is being handled... So fail early, but not too hard.
- pknopf 6y agoAlso, under-engineering can sometimes mean writing more code, or take longer to implement.
- marcinzm 6y agoWhich may be a great thing if it saves you time refactoring or modifying code down the line. The hardest thing about code is not writing it but reading it, and clever succinct code can be very hard to read.
- kazinator 6y agoThe definition of "technical debt" is so pliable that we can easily regard all the parts of the system that are overengineered to be a form of technical debt.
- allenu 6y agoYeah, to me there's a natural progression in understanding of system design. When you start out, you just write code and don't think about how things interact with each other too much. Then you learn that you're rewriting a lot of code, you overcompensate and start to over-engineer to avoid duplication and often to handle more scenarios than you need. You abstract out possibly too much. Finally, you get to a phase where you realize a lot of abstractions that you've created aren't actually used and you're writing more "meta code" than you need. In this phase you learn to engineer just enough for what you need at the time and design things to be easily changed in the future. You trust that even if you're system design can't handle everything right now, you've designed options for yourself to expand as needed.
- Nimitz14 6y agoNowadays every CS student reads HN and blogposts like this one so by the time you end up having to work with them they're so indoctrinated into the "must write Enterprise(tm) ready code" mindset trying to teach them to be more relaxed is a real pain.
- deleted 6y ago[deleted]
- dstick 6y agoYup, adopt to the business you’re in. As in, the company. Make suggestions if you think it’s worthwhile but in the end accept that there’s a “that is the way” in any company and you’re getting paid to learn and work with that “way”, and build it out :)
- nickbauman 6y agoTDD helps keep this "abstraction abstraction" thing in check.
- mjcohen 6y agoI prefer TDD. More entertaining.
- hmillison 6y agoAgree with this 100%. I've seen both in older codebases. It's even more frustrating when you work with engineers who refuse to believe that any code they write could become technical debt in the future. These tend to be people who overcomplicate systems to anticipate future requirements
- Aeolun 6y ago> These tend to be people who overcomplicate systems to anticipate future requirements I don’t think I’ve ever anticipated a future requirement that did not ultimately turn out to be necessary. Conversely, I’ve had a lot of people tell me something was not necessary only to find that, surprise, surprise, it was necessary after all.
- dudul 6y agoTotally agree. As long as the system is easy to change, I don't care if it's "technical debt". I'll even go further, I don't care if it doesn't give us "flexibility" and "modularity". I don't care if it's not "generic". There is nothing that pisses me off more than people designing systems for future requirements that are not even being discussed by product leads.
- miltondts 6y agoIt's kind of amazing that "over engineering" in software means the exact opposite of what the term should mean. To me, engineering is taking a problem and the corresponding constraints and building the solution that satisfies it with the least amount of resources. "over engineering" in software is about trying to make something adaptable? Or maybe just satisfying someones sense of beauty.. Or maybe it's just about programmer convenience at the expense of customers/user experience and hardware resources..
- ironmagma 6y agoIt's also a bit of an abuse of the term. Overengineering in engineering (mechanical, civil and other similar disciplines) means building a component to withstand more than the absolute minimum. So, a bridge you'd want to be overengineered by a factor of 2 or 3 at least, whereas airplanes are hardly overengineered (lower factor of safety).
- miltondts 6y agoAh I was not aware of the general term and its' meaning. As you say, quite the abuse of the expected meaning.
- Ma8ee 6y agoBut isn’t that how the term is used? The system is over engineered when it is built to scale to a million concurrent users while we current only have a hundred. Or when it is built to handle use cases that no one has required.
- ironmagma 6y agoIn this context I read it more as being excessively complicated to some unspecified end rather than engineered to withstand a load way larger than necessary.
- Ma8ee 6y agoOften it is excessively complicated because it’s divided into dozens of services to be able to scale, or having extra abstraction layers to deal with imagined future requirements.
- jillesvangurp 6y agoUnder and over engineering are relative to your understanding of future requirements, which by definition are both unknown and subject to educated guesses. Making such guesses correctly is what distinguishes a good engineer from a bad one. Nobody ever spells out the current requirements to any level of detail even; so forget about knowing about future ones. You just have to know, recognize, and adapt to that constantly. A lot of over engineering is due to getting this completely wrong: you prepare for something that never happens, at great cost and while underestimating the difficulty level. So you end up wasting endless amounts of time on stuff that has no business value. On the other hand, a lot of under-engineering is due to not having a clue about what is obviously coming next and getting caught by surprise by completely obvious requirements.
- karmakaze 6y ago> understanding of future requirements, which by definition are both unknown and subject to educated guesses. Making such guesses correctly is what distinguishes a good engineer from a bad one I would rephrase this as make guesses based on probabilities and urgency estimates from past experience. You can't know the future but you have stats of the past. So a good engineer is one that has relevant experience and applies it appropriately.
- nullsense 6y agoBasically a perfect description of the problem. Seems to me the default is obviously getting things wrong whether that be over or under engineering. How would one go about reliably making choices that strike exactly the right balance consistently? One thing I'm starting to really internalize is that to do so requires a deep understanding of software engineering as a domain, the domain and existing system, and the technical vectors in the business.
- hinkley 6y agoI think I write code the way people describe Jazz. You have to listen to the notes he isn't playing. I leave breadcrumbs and openings in my code all the time so that the next time I'm in there, I'm set up, invited even, to ask the question I left unanswered before, and maybe do something about it. I leave the option of adding a feature, instead of building a config framework to support it and then defining one implementation. Which will end up not being the correct API when (if) I write the third one. Sometimes people beat me to it, and get excited because they had an idea they're now invested in. I usually just let them have it, don't point out that I put the idea in their head. It's so infrequent people get that invested in functionality, you have to encourage it. There's too many things I'd like to do and never enough time anyway. They've just nominated themselves as a candidate for maintaining that module when I get tired of looking at it, freeing up my time for things nobody else cares about until it's done. It's like if you were designing a house with plans to expand it later. You'd be very careful about certain decisions, like whether you should put a bedroom in the logical spot for an addition, because now that bedroom also has to be a thoroughfare. For 20% extra effort, you've extended the calcification threshold for that house/code by 80%.
- asiachick 6y agoI'd call React and Redux both massively over engineered. There's a ridiculous amount of lines of code being executed to do the simplest of things. You do something like `a.b = c` and really `a` is a proxy so that setting `b` the setting gets tracked going through 100+ lines of code all of which has tracking structures that get setup and torn down between components. They claim this will make your life easier but when the facade breaks you end up having to design your entire app around the fact that `a.b = c` is not simple, it's complex and so you have to avoid it as much as possible my piling on more complexity.
- yoz-y 6y agoAll GUI frameworks hide a lot of what’s happening in the insides. There is a scale to it but personally I think that reasoning about a “reactive” program is quite easier than untangling a ball of callbacks written in say, GtK. Reactive frameworks indeed hide a lot of complexity but that does have positive impact on the user code. (IMO)
- danenania 6y agoA simple react/redux app is definitely much harder to understand than a simple vanilla js app. But a large, complex react/redux app is far easier to understand than 99% of large, complex vanilla js apps.
- barryhoodlum 6y agoNeither React or Redux use proxies or setters at all. Are you thinking of a different framework?
- asiachick 6y agosome lib recommended to remove all the redux boilerplate of react, uses proxies. It's mostly irrelevant though, the point is there's too much code running to do what should be simple things.
- paiute 6y ago“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.” ― C. A. R. Hoare This is how I approach software, but there are so many people out there who won't approve simple code, because it doesn't have enough configs, or classes, or whatever. It seems that the person who wants the most over-engineered code tends to get their way. Psychologically the absence of 'things' is always inferior and harder to argue for than having more 'things'.
- Gibbon1 6y agoThe mode code you have the mode code you have to maintain.
- lalalandland 6y agoC.A.R. Hoare: 'There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies.'