Domain-Driven Design logo

Architecture & Methodology

Official site

Domain-Driven Design

Domain-Driven Design — modelling software around a shared, evolving understanding of the business domain and its ubiquitous language.

Overview

DDD is my default lens for systems with real business complexity. The discipline is less about technical patterns and more about alignment: a ubiquitous language shared with stakeholders, strategic boundaries drawn around subdomains, and a model that reflects how the business actually works.

I practise the strategic patterns deliberately — bounded contexts, context mapping, and anti-corruption layers decide where teams and services split. Tactical building blocks (aggregates, value objects, domain events, repositories) keep the model expressive inside each context.

Where DDD separates strong engineering from cargo-culting is the feedback loop: the model only earns its keep if it keeps the business language and the codebase in step as requirements evolve. That payoff compounds on long-lived systems.

The strategic layer is where I start: discovering core, supporting, and generic subdomains, and drawing bounded contexts where the language actually differs. Those boundaries are what make a monolith safely splittable into services later — the cut is by meaning, not by table count.

The ubiquitous language is the contract of the project. I run it through Event Storming and domain workshops so the same terms mean the same thing to stakeholders, product, and code. When the business says "approved", the codebook and the UI say the same word.

Aggregates are where transactional consistency lives. I size aggregates by invariants, not by convenience — a single aggregate guards its own consistency boundary, so the rules that must hold together do, and the rest of the model stays loosely coupled around it.

Domain events carry meaning outward. Rather than services calling each other, the domain emits facts — "orderPlaced", "paymentSettled" — which is exactly the seam that lets DDD compose with event sourcing and CQRS on one side and with integration patterns on the other.

Repositories and services keep infrastructure at the edges. Rules in the domain, frameworks at the boundary. That discipline is what lets a DDD system ride a framework change or database migration without re-architecting the business logic.

I am honest about DDD's scope: it is the wrong tool for CRUD-only systems where the business logic is thin. Applied where the domain is genuinely complex, it is the difference between software that fights the business and software that speaks its language.

How I Work With Domain-Driven Design

I begin with language, not structure. The first deliverable is a shared vocabulary with the business — the terms that mean something to everyone — because DDD lives or dies on whether the code and the stakeholders say the same thing.

Event Storming is how I discover the domain. I run the business people and engineers through the flow of events together, which surfaces the real model faster than a requirements document ever will.

Bounded contexts are drawn where the language differs, not where the tables are big. Each context owns its meaning, and the seams between them become the natural place for services and anti-corruption layers.

Core versus supporting versus generic subdomains drives effort. I invest the modelling rigour where the business actually competes, and keep the generic parts simple — DDD's energy belongs on the core.

Aggregates are sized by invariants. I protect consistency within a single aggregate and keep everything else loosely coupled around it, so the rules that must hold together do, and the rest stays flexible.

Domain events are the outward voice. Rather than services calling each other, the domain emits facts — and that is exactly the seam that lets DDD compose with event sourcing, CQRS, and integration patterns.

The repository and service layers keep infrastructure at the edges. Frameworks and databases sit behind boundaries, so the domain logic stays pure and survives framework or storage changes.

Tactical patterns are applied with restraint. I reach for value objects and domain events where they earn their keep, and I avoid cargo-culting every pattern onto every object.

I am honest about where DDD does not pay. For CRUD-only systems with thin logic, the energy is wasted; applied to a genuinely complex domain, it is the difference between software that fights the business and software that speaks it.

Key Capabilities

Strategic DDD: bounded contexts, context mapping, and anti-corruption layers.
Tactical patterns: aggregates, value objects, domain events, and repositories.
Ubiquitous language that keeps stakeholders and code in sync.
Event Storming and domain workshops to discover and model the core domain.
DDD as the foundation for microservice boundaries, not size-based cut-ups.