alama@world: ~/
./toggle-theme
Language in Context thumbnail

# Language in Context

by Eric Evans
Published on October 2, 2020
Domain-Driven Design Software Architecture Bounded Contexts Strategic Design

Description

Eric Evans revisits bounded context — the strategic-design pattern he introduced in the blue book — and argues it's a natural consequence of the ubiquitous language pattern. He clarifies the difference between bounded contexts, subdomains, and teams, and pushes back on the tidy diagrams that dominate DDD talks. Real systems are messy: legacy applications, SaaS integrations, and reorganisations pull the model apart, and bounded contexts are the pragmatic tool for keeping islands of order in that sea of mud.

Venue

DDD Europe 2020

cat notes.md

My Notes

Key Takeaways

Bounded Context Falls Out of Ubiquitous Language

Evans frames bounded context as an implication of the ubiquitous language pattern, not a separate idea you bolt on afterwards.

  • The word ubiquitous is a source of regret — it makes people hear "one language everywhere", which is the opposite of what he means
  • Ubiquitous refers to two extremes: the same language shows up in conversations with domain experts and in the code — not across every problem in the system
  • Different problems need different models. Forcing a single model to cover everything would require a language as versatile as a natural language, which is exactly the ambiguity you're trying to avoid
  • Once you accept that you need multiple specialised models, you need a boundary to say where each one applies. That boundary is the bounded context

Context, Literally

The name is not clever — it's just the ordinary meaning of the word.

  • You understand this sentence because of everything said before it. Same in code: booking.finalize on its own tells you nothing until you trace outward
  • A useful measure of a design: how far do you have to trace before you can predict what a call will do? In highly coupled systems the answer is "too far" and eventually "I don't dare change anything" — that's how legacy systems calcify
  • Bounded context artificially, consciously limits that tracing radius — not just around code connections but around the meanings of the terms themselves
  • Inside the boundary, definitions and rules are consistent — "as consistent as humans can make things", not 100%

What Counts as a Boundary

Any separation a developer can easily see. Evans deliberately keeps the list open-ended.

  • Distinct database schemas
  • Service boundaries
  • Deployment boundaries
  • Team ownership

Two systems hitting the same tables are not separated at all, no matter what the architecture diagram claims. The people inside the boundary also have to agree on what words mean and on some development process — otherwise they step on each other's toes.

Bounded Context vs Subdomain vs Team

The bit of the talk that clears up the most confusion. Evans uses a simple bank: cash accounts and credit accounts, each with its own business unit, software team, and model. On day one, bounded context / subdomain / team all line up perfectly. That's the tidy picture everyone draws.

Then he introduces a reorg. The bank realises customers actually split into individuals and businesses, not cash vs credit. Business units re-form. Software teams re-form. But:

  • The subdomain decomposition has changed (personal vs business)
  • The teams have changed
  • The bounded contexts have not — the code that was there yesterday is still there today. A reorg doesn't rewrite software

The failure mode: teams act as though the software followed the reorg. Stewardship becomes unclear — nobody owns the integrity of the cash model any more — and both new teams start hacking on the same artifact without coordination. That's the three-legged race.

The Three-Legged Race Metaphor

Two children tied together running a race — outcome depends on the balance of speed and coordination. Add a third leg, or a fourth, or a fifth, and eventually nobody can take a single step without falling. That's what happens when a single unified model has to serve everyone: forward motion requires universal agreement, and you get none.

  • Bounded context lets one group move without waiting for another to agree
  • The only thing everyone must agree on is the interface between contexts
  • You don't even agree with your past self — a legacy system is essentially a bounded context maintained by an earlier version of the team

Real Systems Aren't Tidy

A picture with two neat bounded contexts and a translator between them is aspirational. Evans deliberately messes it up:

  • Salesforce. Already exists. Already is what it is. Do you fight it or conform to it? If Salesforce has thought through customers-and-IDs, don't swim upstream — declare a conformist relationship and adopt its model
  • The legacy system. There is always a legacy system in 2020 because "everything's already been softwared". If you conform to it, you might as well have built the new work inside it. Instead, you use an anti-corruption layer — a much more robust translator that treats everything crossing the boundary with suspicion, in both directions

Scale of the Anti-Corruption Layer

Evans deliberately redraws the context map at realistic scale.

  • The legacy app is much bigger than the new context — "true 99% of the time"
  • Salesforce is bigger still — he jokes he considered drawing a line so long its curvature was invisible
  • The anti-corruption layer itself is often comparable in size to the new system it protects. This alarms people; Evans argues it's right

Why: without the ACL you'd absorb the legacy system's complexity into the new context, making it fuzzy at the edges and effectively bigger than the whole thing was before. The ACL is real software — often arbitrarily complex — but it lets the new system stay small and clear.

The Shoes-Off Metaphor

For anti-corruption layers, Evans uses a physical-space analogy: a house where you take off outdoor shoes at the door and switch to indoor shoes. Different expectations inside vs outside (cleanliness of floor, volume of voice), enforced at the boundary. Software boundaries work the same way — but only if you're serious about them.

You do have to take off your shoes when you come in the door every time — or be ready to mop up afterwards.

Notable Quotes

On the trouble with the word "ubiquitous":

One of my regrets about the word ubiquitous is that it means everywhere, and it makes people think that what we're looking for is a single model that would address all our problems throughout the system. But that's definitely not what we want to do.

On why the concept feels slippery:

The definition is sort of slippery. It's like trying to grab fog for people sometimes. It's actually one of those concepts I think that's so simple that people think, well, that can't be all there is to it.

On tidy diagrams:

A picture this tidy makes me very suspicious. In the real world, when I've been on real projects, things are never like this. Even projects that I've run. Although I must admit that there was a time when I thought that if we just tried hard enough we could make the whole thing like that — but it never happens.

On the reorg / stewardship problem:

Just because we did a reorg doesn't change the software we already have. And yet a lot of times when people reorganize the teams, they behave as if it did.

On coupling and paralysis:

Maybe in the end you conclude, I don't think I'm ever going to fully understand what's going to happen, and therefore I don't dare make any changes. And this is what happens to us in a lot of legacy systems.

Closing summary:

Bounded context is a pragmatic thing that allows us to do elegant designs in real situations, and not just talk about it, and not create problems for people who are trying to get their jobs done.

How I'll Apply This

  1. Stop conflating team boundaries with context boundaries. After a reorg, resist the pull to act as if the code re-organised itself. Explicitly name which bounded contexts still exist, who owns each one now, and whether ownership is actually clear. Unclear stewardship is the leading indicator of the three-legged race.
  2. Pick the boundary a developer can actually see. When defending a context boundary, point at something concrete — a schema, a deployable, a repo. If two "contexts" share a database, they aren't two contexts. That's the honesty test.
  3. Budget for the anti-corruption layer. When integrating with a legacy system or a SaaS product, plan for the ACL to be comparable in size to the new work. If a "quick integration" is small, the complexity didn't disappear — it moved into your model and will corrupt it. Better to see the cost upfront than to discover a fuzzy domain a year later.
  4. Default to conformist for SaaS integrations, ACL for legacy. Salesforce/Stripe/Auth0 have thought through their models; conforming is cheap and fine. Legacy systems you own, with a reason to diverge, get the ACL. Don't confuse the two.
  5. Measure the tracing radius. When onboarding to a new area of code, notice how many files I have to open before I can predict what a call does. That number is a proxy for how well the bounded contexts are actually holding.