Application Modernization - Part 1: Domain-Driven Design (DDD) to break the business domain

Application Modernization - Part 1: Domain-Driven Design (DDD) to break the business domain

Business enterprise platforms are complex systems with an ecosystem of many internal and external integrations and dependencies. Modernizing these kinds of applications requires a divide and conquer approach, with a transformation program composed of multiple steps, ideally performed in an Agile way.  But, how to proceed? Let's see how Domain-Driven Design (DDD) addresses this.

Splitting the domain into Bounded Contexts

DDD uses Bounded Contexts as a way to split the overall system into subdomains. It's important to note that each Bounded Context has also its own ubiquitous language that defines the concepts of that domain.  This is important since Business Organizations and IT Systems are linked together in their evolution by Conways's law, so any effort to decompose the business domain should be based also on business criteria, and in different subdomains, concepts and entities might have their own specific and precise meaning.

Since a map is always a useful tool to understand the big picture (see also this article), let's see how the relationship between the Bounded Context could be visualized with a Context Map, such as this one that I have drawn inspired by Travel & Transportation domain experience.

Travel & Transportation Context Map
Travel & Transportation Context Map

In this example, we see that the same concept might appear in more than one Bounded Context. Is this a problem?

No, this is on purpose, since in different contexts the same entity is used and characterized in its own specific way, based on the ubiquitous language of that specific context.

So in the above example, the Customer of the CRM Context is linked but not the same as the Customer of the Sale Context. However, these are linked via IDs, that allow semantic references across different contexts.

What's inside a Bounded Context? Aggregates to define microservices

We have just seen that each Bounded Context has its own Domain entities, which sometimes can be simple, but often are a composite of multiple data in hierarchical (think object classes) or relational (think table) relationships.  How can we organize the domain models of each context?

In DDD the divide and conquer is applied also at this level, grouping together domain data that is handled together into Aggregates. An aggregate is updated atomically and enforces rules of consistency dependent on the Business domain.

Multiple aggregates can refer to a single domain concept, and these can be related via IDs. For example, in a further drill down of the Context Map shown above, focusing CRM Context we see the main Customer aggregate but also other aggregates related to Customer via the ID, such as:

  • PreferredDestinations
  • PreferredTravellers
  • PaymentOptions

Each of these can be updated independently of the others, and are good candidates for a possible implementation as separate microservices, even in the same domain.

Next step: transactionality

We have used two main DDD tools for Domain decomposition:

  • Bounded Contexts
  • Aggregates

These are the key to defining the application modernization journey since they drive the microservice solution. Specifically, a microservice cannot be bigger than a bounded context or smaller than an aggregate.

This also provides key elements for managing the transactions of the solution, with each Aggregate as the natural place for using database transaction facilities to ensure their atomic updates, with eventual consistency used between different Bounded Contexts.

But for this, I'll go more in-depth in Part II - "Transaction and Events microservices".