In the previous part, we discussed on some guidelines in doing DDD by having our strategic design as the initial phase in order to discover our domain, sub-domains, and their bounded-contexts. This phase should be initiated through a brainstorming and/or event-storming session with all related domain experts. The most important thing is that we should avoid a state-driven mindset (data-centric view) when designing our domain model. As contrary, it should be process-driven (behavior-centric) instead.
Table of Contents
- DDD Part 1 Introduction
- DDD Part 2, Context Map → You are here
- DDD Part 3, DDD Building Blocks
- DDD Part 4, DDD and Hexagonal Architecture
- DDD Part 5, DDD and Microservices
- DDD Part 6, Code Implementation
- DDD Part 7, ES and CQRS — DDD’s best part (coming soon)
Additionally, we also know that a domain can be structured in sub-domains, and each sub-domain actually can contain further sub-domains with communication happen among them.
Furthermore, sub-domains can be divided into 3 different types as follow:
- Core Domain
– Core business, this is where our Organization is earning its money.
– High degree of differentiation to competitors.
– Should be owned by an In-house development team.
- Supporting Sub-domain
– Supporting functionality that is not available as COTS (Commercial / Custom Off The Shelf) Software, i.e. software or hardware products that are ready-made and available for sale to public such as SaaS. Usually we bought and customize this COTS to match our specific needs.
– External-development, yet In-house teams should be in the lead.
- Generic Sub-domain
– Suitable for Outsourcing.
As mentioned earlier, domain and/or sub-domains can communicate to each other. However, every business domain consists of a bunch of bounded-contexts. Each bounded-context contains models and perhaps other contexts as well. The bounded-context is also a boundary for the meaning of a given model. With that being said, there’s a possibility of a model to be scattered / replicated in more than one different context. This sounds like a violation of the DRY principle. Nevertheless, practically speaking, those replicated models would look different in each of their context.
For example, Customer model in the context of Shipping Service will be different with the one defined in the context of payment service. For shipping purpose, we don’t need customer’s payment information, and vice versa.
The bounded-context cannot work alone, hence it won’t show us how the system works until we draw a line between every contexts. Therefore, the next thing to do is having our Context-Map as a way to describe the connection between our models / contexts.
There are several context-map patterns which strongly depends on various circumstances as given below:
Different team share a subset of the domain model, either code and maybe the database (or perhaps both). Thus, teams involved must collaborate. Any changes in a kernel model must be done only in consultation with the other team.
- Customer / Supplier
a.k.a. Consumer-Driven Contract relationship is where the downstream context defines the contract that they want the upstream context to provide. Both two domains can still evolve independently as long as the upstream context fulfills its obligations under the contract. Most of the time, the downstream team (Consumer / Customer) will have the veto rights, hence there’s no translation needed on this particular pattern.
Almost similar like Customer-Supplier pattern, except for the downstream is strictly follow models provided by the upstream team (downstreams are forced to consume what they get). There’s no veto rights and no translation models. Hence, if the upstream model is a mess, it will propagate it to the downstream model.
- Anti-Corruption Layer
From the Customer-Supplier pattern, we add a layer that isolates a client’s model from another system’s model through some kind-of translation mechanism (which usually is implemented as an adapter).
- Separate Ways
There’s no connection at all between the two contexts as depicted above. This allows teams to find their own solutions in their domain.
- Open-Host Service
In this pattern, each bounded-context offers predefined set of services that expose functionality for other systems and give the downstream a set of choices to implement their own integration.
For instance, an Order Management System provides different protocol services such as gRPC, REST API, SOAP-WS, CORBA, etc to create / post a new order. Subsequently, other services can choose which one to implement from those set of choices.
- Published Language
Almost similar like Open-Host Service. However, it defines a common language between bounded-contexts.
Where do Context-Maps help ?
A Context-Map helps to identify governance issues between applications and teams.
A Context-Map also helps us in seeing how teams communicate and play “politics”.
- Bad Models
By using Context-Map, we can get a clear view on where and how bad models propagate through application landscapes.
A Context-Map can lead us to future transformations since it gives us an in-depth understanding in the integration aspects and sub-domain / context.
“Strategic Design” is the first (initial) phase of Domain Driven Design which made up of Bounded-Context. Context-Maps help us to see how various bounded-contexts are interacting / communicate with each other.
Read the next part here.