Trust me when I tell you that your team’s first instinct will be to build a data service. Please resist the temptation. We’ll talk more about that in a minute.
You’re effort to build services should begin by documenting your business workflow. Not the workflow of one of your applications. We’re talking about the workflow of your business; the processes and decisions you would go through if doing your business manually.
The processes in your business workflow should map fairly well to your core-use-cases. These will be the core-use-cases because your business cannot live without them. You’re software has a lot of use-cases, only a few of them are the core-cannot-live-without use-cases. We want to focus these use-cases. Most of the other use-cases you believe exist will be variations from the core-use-cases.
Sometimes a core-use-cases includes other nearby processes or the flow decisions leading to or exiting from the use-case. You’ll need to decide those boundaries and then document them. This is why the processes in your workflow do not represent your use-cases in a 1:1 fashion.
[Danger] At this point it’s going to be tempting to just make these core-use-cases into services. In fact, it’s fair to say most teams make this mistake. It’s so common that this one mistake accounts for much of what is known as the software crisis. We’re not going to drill down on this any further than to say, “resist the temptation.” Take the next step, which is the hardest step to take.
With our core-use-cases in hand we want to look at the likely areas of volatility surrounding our use-cases. This is a crucial step. Do not skip this step. It’s also the hardest step, requiring the most insight and skill.
To build robust software, our services must be encapsulated within a system designed to protect us from the impact of change. Volatilities are the aspects of the processes likely to change. By identifying the areas of volatility and then making these areas the basis for our design, we will be able to contain the impact of changes. Volatility-based decomposition should be practiced at all levels of your software, but it’s particularly important to get it right at the service/workflow level.
We can consider at least two axis of volatility. Changes that happen at a point in time across different customer types and changes that happen across time for the same customer type. There are other forms of volatility, but those are the primary axis-of-volatility.
We create a list of these volatilities and then we try to group them by their similarity. It is these groupings that should become our services. For example, if our use-cases require multiple data feed and we find that there is volatility around the nature of the feeds (perhaps because there are multiple vendors that supply the feeds via multiple formats), then we might consider having a FeedManagerService to encapsulate this volatility.
The results of our analysis will reveal the volatilities that will be the services within our design. Each service should be crafted to encapsulate at least one, and hopefully several, sources of volatility. This will lead to less rework and higher robustness as things inevitably changes and our volatilities become a reality. Designing this way will help to future proof our design. The goal is to encapsulate an entire volatility within one component/service. When a change is realized it should be fully contained within this one component/service.
We want to end up with just a few services that encapsulate all of our areas of volatility. Each of our core-use-cases should naturally find a home within one of our services. If not, then there is still more analysis needed. The important thing is that the system be designed around areas of volatility. A system designed directly from our list of processes will suffer from functional decomposition.
A system designed using functional decomposition (taking the list of processes and just making them services or methods), and ignoring the volatilities, will mean that each time one of our volatilities becomes a reality our system will require change. But it’s actually worse than that. Because our system will have been designed around the processes, a change to one process is likely to have ripple effects, often into many of the other processes, require the changing of many parts of our system. Designing this way we will have exposed our system to the maximum amount of risk from the maximum number of change types. We can do better. So we use the areas of likely volatility as our design guide, not the processes themselves.