Domain-driven design: strategic and tactical patterns
DDD aligns software boundaries and language with business knowledge. Strategic patterns decide where models differ; tactical patterns express rules inside a boundary. DDD does not require microservices.
Core ideas and patterns
| Idea | What it solves | Cost, limit, or warning |
|---|---|---|
| Ubiquitous language | Creates shared precise domain terms | Language must be contextual and continually refined |
| Bounded context | Defines where one model and language apply | Boundaries discovered too early can freeze misunderstanding |
| Core/supporting/generic subdomain | Directs investment by differentiation | Classification changes with strategy |
| Context map | Names relationships and influence between models | Political reality may differ from desired integration |
| Entity | Models identity across change | Entity-heavy models hide value semantics |
| Value object | Models immutable descriptive value | Equality and units must be precise |
| Aggregate | Protects invariants inside a transaction boundary | Large aggregates cause contention |
| Domain event | Records a meaningful fact in domain language | Technical events should not masquerade as business facts |
| Repository | Provides aggregate-oriented persistence abstraction | Generic CRUD repositories leak persistence semantics |
| Domain service | Holds domain behavior not owned by one entity | Can become an anemic dumping ground |
How to apply it
Run event storming or domain storytelling with experts. Discover commands, facts, policies, hotspots, invariants, and terminology conflicts. Draw context relationships. Model aggregates around consistency needs, not object graphs. Keep application orchestration separate from domain policy.
Evidence, not opinion
Use example-based tests in domain language, invariant/property tests, context contract tests, and change coupling. Review the model when experts stop using its terms.
Small example
CreditLimit is a value with currency. CustomerAccount is an aggregate that protects the approved-credit invariant. CreditChecked is a domain fact; “row inserted” is not.
Feynman check
Explain the design to a new engineer without using the pattern names. State the problem, the forces that conflict, the chosen boundary or mechanism, what can fail, and the evidence that would prove the choice still works.