If we start building software with domain-driven design (DDD), it can seem to be much work to model everything. Luckily, any domain of reasonable size has sub-domains of lesser importance. However, how do we separate these from the essential concepts? Where do we invest in DDD if resources are limited?
These questions may be answered with the chapters about the distillation of the core domain of Eric Evans’s DDD [Eva04]. This core domain is the part of our application that we want to be of the highest quality as possible. Domain Vision Statement, Highlighted Core, Cohesive Mechanism, Segregated Core, and Abstract Core are concepts that we can use to distill the core domain.
Not every part of a given application is equally important. There are (sub-)domains that are used by many businesses. For example, accounting or project planing are domains that are needed by most companies. These are called supporting domains in DDD.
The core domain, on the other hand, is concerned with the unique selling point of our business. The company values that part of the domain the most. That’s why we want it to be of the highest quality as possible. It is the part that justifies the initial effort that DDD may require.
Last but not least, there are generic (sub)-domains. These parts of our domain are well known and used in many applications. More often than not, there are standard solutions or libraries available that we can use. We don’t even need to develop them ourselves but integrate them as a bounded context.
Domain Vision Statement
The first and easiest option to distill our core domain is to write a Domain Vision Statement. Typically this will be one page with a very high-level definition of the core domain. It should only consist of domain-specific language and not be concerned with technical things like availability.
The domain vision statement can act as a lightning post where team members refer to in the early stages of a project to decide about the placement of artifacts and naming. Alternatively, if there is legacy involved, the domain vision helps to identify the first parts of the domain that we want to attack with refactorings.
The next stage, when distilling the core, could be to highlight it. In a greenfield project, we could write a brief document of some pages that describes core components and their interactions. The text should still be as concise as possible to prevent it from becoming out of sync with the development.
In projects with much formal specification, it could be useful to compile the relevant parts in one place. Highlight the core by pointing to existing specifications that deal with the most valuable concepts.
When highlighting the core, team members can reason and communicate about it. While doing so, the distillation continues, and it becomes clearer what the core is and what we may refactor as sub-domain.
Sometimes when we are refactoring our domain model, a cohesive mechanism emerges. It could be a concept or pattern that is general knowledge in software development like graph operations or something like a rule engine.
The cohesive mechanism should be factored out of the core domain and put into a supporting module. This simplifies the core domain, and most developers can understand the cohesive mechanism or look it up at least.
In contrast to generic sub-domains which subtract a part of the core domain, cohesive mechanisms can be used to encapsulate complex logic. Both patterns leave behind a more coherent and simplified core domain.
When there are multiple concepts entangled within the core domain, we may want to create a segregated core. Inside the core, we focus sharply on the core domain. We refactor all supporting concepts into classes in separated modules.
While it can be beneficial to reduce the size of the core in this way, we should always keep an eye on the dependencies that are needed. If the core module(s) and supporting modules would have to have many dependencies after the refactoring, it may be better if the concepts stay within the core.
Another way to reduce the size of a core could sometimes be to create an abstract core. If there are distinct areas of the core that use a common subset of it, we can refactor those functions into an abstract core. Most dependencies between those areas are located within the core. The specialized sub-domains depend on the abstract core and won’t have dependencies between each other.
Wrap Up / Final Thoughts
The distillation of the core is about focus and cohesion. Focus on the most valuable part of your software and make it cohesive. That way, we can reduce overhead and allocate our resources most efficiently.
Evans didn’t mention it explicitly as far as I know. But I think the core domain is what he refers to with the title of his book about DDD: “Tackling Complexity in the Heart of Software”. Therefore it’s not only for the business essential to focus on the core domain but also for us as software engineers.
[Eva04] Eric Evans: Domain-Driven Design – Tackling Complexity in the Heart of Software (homepage)