Domain-Driven Design
Domain-Driven Design (DDD) is a systematic approach to analyzing complex business problems and modeling software solutions. It splits naturally into two complementary halves: strategic design (the big-picture boundaries) and tactical design (the building blocks inside each boundary).
Two Spaces
DDD constantly distinguishes between the problem space (the business reality you’re modeling) and the solution space (the architecture that addresses it).
Inside the problem space
Inside the solution space
- Bounded contexts — software boundaries within which a single domain model applies coherently.
- Context maps — visual representations of how bounded contexts relate.
- Integration patterns — Shared Kernel, Customer/Supplier, Anti-corruption Layer, and friends.
The Bridge: One Domain, Many Models
The same business concept can carry different meanings across bounded contexts — and that’s a feature, not a bug.
The model is what spans both spaces. Multiple bounded contexts can reference the same sub-domain; one sub-domain can be touched by multiple bounded contexts. The relationships are many-to-many.
Tactical Building Blocks
Inside a bounded context, tactical DDD gives you the patterns to express the model in code.
A Concrete Walkthrough
Imagine an e-commerce platform. Strategic analysis surfaces three sub-domains:
- Product Recommendations — core (your differentiator).
- Order Processing — supporting (essential, but not where you compete).
- User Authentication — generic (essentially the same for everyone).
Each maps to a bounded context. Inside the Order Processing context, tactical patterns shape the model:
- An
Orderentity with identity and lifecycle. OrderItemvalue objects defined by product and quantity.- An
OrderAggregateenforcing invariants like “total = sum of line items.” - An
OrderRepositoryfor persistence. - A
PricingServicefor calculations that don’t belong to a single entity.
Strategic and Tactical Are Iterative
Strategic and tactical design are not sequential phases. You start with strategic analysis to find boundaries, but tactical implementation insights routinely feed back into strategic refinement. The boundary that looked clean on a whiteboard sometimes turns out to be wrong; the fix is to redraw the boundary, not paper over it in code.
The domain model emerges from this iteration — from the dialogue between business reality and software implementation.
Why DDD Pays Off
DDD does three things at once that no other approach quite does:
- Aligns software structure with business structure. What changes in the business changes in the same place in code.
- Gives engineers a shared vocabulary with the business. No translation layer between requirements and design.
- Provides patterns for the gnarly bits — invariants across multiple entities, integrating with legacy systems, evolving boundaries as understanding grows.
In multi-tenant SaaS, where the product and the business model are tightly coupled, DDD is often the difference between a platform that scales coherently and one that becomes the kind of “big ball of mud” the previous lesson warned about.
Recap
- DDD has two halves: strategic (boundaries) and tactical (building blocks).
- Problem space describes the business; solution space describes the software.
- Bounded contexts encapsulate one consistent domain model each.
- The same business concept can mean different things in different contexts — and that’s correct.
- Tactical patterns (entities, value objects, aggregates, repositories) implement the model inside a bounded context.
- Strategic and tactical work iteratively — boundaries get refined as the team learns.