#39 Step Two of Evolutionary Architecture: Focus on Maintainability
If you notice that your system is becoming increasingly difficult to maintain, this is a red flag. You need to address it before it becomes an unmaintainable monster. Don't wait until it is too late.
Keeping things simple is one of the most underrated aspects of software development. I wrote about this recently. If you want your system to last and grow smoothly over time, aim for an architecture that is intentionally boring. Trust me, boring is beautiful here.
At some point, we need to think about other aspect of our system - like how easy it is to maintain. Maintainability is the second step in our evolutionary architecture approach.
When you start simple, your system naturally becomes easier to maintain. You don't have a bunch of external components like cache or data streaming tools to worry about. Fewer moving parts means fewer things can break, which makes maintenance much smoother. Though let's be real - if your code is a spaghetti, even the simplest system will be a headache to maintain ;)
The tricky thing about keeping the system simple is that your early decisions can come back to bite you and your team as the system evolves. Every system faces different growing pains depending on its context.
When certain parts of your code start expanding faster than others, your simple design might not scale well with them. Some modules turn out to be way more complicated than you first thought. Plus, as your organization grows and you want different teams working independently, those early simple choices might actually get in the way, negatively affecting maintainability.
Example? Imagine this scenario: You start with a simple setup - one assembly and four developers. Life is good. When someone needs to change something in a module (represented by a folder in the assembly), the team huddles up, discusses it, and makes it happen. Clean and straightforward.
But then your system grows. Now there are three teams, each owning different modules. And here is where that simple structure starts causing headaches. Every time one team wants to update a third-party package - even for their own module - they have to:
Notify other teams
Wait for them to review and approve
What was once a quick decision now turns into a slow, multi-team coordination flow. Your simple, single-assembly approach has become a bottleneck that is actually making things more complicated, not less. That is a classic example of when simplicity from the past can handcuff you in the present.
Code changes become a real headache too. With three teams of four developers each, you have twelve people all trying to push code into the same assembly throughout the day. That means constant merge conflicts and developers wasting time resolving them instead of building features. What used to be a smooth workflow with a small team turned into a daily battle with Git.
There is no magic solution to these growing pains - you need to find what works best for your situation. In our example above, one approach would be to break each module into its own separate assembly. But this is just one way to go - the key is to choose what makes sense for your specific needs.
How do you spot a maintenance problem? Simple: your team starts feeling the pain. And how do you know you have fixed it? Even simpler: that pain disappears and your team can work smoothly again. No need for complex metrics or fancy formulas here - just good old common sense will tell you everything you need to know.
How do you deal with maintaining the growing system?