Live data from Hacker News

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

news.ycombinator.com

1–10 of 258 posts

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

#1
I have worked at Microsoft and Google in multiple different teams.

One thing I realized that sometimes engineers go extreme in designing things/code for future cases which are not yet known. Many times these features don't even see any future use case and just keep making the system complex.

At what point we should stop designing for future use cases ? How far should we go in making things generic ? Are there good resources for this ?

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

#3

my rule of thumb is: requirements -> tests -> specific code if i reach the same code more than once, refactor and bother to generalize....

Can you explain this a little more in your own words, I've tried to read through TDD and talked with co workers but never actually seen this in the wild.

How do you go about planning your tests / separation of concerns. As in do you only write tests for your service layer? I find I'd be wasting time to write it at the controller level/route level.

What about the DML schema?

Personally I always start at the database layer and work up because then I know at least what data and models I'll be working with

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

#4
Although software development tends to come across as deterministic with rules on what to do when, a lot of it is up to developing good judgement.

The more time you spend thinking about the business and how what you're building will support it the better judgement you'll develop. You might not be able to articulate or argue it but you'll have an instinct on when an abstraction is going to be useful vs brittle.

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

#5
Make your code modular. Use dependency injections. Write short, clear functions.

When everything is DRY and functions follow SRP, it's hard for your code not to be "future-proof."

Tests only when they make sense, not when you are mocking half the app.

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

#6

my rule of thumb is: requirements -> tests -> specific code if i reach the same code more than once, refactor and bother to generalize....

Can you explain this a little more in your own words, I've tried to read through TDD and talked with co workers but never actually seen this in the wild. How do you go about planning your tests / separation of concerns. As in do you only write tests for your service layer? I find I'd be wasting time to write it at the controller level/route level. What about the DML schema? Personally I always start at the database l…

The service layer can be the most practical place to write tests, because you aren't mocking a lot of random services (like you would with a controller) and you can focus on testing methods that do a single thing, if your services are well written.

If your test is more than 5-10 lines long, you are probably trying to do useless things like mock half the app and you should have a method that returns simple data / services that don't take a 1000 other services as dependencies.

TDD is only a good choice when you have a clearly defined problem and know how you solve it.

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

#8
1. Embrace refactoring/rewriting as inevitable;

2. Understand it's very often easier, faster and better to write something trivially but twice than writing it well once;

3. Realize no matter how hard you try, unless this is something you've already done once (which brings you back to #2 above), then your information of the problem is incomplete and therefore any all-encompassing solution you may have will essentially be partial and based on extrapolation of your knowledge and guesswork.

The above also deals with a significant cause of procrastination - an internal subconscious feeling we can't do what we're about to do well, therefore we'd rather not even start it. Just sit down and tell yourself, "today I'm going to write a bad module X", and with enough time you'll be able to sit down again and write a good X.

The one thing you should spend a bit more time on is interfaces and decoupling, but as for internal implementations of things, or even entire system blocks that you can swap later on - don't bother too much. It'll be OK at the end, and you'll get there faster. Even if you need to rewrite the whole god damn thing.

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

#9

1. Embrace refactoring/rewriting as inevitable; 2. Understand it's very often easier, faster and better to write something trivially but twice than writing it well once; 3. Realize no matter how hard you try, unless this is something you've already done once (which brings you back to #2 above), then your information of the problem is incomplete and therefore any all-encompassing solution you may have will essentially…

^ This

Also:

1. cut features and enjoy saying no.

2. set deadlines and ship (if not enough time, see 1 above)

3. don't skip tests; makes refactoring/rewriting a breeze

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

#10
The chapter The Second-System Effect form The Mythical Man-Month book (Brooks, Jr. Frederick P.) talks about this problem:

“An architect's first work is apt to be spare and clean. He knows he doesn't know what he's doing, so he does it carefully and with great restraint.

As he designs the first work, frill after frill and embellishment after embellishment occur to him. These get stored away to be used "next time." Sooner or later the first system is finished, and the architect, with firm, confidence and a demonstrated mastery of that class of systems, is ready to build a second system.

This second is the most dangerous system a man ever designs. When he does his third and later ones, his prior experiences will confirm each other as to the general characteristics of such systems, and their differences will identify those parts of his experience that are particular and not generalizable.”

The overall advice is to practice self-discipline:

“How does the architect avoid the second-system effect? Well, obviously he can't skip his second system. But he can be conscious of the peculiar hazards of that system, and exert extra self-discipline to avoid functional ornamentation and to avoid extrapolation of functions that are obviated by changes in assumptions and purposes.

A discipline that will open an architect's eyes is to assign each little function a value: capability x is worth not more than m bytes of memory and n microseconds per invocation. These values will guide initial decisions and serve during implementation as a guide and warning to all.

How does the project manager avoid the second-system effect? By insisting on a senior architect who has at least two systems under his belt. Too, by staying aware of the special temptations, he can ask the right questions to ensure that the philosophical concepts and objectives are fully reflected in the detailed design.”

Post reply on HN