It's not fun to say "no" but without saying "no" there is no control we can exert over our domain landscape. Boundaries are the DDD way of including or excluding something in a context.
While the ubiquitous language might be the most pervasive and influential tool in the strategic DDD toolbox, I'd say that the defining of Bounded Contexts remains the most powerful tool. Language makes us define the concepts in play, as well as what (and how) they represent something. Setting boundaries on contexts, on the other hand, carve out the landscape, pointing out where responsibilities lay.
Oh, what the Bounded Contexts are?
[...] A Bounded Context is a semantic contextual boundary. This means that within the boundary each component of the software model has a specific meaning and does specific things. The components inside a Bounded Context are context-specific and semantically motivated.— Domain Driven Design Distilled (Vernon 2016, p. 11-12)
We use this construct to logically discuss and model our expectations on a given part of the overall problem space. This Bounded Context is then manifested, through programming, into a realized vision of the model. That's the Circle of Life, in DDD terms.
I will adapt and echo some of the great points made in https://learn.microsoft.com/en-us/azure/architecture/microservices/model/microservice-boundaries and in Domain-Driven Design Distilled.
Segregate Bounded Contexts and any work in a meaningful way. Conventionally this is with one code repository for each team and Bounded Context. If it's not clear yet, often one Bounded Context translates into one technical solution.
A Bounded Context is always designed from the actual business reality at hand. However, as long as you can meaningfully and accurately decompose parts in their own Bounded Contexts, you are free to do so.
Don't mix up domains, domain languages, or other semantics across multiple divergent needs in the same Bounded Context.
You do not care about anything outside the Bounded Context, only if necessary about any integrations.
An Aggregate, as we will see, roughly equates to what is typically called leading data. An Aggregate is the core of most Bounded Contexts. If you cannot decompose the Aggregate into less than its cohesive entirety, then you have found the true boundaries of the Aggregate.
Consequently, services are completely independent of other services and Aggregates and whatnot. All of the required data and behavior are colocated in the Bounded Context, on the Aggregate. Therefore we can always "trust" the way that data is handled, updated, and modified over time. You do not "split the responsibility" with anyone else.
I will now step through some of the iterations I went through to come to terms with the overall modeling of the Get-A-Room application and somewhat improvise that experience to give you a sense of what it might look like.
Consider using some good templates if you are so inclined:
It was clear early on that there are multiple solutions, or Bounded Contexts, in play in the application/domain. Looking at the overall requirements I could see that analytics and security were completely separate and that the reservation part might be better colocated together. That wasn't necessarily an immediate "score" in my mind but given that their nature of them is intertwined I decided to put them together.
Bounded Contexts established.
This should not be too controversial, I think.
One confusion that Evans sometimes notices in teams is differentiating between bounded contexts and subdomains. In an ideal world, they coincide, but in reality, they are often misaligned. He uses an example of a bank structured around cash accounts and credit cards. These two subdomains in the banking domain are also bounded contexts. After reorganizing the business around business accounts and personal accounts, there are now two other subdomains, but the bounded contexts stay the same, which means they are now misaligned with the new subdomains. This often results in two teams having to work in the same bounded contexts with an increased risk of ending up with a big ball of mud.
As per DDD best practices, we want to have as close alignment as possible between subdomains and Bounded Contexts. Still, because we put Reservation and Display in the same (core) subdomain, that one gets a little fatter. Once again, this is acceptable given that Display will serve as essentially just a read-replica of the Reservation context.
Fitting Bounded Contexts into Subdomains.
With the addition of subdomains, we have now clarified their relative importance and set the maximum outer boundaries.
- Reservation is the core domain, which we will invest more heavily in
- Security is a supporting subdomain, and we accept that we need to do our own work here for it to be useful in our application
- Analytics is ideally shipped to a commercial-off-the-shelf product or something similar; in Get-A-Room we set up a bare minimum custom implementation
For some informative light reading on this subject, see https://medium.com/ingeniouslysimple/context-mapping-in-domain-driven-design-9063465d2eb8
In terms of integrations, it should be clear that these somehow need to interact with each other. But how?
- The Reservation context has a
Customer-Supplier relationshipwith Display, meaning it supplies data in a way that is easy to represent. In this exact case, it's very close to the original format as it's not that complex.
- Reservation as a whole has a
Conformist relationshipwith the Analytics context. This entails that the Analytics service/context dictates how they want data integrated.
- The Reservation context and the VerificationCode context have a
Published language relationshipwhich is a somewhat convoluted way of expressing that the security side will present a documented API to use.
Expressing the Relationships in a complete Context Map.
Having done all of this modeling, we are well on our way to understanding the domain, how things fit together, how they interact, and being super-clear on which services are worthy of more investment and care.