Domains, Sub-Domains and Bounded Contexts: Explained with example from industry


The Domain Driven Design (DDD) book and community use the language of Domains and Bounded Contexts. Often there is confusion around what is a Domain, Sub-Domain, Bounded Context and how do we tell the difference between one or other when we are in the trenches.

This confusion can lead to poor design where our domain or bounded context is not reflecting reality and the software we then build off of it uses a bad model or shows signs of tight-coupling leading to very chatty services between contexts. In this post we pick the example of Insurance Domain and explore some heuristics for determining domains, bounded-contexts before we build our domain APIs and Events

Domain

The wikipedia definition of a domain

Our definition of a domain is in the context of software engineering. In this context, our domain example starts out within a specific industry – Insurance, Banking, Education etc because our software is specific to the industry domain

Industries and Domains

Looking deeper into an industry vertical (domain) at the next level we can have domains by subject areas or line-of-businesses, which one do we pick?

Heuristic 1: Follow the funding model

If we follow the funding model then business domains make sense at the highest level (e.g LifeInsurance, Vehicle Insurance) vs a functional domain that supports the capability (e.g. Claim, Policy, Document etc). We can then think of the child domains as business oriented functional domains that help realise business capabilities (e.g Life Insurance – Claim vs Motor Insurance – Claim vs Vehicle Insurance – Claim)

Heuristic 2: Orient domains to business capabilities

Child domains such as Claim, Policy, Document within Vehicle, Home, Life business domains

Notice some domains are core to your business, i.e. they hold the secret-sauce that brings in the revenue while the other domains are supporting

Heuristic 3: Know where your secret-sauce is, core domains

There are also supporting domains which are key to the core-domains delivering value, for example we need Identity to support taking Claim and Policy domains online. In a brick and mortar scenario, Identity may not be critical but for an online presence it is key

Heuristic 4: Know what you cannot do without, find your supporting domain

Finally there are things that you need and generic to all business functions, for example in Insurance context we may need Notification, Document Generation etc. There are your generic domains and support your business functions without specific context (re-useable?)

Heuristic 5: Know what is common across one or more domains and generic, build common services for these for all others to use

Note: The classification of core, supporting and generic is applicable in a business function context. For example, if we divide a domain further into core, supporting and generic then it has to be for business reasons, in which case one might argue why it the inner core domain is not pulled up

Warning: Generic domains are notorious breeding grounds for your monolithic software of the future. These can start our context-free and over time contextual logic can creep-in, for example – a Notification service mutates from being generic to using specific Email templates and Branding depending on the context. The act of changing the Notification API to accept new attributes for branding or email templating can become contentious and cause impact across line-of-businesses within an enterprise

Bounded Contexts

A Bounded context is a term from Domain Driven Design (DDD) and represents a linguistic boundary within or across a domain. While the statement “this is where there is a ubiquitous language“, sounds trivial there are several traps:

  • Linguistic boundary depends on who we sanction to tell us the language – who is the true domain expert?
  • Depending on which definition of language we pick the linguistic boundary could be wide, as wide as a large domain or even across domains (see 3 choices below). This would make the model bloated and would introduce strong coupling
  • Language applied to some entities may have a common model (e.g. Reporter Contact in Lodgement and Management of a claim) making us believe the bounded context extends wider ( e.g making Lodgement & Management context). We need to examine the language for all entities (e.g Claim in Lodgement is a small model vs in Claim Management which is the full claim object)

We have 3 possible choices for drawing boundaries

  • Context spans the domain: e.g. Claims domain speaks the language of the NSW Motor Vehicle Claim laws
  • Multiple Contexts within the domain: e.g. Claim Lodgement and Management, Claim Owner Registration
  • Context spans multiple domains: e.g There is a NSW Motor Vehicle P&C law and the language in the 2 domains for policy buying, claim lodgement etc uses the vocabulary of the book

In our insurance example then, we apply the heuristics for bounded contexts and make sure they are not too big or not too small to end up with something like the picture below. Notice how the all domains have multiple bounded contexts (models) and we have split the “lodgement and management” context into 2 (despite both of them defining the contact entity in the same way)

Sample set of bounded contexts for Vehicle Insurance with representation of a Contact

APIs, Events and Services

The interactions across bounded contexts happens with the exchange of a model – one sends its internal representation of a concept across to another or consumes a model from another. DDD context interaction patterns describe these as “Upstream” or “Downstream” relationships and help show where an external model is influencing a bounded context

Domain events, commands, queries across contexts

These interactions not only help with designing services but using the DDD context mapping notation we can define power relationships and discover the information models we need to propagate

We need to also model the transactional state of the system as we build the cross-context interactions. This means that we need to be asking if the consistency requirements are real-time or can they be eventual because incorrect integration pattern here could stop a business functionality. For example, imagine having to update the customer management context in real-time via an API (POST /api/customer/contacts) every time we are in a Policy buying or renewal transaction step. The strong coupling could cause the Policy buying and renewal to fail if there are network or data validation issues in the customer context

How do we interact across contexts? How do we propagate a model?

Summary

We use domain driven design to discover our business Domains, Bounded Contexts, Models and Interactions to build better distributed software features which would be cohesive within contexts and decoupled across boundaries leading to nimble, changeable modules that can deliver iterative value over time

In this post we used a sample industry vertical (Insurance) to do strategic DDD. The next step is to get into details: this is tactical DDD where teams continue to do domain storytelling, define the details of the models (domain aggregates, value objects etc) and identity commands, queries and events. Finally we take these and engineer the solutions – i.e. apply API, Event and Systems Integration patterns and best practices to build the integrations

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s