This post is a summary, a note to myself about the differences of Subdomains and Bounded contexts. Those terms are often used by Domain-Driven Design practitioners. There was a time when I used to mix them up a little bit. Hope you can find this useful. If you find any inaccuracy, let me know. I am still improving my DDD practice and knowledge.
Let's start with what a subdomain is. Subdomains lay in the problem space. One large problem domain can be split into multiple subdomains. The reason for partitioning a larger domain into smaller subdomains is that it makes it easier to manage complexity, and separate the important parts of the system from the rest of it.
Wait, aren't all parts of the system equally important?
Well, in DDD the subdomains are split into 3 categories:
- Core Domain
- Supportive Subdomain
- Generic Subdomain
The Core Domain is the most important part of the business domain. It's what makes the application worth building in the first place. It's the reason for the application being created from scratch instead of being bought.
What does it mean for us, developers? This is something that makes our business special and unique (in most cases). It's also something that may affect the decision whether the software is developed outside or in-house. Besides that, we should put most of the effort here and craft this part of the system very carefully. Wait, aren't all parts of the system equally important?
The thing worth remembering is the fact that business might change over time, and so might Core Domain. Keep your head open and listen to what people say. After some time spent with the initial Core domain, you might find a new one, that evolved from a supportive subdomain, for example.
The supportive word of the supportive subdomain term means that this part is supporting the Core domain. In other words, the supportive subdomains deliver functions that support proper functioning of the Core domain. Those subdomains are specific for the organisation and it's processes, that's why we cannot buy them. However, the supportive subdomains are a little bit less important than the core domain. This less importance allows us, developers, to put less effort here on the quality.
And don't get me wrong, you shouldn't use all the anti-patterns that you know in the supportive subdomain. The thing is that there are more and less important parts of the problem that the software system will be solving. Hence, it's acceptable to do some compromise here if necessary. For example because of the time pressure or other drivers that exist in your environment.
The Generic Subdomains are important parts of the business processes, however, those are not unique. Because of that, the generic subdomains can be bought. A good example is invoicing, payments, email sending service. If your business isn't dealing with those things (because then it would be core domain), there's a high chance that it would be more pragmatic to buy an out of the box solution and integrate with it. Also, developing a generic subdomain in house is probably not going to bring your business the competitive advantage that the Core domain does. However, if you decide to develop a generic domain in-house, it might over time turn into the core domain. At least according to the theory :D. Or an idea that's sounds great in the beginning might turn into nightmare as well. Think about custom made ORMs...
Bounded Contexts lay in solution space. They help with maintaining the integrity of domain models within certain context, by clearly defining boundaries of model's responsibility in the code. The reason for that is the fact that certain things might have different meanings. For example, customer might be described by it's name, age, username, etc. in one context. In payments context, the same customer might be described just by an identifier and credit card number.
Bounded context has linguistic barriers (yes, language is important, even for us, geeks😄). The language comes from the domain experts and should be reflected in our code representing the domain model. Definitions of terms are clear within given bounded context. Such as mentioned customer might mean two different things in two different contexts. And the thing is... that you have to catch those differences.
How to do that?
What works for me is listening to domain experts and learning their language. I also keep in mind which part of the process they're dealing with or talking about. Or actually I am trying to catch that. Besides that I ask questions if I don't understand something or I am uncertain what they have in their minds during discussions. You need to find your way.
As I mentioned, I try to keep clear boundaries between my bounded contexts. What is also important is the fact that each BC has it's own domain model, that doesn't share any data with other BCs. For example, only one BC would be responsible for customer's credit card number maintanence.
In other words, BCs should be autonomic. The autonomy means that it's possible to make decisions.
Why do I think BCs are important? In few project that I saw there was a problem with the models. Besides being anemic, those models held too much data. The data usually was related to the same word, but in different context of using this word. This leads to the classes that are really hard to change, because changing one thing is often breaking something else. That's because the data is coupled on different levels. Also BCs are closely related to problem subdomains. In my experience, keeping one BC per one problem domain often works very well. The reasoning is that the class has only one reason to change then. That's actually what I consider following SRP. Also, I try to craft the model to do one thing and do it well (and preferably fast 😄).
One model to rule them all doesn't look like a good approach. I experienced that it's better to make 3 or 4 customer classes if needed. Each of it in it's own context. And make it do exactly that small thing that it has to do. Nothing more, nothing less. Maintaining complex system is easier when its split to multiple code models with clear boundaries. With one big(ger) model it is easier to group wrong concepts together.
I found it easier to split work between people. It's much easier to work within BC. Less likely that we'll have to modify the same thing at the same time.
- Subdomains lay in the problem space
- There are 3 categories of subdomains:
- The Core subdomain is the place where most of the modeling time should be invested
- Bounded contexts are the answers, the solution for the problem space
- One entity, such as a Customer, might be represented in multiple Bounded Contexts
- The solution benefits from autonomic BCs
- One model to rule them all might not be the best choice for complex applications (but it might be good for CRUD)