Software Design: Changeability

There are a lot of patterns & principles of software design out there. One can count, GoF Design Patterns, S.O.L.I.D., YAGNI etc…
You may read articles, describing, how the code should be readable, simple and testable. Some of these principles are in conflict with the others. What to do then? What to choose from?
This is where “programming is an art” statement comes from. You need to balance the conflicting requirements.
But is there a single rule you should consult, that will help you to make the final decision?

I think, the rule is that your code should be changeable.

We are trying to hit the moving target when building software. If you are building something for a client, the client usually doesn’t know in detail what he needs until he sees it.
If you are working on a product, you never know in advance how the market will react on a release or a feature.
Everything changes rapidly: UX team will change their mind as soon as they see the design in action, software platforms release new APIs every year, web standards are evolving…
You should be ready for it.

Moreover, most of the software design (or architecture) principles you are heard of have the changeability at the very core.

Making the code testable means making it easier to change. Why do we need unit tests in the first place? Why do we need test automation? To be more confident that the code works after the changes we made. If a code never changes, there is no point to write any unittests for it. It is way faster and simpler to test it manually.

Making the code readable means making it easier to change. There is no point to design the code in a readable way if nobody will read it. When do we want to read and understand the code? In the vast majority of cases it is when we want to change it.
(Yes, if you are building an API, especially a public one, you should also think about how easy is it to understand the code. But usually these concepts come together).

Using the principles like DRY or YAGNI means making it easier to change. It is much easier to change the code, when the chages are incapsulated in a single place (DRY) and there is no unused code “for a future use” (YAGNI). It way easier to change the code when object does one thing (SRP).
Understanding what technologies to use and when improves changeability as well (like hybrid apps: here or there).

Changeability matters.
But there is one more, very important statement to make.

I have some bad news for you.
You can’t be prepared to all the possible changes.
You can’t structure the code in the way that all the changes in the world are easy.
To make matters worse, it is so easy to make the code really hard to change trying to make it too flexible.

So some changes will be hard and painful to make. But it is ok.

Good news: not all the changes in the world will occur with your code. Some changes are by a long shot more probable than the others.

As you finish designing your code (on a paper, in your head or in a software tool), don’t rush to implement it immediately. Think a little bit. Think about what changes are possible. Write a list. Sort it by how probable the changes are.

Then take look back at your design. Does it handle the most probable changes well? It is so easy to make the code flexible in a way that nobody needs. And it is so easy to forget about the most probable changes to your codebase.

Optimise your software design to handle the most probable changes that will happen to your code.

Do this while implementing a feature or while making a refactoring. Change your code in a way, making it more flexible, but don’t forget think about what changes you are optimising for.

PS: There are some related links:
Agile Architecture” by M. Fowler
Architecture without Architects” by Erik Dörnenburg