Design for Change
The world keeps changing, and it’s inevitable people’s needs and preferences will change with it. And to satisfy that change, software must adapt as well.
Start by accepting that change is inevitable. … As a consequence of this, software is never finished, only abandoned. (Charles R. Martin)
So how do we design for change?
Simplicity #
Keep things simple, so you can clearly see and understand the effects of change.
- Make yourself familiar with the tools, the language, and the vocabulary.
- Use good abstractions. Follow the rule of 3 (or 3 to 7).
- Maintain modular components, encapsulated implementation, and clear separation of concerns.
- Be parsimonious with your implementation, remove everything that not essential.
Build Confidence in the Ability to Change #
Make changes have low or no-consequence option (use source control so you can always revert change, build the ability to rollback updates).
Use automation to guarantee repeatability, and minimize human error.
Test before you release.
Have tools to reliably Monitor and Observe the live usage and behavior, so you can identify issues early, and respond proactively.
Maintain knowledge of the product.
When writing code, prioritize for readability. Code is for humans, not machines1.
If you can’t document it as code, document it near the code. Keep documentation of objectives, ideas, design, decisions, tradeoffs, usage samples, etc.
Keep the documentation close to the code, so it’s easy to find, and understand in context. Keep the history (versioning) so it’s easy to understand how things changed over time.
Use a common language, and explain the vocabulary. Follow standards in documentation and code.
Continuous Refactoring #
Refactor the system continuously to keep it current with changing requirements and complexity:
- Tidy up first (and leave code neater than you found it)
- Remove that which is obsolete
- Update design to fit current requirements (don’t just patch existing design)
- Keep up to date with dependencies (infrastructure, tools, libraries, APIs, etc.)
Yes, even if you use LLMs, eventually a human will need to be able to reason about that the code does. ↩︎