Live data from Hacker News

Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

newsletter.beginner.dev

41–49 of 49 posts

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#41

Earlier quoted context omitted.

A half-baked thought: It's interesting though isn't it, that the "immature" approach is to try to be extra vigilant. You'd think an immature coder would just want to hammer things out quickly. I wonder if it's because they learned that lesson at some point (maybe in college) and are overcompensating, trying to be extra mature or something.

A lot of us were really immature, just-hammer-something-out coders in high school, maybe in college. Then we got a job, and now we had to be professional . So we went too far the other way, trying to be how we thought we were supposed to be, but without really knowing how yet. (Shout out to Don Martini, who helped me more than he knew in my first job, as I was trying to grow into a professional programmer. Ditto Stev…

Yeah, I think this is insightful and is common across many disciplines.

When starting out you do as much as you can, which is often very little, things are underdeveloped. You just don't have the tools and techniques to properly solve problems.

As you improve, you expand your set of tools and techniques and you tend you overuse them. This is part of the learning process but can result in things being overbuilt.

It's only with time, experience, and feedback that you learn the boundaries about what tools and techniques are most useful and appropriate.

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#42
I practice something I sometimes call negative space, which sometimes ends up about as vague as it sounds.

My gold standard for well written tests is if the engineer who broke the test can fix their regression without looking at the test implementation, you have achieved nirvana.

My gold standard for well factored code is if people add a feature exactly where you would have added it. But that can be arrived at through socialization or by leaving spots where a feature would need to go if you actually need it.

You don’t need to build in conditionals for speculative features. You can just think about how you would start. What’s the first refactor? Can I arrange the code so that’s not a pain in the ass?

Bertrand Meyer felt that actions and decisions should not be mixed. For one they make testing a pain. They also increase the lines of code in impure functions, which reduces scalability of your system. A common effect of new features is adding more complexity to the decision process, so it’s easier to add 3 lines to an 8 line function than 3 lines to a 40 line function.

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#43
Write code for the problem you have in front of you today. Stop.

However: If you have senior devs knowledgeable in the domain who can realistically show how the system has changed in the past, write code to accommodate those types of changes because it is far more likely that the system will change again similarly than change some other way. If someone pipes up with some "what if" hypothetical, shut them down.

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#44
He's right.

When the author says over-engineered stuff is future-proff and all of that, he's implying _successful_ over-engineered stuff. Same for under-engineering.

Of course most over-engineered projects fail. Most under-engineered too. That's why we learned all those things people are parroting in this thread (we parrot because it's useful).

However, _some_ over-engineered projects will succeed. Those will most likely present a nice combination of future-proofing, scalability and reusability at the core of their success. Some under-engineer projects will iteratively limp their way into excellence as well.

He's not asking you to think of scalability and such, on the contrary, his recipe for following the middle way is quite reasonable (although a bit generic, like these kind of things always are).

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#45
post #38

Earlier quoted context omitted.

There is a balance. I've seen plenty of under-engineered software with the same code copy-and-paste dozens of times. I've also seen incredibly complex abstraction layers that only made sense to their original authors (long gone...) and were incredibly hard to navigate and maintain (class hierarchies 5 layers deep, etc.)

It's worth noting that oftentimes a complex abstraction layer can be a sign that they were building upon an under-engineered base. A corollary to Hanlon's Razor could be: "Never attribute to over-engineering that which is adequately explained by repeated under-engineering."

The problem, IMHO, is that often "engineering" is ad-hoc, divorced from the big picture:

Developer sees codebase with too few / bad abstractions that make changing the code base in the way they want to hard. They invent some new abstraction (e.g. class hierarchy) that solves the immediate problem and makes adding the new code easier.

The problem is that these new abstractions may only make sense in the particular state the code is in right now and don't necessarily correspond to intrinsic / natural concepts that can be verbalised when talking about the solution.

A good indicator of this is that you have a bunch of "...Service" classes that don't really tell you what their responsibility is. In the end, you might have 10 such classes all calling each other, and new code is added to these classes seemingly at random without any sense of coherence to the individual components. Then, in the worst case, some people go overboard unit testing these classes with questionable semantics and interfaces, mock everything away, and refactoring the mess becomes a huge pain.

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#46
post #8

Newbie devs think under-engineering is a problem. Experienced devs know over-engineering is a problem.

Both is a problem. It's just that, as a dev, you're less likely to see code with massive amounts of duplication because any mediocre developer understands why this is bad.

However, work with really bad (or just extremely inexperienced) devs and/or people who are not primarily coders (e.g. data scientists), and you'll see a lot of under-engineering to the point that it's almost impossible to figure out what the code is actually doing (especially when it's coupled with random code that is inserted without understanding, just because it makes things work somehow, at least on the dev's machine).

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#47
The issue isn't over or under engineering by these definitions. A good solution needs to satisfy both all requirements, some of which may be clear from the onset and some of which need to be discovered. The issue is how one handles unknown requirements. So often people either guess what unkown requirements will be (which is how this piece defines over-engineering), or ignore them (which is how this piece defines under-engineering). You should be doing neither. Instead you should be decoupling your known from your unknown requirements so that you are agnostic to what solutions need to be implemented down the road. You don't need things that can handle problems you don't have, but you need to be able to easily rip out and replace parts of your solution as they become inadequate. You don't need to handle every edge case, you need to design things to fail safely by default. You don't need to hold off on making decisions until you have information, you need to make decisions you'll be happy with no matter what information you receive later. A robust solution can still be quite lean.

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#48
post #23
post #21

Earlier quoted context omitted.

> I really disagree with the pros listed on over-engineering, specifically "future-proving" and "reusability" Yes, someone who argues that "over-engineering" leads to "future-proving" is caught by the bug. When you future-prove something, that's called "engineering". Over-engineering is by definition failing to foresee future needs, imagining generic future needs ten steps ahead instead of the less ambitious future n…

Exactly. A thing so small and simple that you can rewrite it in an afternoon is more futureproof than any 8000 LOC monstrosity.

> Exactly. A thing so small and simple that you can rewrite it in an afternoon is more futureproof than any 8000 LOC monstrosity.

As I've said multiple times, here and elsewhere, it is easier to fix the problem of under-engineering that the problem of over-engineering.

I also disagree with the article's "pros" for over-engineering. There is no pro that I can think of that doesn't boil down to resume driven development.

The pros of under-engineering is (the way you say it) obvious: very little time was spent to figure out that you did it wrong.

Re: Striking the Right Balance: Over-Engineering vs. Under-Engineering Software

#49

I really disagree with the pros listed on over-engineering, specifically "future-proofing" and "reusability". I doubt you can accurately predict the future and whatever assumptions you make will likely be wrong in some way. Then you are stuck having to solve the problem that you created by trying to predict. As for reusabilty, it's similar. Start with solving what you have to, then abstract as you see it fit. Again,…

It's interesting to try to fit what is often talked about as "future-proofing" and "reusability" into the development of a general-purpose CPU, since CPUs are in a sense the ultimate reusable system. In an overly simplified textbook example of designing/building a CPU, you have an ISA you're building the CPU to support. The ISA defines a finite set of operations and their inputs, outputs, and side effects (like stori…

> Usually a system just needs to support a handful of use cases, like integrating with different payment providers.

Building EV chargers is a good dose of electrical engineering combined with talking to dozens of car models and their own particular quirky interpretations of common protocols, which is like designing websites for a market with dozens of unique browser implementations.

In spite of that, it seems half of the complexity is making sure people pay.

Post reply on HN