|
|
|
|
|
by cjfd
2184 days ago
|
|
You should immediately stop designing for future use cases. Use TDD and only write only just enough code for the currently known required functionality. When you get to know more required functionality the tests protect you from breaking existing functionality and you can extend your code to support the new use cases as well. At this point you should make your code just generic enough to support all known use cases without code duplication or too much boilerplate code. If you can support functionality in more than one way you can decide what way to choose based on what you expect in the future. But choosing the most simple solution trumps attempting to future proof your code. It turns out that predicting the future is quite hard and there will be new feature requests that nobody had foreseen and code that has been made as generic as possible will not handle this well. Spiderman says that with great power comes great responsibility. The converse also holds true. With great responsibility comes great power. You cannot just pick the easy part of TDD, be irresponsible and expect to have any power. The less easy parts of writing a test for every use case and of refactoring all the time make the practice of not attempting to guess the future possible. If you leave out the prerequisites the end result will not be so very pleasant. |
|
It implies:
- Behaviour can and should be compartmentalised
- Certain types of efficiency are ignorable
- Data structures are better off being relatively simple
- Behaviour is able to be understood before the system emerges
- The system doesn't fundamentally need a lot of mutable state
- Dispersing functionality across small, atomic functions (that obscure sequential flow and state mutation) is good for the code
- It is easy to extract the functionality of this system into pure functions
- A high-level veiw of the system is unnecessary (!)
- In this system, most bugs will come from small units, not interactions between units
- Behaviour of units is likely to be relatively unchanging
- Refactoring primarily happens between interfaces, not to them
- Test rigging is cheap and easy at every level of abstraction, or at least that it's better to contort your system into a structure where that's true
None of these things are a given.