Architectural Mantra
- Mariusz Sieraczkiewicz
- Software architecture , Project management
- October 17, 2013
Table of Contents
Those who attended JDD 2013 could see it live. For those who weren’t there or missed it, below you will find a presentation on the Architectural Mantra along with an extensive article. Set aside some time for this.
We often repeat that we don’t have time. There’s no time for unit testing because our estimates are cut in half. There’s no time for refactoring because our project manager doesn’t agree. There’s no time for code reviews because… there simply isn’t time. It’s that simple.
What Is Happening with Our Time?
So what happens to our time? Where does it go? Here is what often happens in our projects — a few stories.
A new person joins the team. They are often faced with a stack of documents to sign — company regulations to follow. They receive various resources from the organization — an account in the HR system, login to the repository, access to servers, and the internal intranet. It all looks perfect. The situation worsens when it comes to information about the system they are supposed to develop. The newcomer receives printed and assembled documentation from various sources, consisting of 500 pages. Not entirely up-to-date, inconsistent, and incomprehensible. And they have to manage. Instead of getting an overview of how the system works within a week, they spend three or four months navigating through the “big ball of mud.” Other team members often don’t have time to introduce them to the system thoroughly. Time is lost here.
Another story — conducting a code review. You find a few shortcomings — here a name needs improvement, there it’s worth separating a factory, and suddenly you come across something strange. It processes JSON in the service. Strange, because it shouldn’t be done in the service. The author of this masterpiece shows you several places where the same thing was done, and they copied the concept from there. And now, this has to be undone. Time is lost here.
Yet another story — you’re about to fix a bug. After a moment of reading the code, your inner dialogue goes like this: “Oh fu*k… What the heck is this? Jesus… Here? XML? What the… Manager?”. And so it goes on for half an hour… or more before you begin working with the code. If this can be called work. Time is lost here.
These are just examples. Hundreds of such situations occur every day. Seconds, minutes, and hours slip away.
Seemingly Simple Question
Conduct a simple test with your team. Ask: what are the building blocks of the system we are writing, and what are their responsibilities (i.e., what can and can’t be done in a given block)? And check if everyone gives the same answer. We did this many times, and we received responses that always varied slightly. Sometimes they differed significantly, sometimes by a few percent. If these few percent differences scale with the number of people and the size of the system, the discrepancies become significant. This way, the architecture starts to erode, small deviations from the rules arise, and even a perfectly designed architecture must fall in such circumstances. The more time passes, the greater the consequences.
Test yourself - answer a few questions that will allow you to assess how well architectural knowledge is disseminated:
• How long does it take to onboard a new person into the project?
• What tools do they have at their disposal? How do they do it, and who pays for it?
• How do you ensure that people in your team, when talking about solutions, are talking about the same thing?
• Based on what can you determine that everyone writing code knows exactly what should be in a given block?
Where does this come from? Leaders shape the architectural image (e.g., technical lead, designer, architect, some team members — depending on the adopted structure). They know how it should be done. On the flip side, being a leader often makes you the person who stands out — you particularly care, you continuously learn, attend conferences, read new books. Not everyone is like that. Not everyone grasps what the architecture of a given system entails at once. That was, is, and will be. And this must be accepted. What can be done is increase the likelihood that despite these odds, everyone will understand the architecture the same way.
What is an Architectural Mantra?
Imagine this goal: At three in the morning, everyone on the team can, without hesitation, state the components that make up the system and their responsibilities. And everyone answers the same. Ambitious? Very. And that’s the point. This needs to be worked on. It might not happen immediately, but with a bit of effort and time, you can get closer to this ideal.
The Architectural Mantra is here to help us achieve this goal. It consists of three components:
- Visualization of building blocks
- Definition of responsibilities
- Driving the process
Visualize
Draw the blocks that make up the system. It can be UML, a hand-drawn sketch, something understandable for the team. Place it somewhere visible, like on a wall, so that it can be referred to and discussed at any moment. Ensure its easy accessibility.
Sometimes it may seem that since we use Domain-Driven Design (DDD), everything is obvious. Nothing could be further from the truth. It is particularly crucial to define the Mantra because architectural approaches are practically never applied by the book; they are modified in some way, and these differences need to be articulated. Below you will find sample drawings — one based on DDD and the other on classic layered architecture. These are just examples. The key is that this drawing be unique to your system.
If your architecture uses the Domain Model pattern — it’s worth visualizing domain classes. If your system communicates with many other systems — it’s worth visualizing connections with other systems to easily track consequences of interactions within the system. These drawings should be the basis for communication — the place where discussions on solutions occur.
Define
Once the architectural elements are drawn, the next step is determining their responsibilities:
• the role they play in the system,
• what operations should be performed,
• what operations should not be performed.
Here are some examples of responsibilities:
Value Object
• Groups data belonging to a certain whole
• Is not stored permanently
• Allows naming a specific domain entity
• Is not unique
• PhoneNumber, PostalCode,
• Implemented based on the Immutable pattern
• . . .
Entity
• An object that must be unique
• Possesses business data and behavior
• Is permanently stored
• The uniqueness of the object depends on the specific context and domain
• . . .
Repository
• Marks the layer for persistent data storage
• Abstracts from the specific method of persistence
• Maintains a collection interface
• . . .
Application Service
• Fits within the application layer
• Performs processing determined by use cases (steps)
• . . .
What should happen — example:
Controller
• Receives a request.
• Performs complex validation.
• Assembles data for service invocation.
• Calls the service.
• Packages the result in JSON.
• Determines the next view.
What should not happen — example:
Controller
• Simple validation (as this purpose is served by the web framework).
• Complex JSON processing (JSON should not come from the service).
• Domain logic, e.g., deciding based on data whether an order should be executed.
These definitions should be as little bookish as possible and as much drawn from what happens in the project. It’s particularly important to note what should not be done in a given building block. This is invaluable information on often-made mistakes. This is the part of the mantra that is most alive.
Drive
This is the part of the Mantra most often forgotten. It’s to this part we owe the name “Mantra.” For architecture to live in the minds of team members, to develop, it must be constantly talked about; something must always be happening around it. This is often forgotten — we think it’s enough to create it, and the rest will happen on its own. Unfortunately, it doesn’t work that way. We need to fuel the fire; we need to act. There must be action on at least several fronts.
1. Define how it is and how it should be
Engage the whole team or key people to define the main elements of the Mantra according to the first two points. Distinguish two states of affairs: how it is and how it should be. It often happens that a significant part of people knows well how it should be, and yet architectural assumptions are not implemented.
2. Disseminate
Call a meeting and discuss the Mantra. Set when it applies. Organize the visibility of the Mantra in physical form (drawings on flipcharts) or electronic form for large teams. If necessary, send out informational emails. Let it be an event.
3. Monitor — code reviews, Definition of Done
If you use Definition of Done, add as a verification point whether the solution complies with the Mantra. Similarly, for code reviews — let it be one of the checked elements.
4. Conduct retrospectives
Conduct regular meetings where the team discusses the extent to which the Mantra is implemented and whether it is satisfactory. If not, what needs to be changed. Let these retrospectives be dedicated solely to architecture (design).
5. Modify
The mantra is a living entity. It must evolve. Especially the section “What should not be done.” It is based on experience. The previously mentioned retrospective is also a place to ask: is the current form of architecture sufficient? Maybe a significant change is needed? Perhaps for a selected part of the system, a different solution (e.g., state machine or separate model) should be introduced.
All this must happen. Who monitors this? The architecture leader or System Owner — the person responsible for the consistency of applied solutions.
Legacy
How should the Mantra look in code that has a long development history? It often happens that the first lines of the system were written in C, then in C++, followed by Java, and then an ESB bus was added. Each of these approaches caused different techniques to be used to solve similar problems. Then, there will be many different solutions in the system. Often there is no project agreement on how it should ultimately look, what we do in module X, where C++ practices dominate, and what we do in module Y, where plenty of code resembles C. In such cases, we deal with several Mantras, different for various parts of the system. Defining them will eliminate the question - how should it be done in this place, the same way we did it last time?
Summary
Since it’s so uncomplicated, why isn’t it happening? There are several reasons. First, it often seems, as we already mentioned, that if we use a certain approach (e.g., Domain-Driven Design), everything is clear. Nothing could be further from the truth; especially then, we need to ensure that everyone on the team understands the architecture in the same way. Second, there’s often a silent expectation that team members will absorb knowledge about the system from the code. It might happen, but it will take many months, if not years. Who has time for that? Who will pay for that? Third, leaders often forget that the architectural vision needs to be spread. They think if they have it in their heads, the rest of the team will somehow assimilate this vision, spontaneously. A bit of naive expectation.
So there’s nothing left but to get to work:
- visualize the elements of the architecture,
- define responsibilities,
- drive the process.
(Text translated and moved from original old blog automatically by AI. May contain inaccuracies.)