Live data from Hacker News

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

news.ycombinator.com

91–100 of 258 posts

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

#91
post #67
post #32

Earlier quoted context omitted.

Unit tests are absolutely fantastic during refactoring. I once had to rewrite a piece of code where nobody really knew what it did or what it had to do, and the original author just made some guesses about the intention. I started out by writing unit tests for everything, which became my handhold and documentation for what the system originally did. Then I started reorganising the code into a more structured and more…

I would argue that having a robust type system and some (not too many) end-to-end tests for your software makes unit testing almost completely useless overhead.

Perhaps in some world where you never modify a type (e.g. concatenate/truncate strings, multiply numbers, etc). Type systems check types, they don’t help verify correctness of the logic performed on the types.

For an example, dig into some crypto libraries. They operate on bytes all over the place performing XORs, etc. A type system isn’t really gonna help you ensure you got the correct number of AES rounds and stitched the blocks in the right order.

IMO the only systems where this “type system eliminates most tests” philosophy seriously works are the ones that don’t do anything other than pass data between components without doing anything beyond calling some serialization methods.

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

#92
There can be no definitive answer to your question but of course some "thumb rules" are applicable.

* The nature of your "system" defines how much attention you should pay towards futureproofing. If it is an end-user app/feature only do what is required and nothing more. You are solving one instance of a (maybe) small class of problems. The future will dictate what needs to be added/modified/refactored when you reach that point and not before i.e. no predictions unless you know the domain well.

* If you are building an "architecture" component like OS/Framework/Library etc. then you need to pay attention to generality and extensibility and design with futureproofing in mind. Use standard best practices like data/api versioning, narrow module interfaces, information hiding etc.

* Always focus first on Readability and Maintainability to the exclusion of everything else. Only when you hit a wall with respect to aspects like Performance etc. do you go back and redo/refactor the code for the newly prioritized requirement.

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

#93
One of the most challenging things in growing a software product is managing complexity. If you are designing a product for future use cases, you add complexity upfront. To keep a healthy balance, I try to follow simple guidelines:

* Focus on the current assignment. Implement it using clean code principles, don't overthink the problem.

* Rather than spending time on design decisions, allocate time on handling edge-cases. These will save you from PageDuty alerts.

* Plan excessive for future use-cases only around data models that insert/read into the database. Data migration is super-painful. A more generic design around your database is almost always preferable.

* Have a feature toggling[1] service in your codebase. It will provide you with a better understanding of how you can implement new features alongside existing codebase in the same branch. Releasing features from long-running separate branches is almost always a wrong decision.

* Always keep in mind time-constraints and how urgent is the requested functionality. Don't let perfection be the enemy of productivity.

* Have a process in place that allows for the technical debt tasks to be tackled independently. It helps fix some bad design decisions, which become apparent in light of new requirements.

[1] https://martinfowler.com/articles/feature-toggles.html

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

#94
post #67

Earlier quoted context omitted.

I would argue that having a robust type system and some (not too many) end-to-end tests for your software makes unit testing almost completely useless overhead.

Perhaps in some world where you never modify a type (e.g. concatenate/truncate strings, multiply numbers, etc). Type systems check types, they don’t help verify correctness of the logic performed on the types. For an example, dig into some crypto libraries. They operate on bytes all over the place performing XORs, etc. A type system isn’t really gonna help you ensure you got the correct number of AES rounds and stitc…

> IMO the only systems where this “type system eliminates most tests” philosophy seriously works are the ones that don’t do anything other than pass data between components without doing anything beyond calling some serialization methods.

Which is what 90% of programmers on this website are essentially doing. And for the remaining 10% there is likely a better suited, different programming language or type system available. Even if there isn't unit tests would still be very niche and the general case would be that by default you shouldn't be unit testing.

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

#95
post #67
post #32

Earlier quoted context omitted.

Unit tests are absolutely fantastic during refactoring. I once had to rewrite a piece of code where nobody really knew what it did or what it had to do, and the original author just made some guesses about the intention. I started out by writing unit tests for everything, which became my handhold and documentation for what the system originally did. Then I started reorganising the code into a more structured and more…

I would argue that having a robust type system and some (not too many) end-to-end tests for your software makes unit testing almost completely useless overhead.

If the code is a mess the type system can’t help, it is part of the mess.

End to end tests are really slow, but if you can get them into the 300-1600 tests per second range then i have no beef. I value tests but I seriously grudge waiting for tests.

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

#96
post #85

> How far should we go in making things generic? My rule of thumb for this is to repeat yourself at least 3 times before trying to build an abstraction to DRY them up. 3 use cases is obviously not always sufficient inform the design of a good abstraction, but IME: - abstracting at 2 use cases is very often premature and results in leaky/brittle abstractions where the harm from added coupling between fundamentally inc…

[deleted]

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

#97
post #85

> How far should we go in making things generic? My rule of thumb for this is to repeat yourself at least 3 times before trying to build an abstraction to DRY them up. 3 use cases is obviously not always sufficient inform the design of a good abstraction, but IME: - abstracting at 2 use cases is very often premature and results in leaky/brittle abstractions where the harm from added coupling between fundamentally inc…

>My rule of thumb for this is to repeat yourself at least 3 times before trying to build an abstraction to DRY them up.

Also known as WET (Write Everything Twice).

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

#98
post #67

Earlier quoted context omitted.

I would argue that having a robust type system and some (not too many) end-to-end tests for your software makes unit testing almost completely useless overhead.

If the code is a mess the type system can’t help, it is part of the mess. End to end tests are really slow, but if you can get them into the 300-1600 tests per second range then i have no beef. I value tests but I seriously grudge waiting for tests.

If the code is that bad, unit tests aren't going to help you. Messy spaghetti code with massive structural issues will break every unit test every time you change anything in the code, in ways that make no sense and provide you with little useful information. You will fix things faster if you just let the tests fail, fix the code and then rewrite the tests. Which makes the unit tests useless.

Also, have you ever seen a project where the code is a mess but the unit tests are perfect? Even if somehow you could write unit tests that would cover for super bad code (which you can't), it is extremely unlikely that your unit tests would be that amazing.

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

#99
post #67
post #32

Earlier quoted context omitted.

Unit tests are absolutely fantastic during refactoring. I once had to rewrite a piece of code where nobody really knew what it did or what it had to do, and the original author just made some guesses about the intention. I started out by writing unit tests for everything, which became my handhold and documentation for what the system originally did. Then I started reorganising the code into a more structured and more…

I would argue that having a robust type system and some (not too many) end-to-end tests for your software makes unit testing almost completely useless overhead.

This means you test your code manually ? I can't imagine not doing TDD, except during extremely early prototyping before knowing if a code will be useful at all.

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

#100
post #32

Earlier quoted context omitted.

Also: have a framework in place, which supports worry-free refactoring. Comprehensive Unit/Integration tests, a robust type-system, pick whatever suits your style. It's a lot easier to refactor stuff when you don't have to worry about breaking something hard to debug with a big code change.

Unit tests are absolutely fantastic during refactoring. I once had to rewrite a piece of code where nobody really knew what it did or what it had to do, and the original author just made some guesses about the intention. I started out by writing unit tests for everything, which became my handhold and documentation for what the system originally did. Then I started reorganising the code into a more structured and more…

"Fantastic" or "The only way" ? has anyone seen a case of refactoring without test end well ? I haven't.

Seems like that "refactoring untested code" would be a well established recipe for disaster.

Post reply on HN