In this post, I’d like to introduce you to the Universal Architecture idea described by J.B. Rainsberger in the podcast Unit Testability and the Universal Architecture.
Everyone wants to deliver software that works and delivers value to our customers. That’s a fact!
Everyone wants our software to be easy to change and maintain. That’s obvious!
Unfortunately, we all know this is very hard to achieve. We are all aware of the pain and costs of impenetrable code.
Over the past few years, after spending my time inside very difficult code bases, I keep asking myself the following question:
- How can we prevent code becoming an intricate mess over time? or, framed more positively….
- How can we write working software that is easy to change and maintain over a long period of time?
Unfortunately I don’t have a definitive answer to this question. The Agile development process was born as an answer and radically changed our industry. However, we’re still bad at writing working and maintainable software. We still deliver software that is full of bugs. Developers still write software that is to hard to understand and maintain. There are many ideas and techniques that can significantly reduce the risk of ending up in a mess. Most of these ideas come from Extreme Programming, and more recently, the Software Craftsmanship community.
The Universal Architecture call to action is simple yet extremely powerful:
Maximise the amount of code you can fully run in memory, make it simple and unit test it aggressively!
If you do it, you will end up in a three zones architecture:
- The Happy Zone
- The Demilitarised Zone
- The Outside World
The Happy Zone
This zone is where the vast majority of your code should live. It includes your domain and application logic. Everything is good here. The code is simple, it does not depend on external frameworks and libraries. It runs super fast and fully in memory.
Unit tests run quickly and provide 100% code coverage. They can provide an immediate feedback loop and safety net during development. They help finding mistakes sooner rather then later.
Developers can be extremely productive in this zone.
In this zone you define clean and narrow interfaces to access services from the external world. The interfaces are closer to your business. They are designed the way you want them and you can change them. You never mock external libraries directly but you create mocks of these interfaces to use in the unit tests (Guideline: Don’t mock types you don’t own)
You have total design freedom to make this code the simplest and cleanest possible code that works.
The Demilitarised Zone
The Demilitarised Zone contains all the code that integrates with the outside world. It offers services to the Happy Zone via well designed interfaces.
The code can run slowly based on how it interacts with the external world.
Here is the only place where you should write integration tests. Watch Integration Tests are a Scam.
These tests have nothing to do with your application!
Effectively these are characterisation tests (also called learning tests). You create these tests to describe the behaviour of third party libraries you rely on. They do not represent any of your application use cases. They exist to document the behaviour of third party libraries. They provide a way to validate your assumptions on how the external world works and more importantly they helps you to catch regressions when the external libraries get updated. These tests don’t need to run all the time in your build server but you definitely want to run them when you upgrade a library or you need to start using it in a new way.
The code in the Demilitarised Zone can potentially be moved into libraries shared across products.
The Outside World
Here is where all the external frameworks and libraries live. It includes the file system, the registry, the database, the network and so on.
The rules of the game
There are few important rules to follow:
- Arrows never go from the Happy Zone out.
The Happy Zone does not depend on the external world directly. If you feel you need to do it, this is a sign that there is a missing abstraction.
- Code should flow from the Demilitarised Zone into the Happy Zone
The Demilitarised Zone should not attract logic. All the logic should flow into the Happy Zone. The Demilitarised Zone contains the minimum amount of code required to invoke the external libraries, everything else can run in memory and should live in the Happy Zone.
- Follow the Four Rules of Simple Design (by Kent Beck)
J.B. summarise the rules in remove duplication + improve names. Following these two simple rules can significantly improve your design and make your code simpler and easier to understand.
The underling idea of the Universal Architecture is pretty powerful and offers a very clear and simple guideline for developers to follow. If more code can run in memory, more code can be easily tested. The feedback loop is short and developers can write high quality code productively. If the majority of the code is in the Happy Zone, we have a greater ability to change and maintain the software in the long term.
I’ve found following the IDesign Architect Master Class very useful and informative to be able to achieve a design that could: deliver on time, on budget and with zero defects. The master class tells you how to get the mindset, what to look for in the requirements and how to set up your project accordingly to deliver such a system. I can recommend this to anyone who takes his profession in software engineering serious.
Did you attend the master class? Thanks for sharing. Seems like an interesting class. I think this is the link to it http://www.idesign.net/Training/Architect-Master-Class
Great article, thanks!
IMHO our IDE’s are still a bit behind when it comes to help out with bugs and best implementation.
Integrating AI’s will be the next step like Facebook’s SapFix that detects bugs and suggest a fix for them.
We write so much boilerplate, that there’s no reason for AI not to suggest refactoring to best practices / DI / unit test our code etc…
I agree with you, there are more ways IDE can help. The fact is that programming is hard. AI can’t solve all our problems and hope it won’t so we can keep our jobs 🙂