Live data from Hacker News

Ask HN: How to avoid over-engineering software design for future use cases?

news.ycombinator.com

131–140 of 258 posts

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#131
Two things in combination help me fairly well in that regard.

1. Keep It Super Simple (KISS).

Implement the solution which works the easiest first. Copy-pasting code is ok at this point. So if an "if" will do it, use an "if". (Don't start with a BaseClass with an empty default method and a specialized class which overrides it).

Once you have something working (hopefully with some automated tests?) you are allowed to refactor and abstract. But see next point.

2. The Power of Three!

You are only allowed to abstract code once you have copy-pasted it in at least three places. If you only have two, you must resist the urge and move on. Maybe add a comment saying "this is very similar to this other part, consider abstracting if a new case appears".

After abstracting stuff, run tests again (even if they are manual) to make sure you have not broken anything.

Be warned that this method is not guaranteed to produce the "best possible code for future you". If you keep doing this long enough, you might get stuck at "local maxima" in design. Future you might need to do big refactors. Or not. That is the nature of programming IMHO.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#132
post #60

The junior developer sees a pattern and thinks why not make this a bit more generic so it handles similar cases. Oh but these cases fit a larger pattern.. and eventually you'll have written yourself an entire framework. This is very valuable, for the experience. Not for the framework, which will never be used. But you should go through it. The mid-career developer knows this from experience and sticks to the minimum…

Personally this is not my experience. Plenty of seniors spitballing not useful solutions, premature optimization of sort etc...

The mid-career is perfectly fine, give you are also good at refactoring if needed.

Also, another thing that I'm not seeing stressed enough on this topic is: measure.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#133
post #68

Earlier quoted context omitted.

>> engineers go extreme in designing things/code for future cases which are not yet known >They're afraid. In many companies (think FAANG), engineers, especially senior engineers are incentivized/forced to show fancy design docs as part of the annual appraisal process. The more complicated the design, the more 'foresight', the better. If it sounds kind of ridiculous (TPS reports from Office Space anyone?) it is. But…

> In many companies (think FAANG) > The more complicated the design, the more 'foresight', the better. Certainly not in Amazon. Surely there can be exceptions but in general the company has a culture of simplifying stuff anywhere is possible.

I've seen promos being denied, because the problem wasn't sufficiently complex enough. I'd say it was, but the design was simplified as much as possible, leading to 'wrong' impressions.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#134
Something I've recently realised after having listened to Kevlin Henney talk about software engineering is how much of the existing knowledge we ignore. The early software engineers in the '60s and '70s were discovering pattern after pattern of useful design activities to make software more reliable and modular. Some of this work is really rigorous and well-reasoned.

This is knowledge most engineers I've met completely ignore in favour of the superstitions, personal opinions, and catchy slogans that came out of the '90s and '00s. It's common to dismiss the early software engineering approaches with "waterfall does not work" – as if the people in the '60s didn't already know that?! Rest assured, the published software engineers of the '60s were as strong proponents of agile as anyone is today.

Read this early stuff.

Read the reports on the NATO software engineering conferences.

Read the papers by David Parnas on software modularity and designing for extension and contraction.

Read more written by Ward Cunningham, Alan Perlis, Edsger Dijkstra, Douglas McIlroy, Brian Randell, Peter Naur.

To some extent, we already know how to write software well. There's just nobody teaching this knowledge – you have to seek it yourself.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#135
post #102

Earlier quoted context omitted.

TDD and unit tests aren't exactly the same thing. Also, not doing TDD doesn't mean that there's no automated testing. I prefer to write my code and then do a few end-to-end automated tests for the most important parts of the code to serve as a backup in case some change in the code causes massive failures. But TDD is overall tedious for (usually) little benefit when compared to a few well selected end-to-end tests. A…

Exactly, in the time it would take me to write a proper TDD suite, I've written a skeleton of a product from end to end and can start iterating over it. If you're working on a very specific box that has well defined, well known inputs and outputs then TDD is an excellent tool. But for anything with a non-specific "We'd like to do X and display the result on Y" it just gets in the way.

I'd TDD that "do X results in Y" and then add an end to end that that verifies that "Y is displayed", unless that code that displays Y is too trivial then an end to end test might not even be necessary.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#136
post #68

Earlier quoted context omitted.

>> engineers go extreme in designing things/code for future cases which are not yet known >They're afraid. In many companies (think FAANG), engineers, especially senior engineers are incentivized/forced to show fancy design docs as part of the annual appraisal process. The more complicated the design, the more 'foresight', the better. If it sounds kind of ridiculous (TPS reports from Office Space anyone?) it is. But…

> In many companies (think FAANG) > The more complicated the design, the more 'foresight', the better. Certainly not in Amazon. Surely there can be exceptions but in general the company has a culture of simplifying stuff anywhere is possible.

You must not have spent long at Amazon.

My original comment was 100% based on my experience as a developer at Amazon.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#137
We overengineer when we overestimate how hard it is to modify details. As juniors, we wrongly learn that changing code is hard and must be avoided at all costs. As mid-level and seniors, these refactors are much simpler, but the painful memories stick.

Architectural boundaries are hard to change later. Drawing the dependency graph and isolating nodes that can change independently is where the majority of our effort should go (imo). Even still, simple is less risky than complicated. Anytime there are more moving pieces than necessary, there is a risk of an unexpected requirement blowing a hole in a design. So identifying those dangling pieces and spending a lot of thought and energy in removing them is where I've found it to be rewarding to "overengineer".

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#138
Historically, this made much more sense. RAM was incredibly scarce as were CPU cycles and the hardware was often tied intrinsically with the software so a modification later down the line was a really big deal.

With modern higher-level languages and scalable cheap hardware, this motivation should have gone away and we should be writing code that is relatively easy to re-factor.

If I don't know that we will need this thing in the future, it doesn't go in. Simple. If 6 months down the line, we now need to add the new feature, I like to think that my code is largely maintainable enough to refactor it to add the feature.

The only exception I can think of is where something is designed to be extendible like e.g. Instagram filters where you might have 10 when you launch but you know that you will have more in the future so you write your code to allow additional filters to be plugged in relatively easily.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#139
It's a difficult battle in many teams where some people will just go overboard for multiple reasons, usually in this order: fun, fear of being seen as short-sighted and/or promotions. It mainly happens in big orgs and your examples definitely fit the bill although I haven't worked there specifically. I'm not that old (very late 20s) but I've seen overengineer code (or infra) ending in the trash so many times... many people could see it coming and warned about it, yet it still happened.

I usually try to support the opposite idea by bringing agile to the table. Agile doesn't say "please don't overengineer" but "this can change a lot in a couple sprints, requirements may be different, there are more (or none anymore) use cases now" and hence why to spend so many resources doing something that not only doesn't cover all potential unknown use cases but also adds overhead when reading the code for no benefit. For some teams this has clicked very well. Appropriate agile training can help a lot.

However it doesn't always work and if the person(s) doing this have higher ups backing it up (even if unintentionally) you're fighting the wrong battle. If you can't change it, move teams or to a company where money is a bit tighter and/or where these behaviours aren't tolerated - in other words, where things needs to get done and there's no time for experimenting with things that most likely won't yield returns.

Re: Ask HN: How to avoid over-engineering software design for future use cases?

#140
Solve the problem directly in front of you.

Then understand a new problem.

Repeat.

If you then start doing things like externalizing inputs, writing tests then when your past solutions become future problems.. You will have created the guide rails on how to solve both the past problem and the future problem together. This is the futureproofing that you should be aiming for. Make sure you write at least a few unit tests that mock out the important logic parts, and write up a short 1 page document about the intent of the program, maybe with a picture and drop that in the README.

Post reply on HN