DDD Building Blocks

An overview of the tactical and strategic patterns that make up Domain-Driven Design, showing how they fit together to form a coherent approach to modeling complex business domains.

Two Levels of DDD

Domain-Driven Design operates at two levels:

  • Strategic Design — how to decompose a large system into manageable, well-bounded parts.
  • Tactical Design — the building blocks for implementing rich domain models within those parts.

Strategic Design Patterns

Bounded Context

The primary strategic pattern. See Bounded Context.

Defines the boundary within which a specific domain model and ubiquitous language apply. A large system is divided into multiple bounded contexts, each with its own model.

Context Map

Documents how bounded contexts relate: which team is upstream/downstream, how data flows, and what integration pattern (Shared Kernel, ACL, Conformist, etc.) governs each relationship.

Ubiquitous Language

The shared vocabulary developed collaboratively between domain experts and developers. Used consistently in conversations, code, tests, and documentation within a bounded context.

Subdomain Types

  • Core domain — the key differentiator; deserves the most investment and DDD rigor.
  • Supporting subdomain — necessary but not differentiating; can be built in-house with less rigor.
  • Generic subdomain — commodity; buy or use open-source (auth, billing, email).

Tactical Design Patterns

Entity

An object defined by a continuous identity that persists over time. Example: Customer, Order. Two entities with the same data but different IDs are not the same entity.

Value Object

See Value Object. An immutable object defined entirely by its attributes; no identity. Example: Money, Address, EmailAddress. Two value objects with identical attributes are equal.

Aggregate

See Aggregate. A cluster of entities and value objects with a single Aggregate Root that enforces invariants. The unit of transactional consistency. Example: Order aggregate containing OrderLines.

Domain Service

A stateless service that encapsulates domain logic that doesn’t naturally belong to any single entity or value object. Example: TransferService.Transfer(fromAccount, toAccount, amount).

Domain Event

See Domain Event. An immutable record of something significant that happened. Raised by aggregate roots; used to decouple domain from application concerns and to integrate across bounded contexts.

Repository

See Repository Pattern. An abstraction over persistence that allows the domain to load and save aggregates without knowing about the underlying database technology.

Application Service

Orchestrates use cases by coordinating aggregates, domain services, and repositories. Contains no business logic — only workflow. Example: OrderApplicationService.PlaceOrder(command).

Factory

Encapsulates complex aggregate construction logic that does not belong in the aggregate’s constructor.

How the Building Blocks Fit Together

Bounded Context
└── Aggregate Root (e.g., Order)
    ├── Entities (e.g., OrderLine)
    ├── Value Objects (e.g., Money, Address)
    └── raises Domain Events (e.g., OrderPlaced)

Application Service
├── loads Aggregate from Repository
├── calls Aggregate methods (which enforce invariants)
├── collects Domain Events
└── dispatches Domain Events (→ integration events → other contexts)

Discovery Techniques

TechniqueLevelPurpose
Event StormingStrategic + TacticalDiscover domain events, commands, aggregates, bounded context boundaries
Domain StorytellingStrategicDiscover workflows through narrative user stories
Bounded Context CanvasStrategicDefine and document a bounded context