Welcome to another Sunday Blog on System Design. This Sunday, we will look into the principles of doing a volatility-based decomposition. Once we are done understanding and memorizing the rules, I will start transferring the framework for doing System Design as explained by Juval Löwy in his book Righting Software.
As I’ve already stated: we are going to learn the rules, follow the rules, and once you are an expert — bend the rules.
Let’s keep track of what we’ve learned so far, to keep things at our fingertips even if you haven’t read the previous article:
- A good system design speaks (how components interact)
- Avoid functional decomposition (what we were doing in universities)
- The client should not be the core business. Let the client be the client — not the system
- Reduce coupling between services as much as possible
- Decompose based on volatility — list the areas of volatility
- There is rarely a one-to-one mapping between a volatility area and a component
- Symmetry is a good sign of good design
Once we start understanding and implementing the framework in the next article, we will verify the design using the memorized rules.
Listing the Volatility — Tools to Identify Them
Once a project starts, the requirements themselves are communicated in terms of functionalities — "the system should do so and so." It's the role of the architect to analyze the requirements and list the volatilities.
Another way to figure out the volatility is through customer interviews.
Volatile vs Variable
Volatility refers to changes that affect several components in the system, while variability refers to changes that can be handled in code using if-else
. So it’s necessary to understand the difference between volatility and variability.
Axes of Volatility: Technique to Identify Volatility
One axis of change is over time for existing customers — how their requirements evolve. The business or expectations of the software’s consumer may shift over time.
The second axis of change occurs at the same time across different customers. Imagine freezing time and analyzing the second axis: Are all customers using the application in exactly the same way? What are the different use cases, and how can they be accommodated?
If something does not map to either axis of volatility, you should not encapsulate it at all — there should be no building block in your system to represent it. Creating such a block likely indicates functional decomposition.
These axes can serve as references during customer interviews to ask better questions, list down requirements, and later analyze volatility.
As you can see in the figure below, your design should follow a lifecycle while refactoring. Design iteratively like this:
In Figure A, you come up with one component — but that’s not good. Then, by analyzing along the axes of volatility, you realize that some things can be encapsulated into separate components. The result is Figure B. You keep factoring the design until all volatilities are encapsulated.
Another way to find volatility is by examining how competitors have designed their systems. That can reveal alternative approaches that can be explored across both axes.
Axes Are Independent
When we say the axes of volatility are independent, we mean the changes we consider using Axis 1 cannot be the same changes we calculate using Axis 2. If they are, it may be a case of functional decomposition.
Solutions Masquerading as Requirements
It is very common for an architect or developer to map a requirement from the spec directly into a component. We should always check whether that requirement is actually a solution masquerading as a requirement.
For example, assume “Cooking” is listed as a requirement in the design spec for a house. Isn’t it actually masquerading for “Feeding”? There are several alternatives to cooking — ordering food, or going out for dinner.
It’s exceedingly common for customers to suggest solutions as if they were requirements. Imagine you create a “Cooking” component, and later the customer demands a new “Pizza” component. Instead, having a “Feeding” component that encapsulates cooking, ordering pizza, or going out is more flexible and future-proof.
Volatility Listing
So before decomposing the system into components, the first step should be listing the volatilities after gathering requirements.
To do so, one should think along both the independent axes. Then, see what “solutions” are masquerading as requirements.
Conclusion
We have now seen the principles of volatility-based decomposition. Let’s update the rules we’ll follow when designing real systems in future blogs:
- A good system design speaks (how components interact)
- Avoid functional decomposition (what we were doing in universities)
- The client should not be the core business. Let the client be the client — not the system
- Reduce coupling between services as much as possible
- Decompose based on volatility — list the areas of volatility
- There is rarely a one-to-one mapping between a volatility area and a component
- Symmetry is a good sign of good design
- The required behavior should be accomplished by the interaction between various encapsulated areas of volatility
List the requirements, then identify the volatilities using both axes:
— What can change for existing customers over time?
— Keeping time constant, what differs across customers?
(Remember: these axes are independent.)Verify whether a solution/component is masquerading as a requirement
Verify it is not variability. A volatility is not which can be handled with if-else. Its variability.
In the next article next Sunday, we will start discussing a framework to actually do system design. Stay tuned!
Here are the links to previous articles in case you missed them. Its highly recommended to read the 4th one in the list which is about practical example of listing the volatility.
Top comments (1)
I have been following your weekly system design series. Good stuff! Keep going!