In Software Is Never Finished and Code Can Always Be Improved I mentioned that you get to know systems better as they grow:
You get to know a system as you are building it, and, in the process of doing so, realize what fits and what doesn’t. The longer you work on a system, the more you test and stress your early abstractions, the more likely it is that you will find a better abstraction for your system.
What I describe in that post is a sort of uncovering. But an uncovering of what? I like to think of it as the system’s personality. As with a person it is the upbringing that eventually shapes what it will like and dislike and how it will behave when matured.
Systems never stop changing, but the early stages of their development are often the most important to what they will end up doing. A system with a rigid personality will never do more than it does, never be used in new contexts. A flexible system, on the other hand, will lend itself to integration in many different processes.
It is important to remember that you will probably need systems anywhere on the gradient from rigid to flexible. Overengineering for (unnecessary) flexibility is not in any way beneficial.
What kind of system do you need? How do you raise your system so it becomes exactly that? Those are the questions you need to answer.
Thinking in System Personalities is accepting that full systems are never designed in their final form before writing the first code. As the system is being developed, the developers get to know the system, what it is becoming, and learn how to adjust their practices to shape it the way they intend.
The first few steps in development (setting up the project or building the first prototype) are never fatal for the system. Sure, you are setting an example for the future, but most mistakes can probably be corrected, and the system is still small enough that system-wide refactorings are manageable.
When the system starts growing in size and responsibility you need to have figured out how you’re going about building it. You need consistency in testing and an agreement about standards of coding and structure. Sure, visiting grandma and getting a bunch of candy is okay once in a while, but the norm needs to be consistent rules — otherwise the system will grow to be irrational and chaotic.
There is always room for improvement. If you find a slight improvement to how you write tests, this change can be made (for all future tests) even late in the life of the system. But it quickly becomes harder to change the actual personality of it.
Some systems go through midlife crises, suddenly changing dramatically, with refactors left and right, and tests where there weren’t any before. Suddenly it’s off to see the world, buying a motor bike, dressing differently. This doesn’t happen to all systems, but to some it does.
This way of thinking gives me a healthy relationship to the software I’m developing, where I can accept it not being perfect. I hope it will be useful to you too.
You can get notified when I write more by signing up to my newsletter.