← All topics
🏗️ Architecture

Domain-Driven Design

Entities, value objects, aggregates, bounded contexts, ubiquitous language.

Entity — has identity that persists across state changes (an Order is still "that order" after its status changes) — compared by ID, not by value.

Value Object — no identity, compared by value, typically immutable (a Money or Address). Two Money(10, "EUR") instances are interchangeable; two Order instances with identical line items are not the same order.

Aggregate — a cluster of entities/value objects treated as one consistency boundary, with a single Aggregate Root as the only entry point external code is allowed to reference directly (e.g. Order is the root; OrderLines are only ever modified through Order's methods, never fetched/saved independently). This is what keeps invariants (e.g. "total must equal sum of lines") enforceable.

Bounded Context — a boundary within which a model and its ubiquitous language are consistent; the same word can mean different things in different contexts (a "Customer" in Sales vs in Support may have entirely different data/behavior) — and that's fine, they're deliberately separate models, often owned by separate services/teams. This is the DDD concept that most directly motivates microservice/event-driven boundaries: each service = roughly one bounded context.

Ubiquitous Language — the domain vocabulary used consistently in conversation, code, class names, and even commit messages, within a bounded context — code that reads like the business talks, not like generic CRUD.

Flashcards (6)

What distinguishes an Entity from a Value Object in DDD?
tap to reveal answer
An Entity has identity that persists across changes and is compared by ID (an Order is still the same order after its status changes). A Value Object has no identity, is compared by value, and is typically immutable (e.g. Money, Address).
What is an Aggregate Root and why does it matter for enforcing invariants?
tap to reveal answer
The single entry point through which all changes to an aggregate's internal entities must go (e.g. Order for its OrderLines) — because external code can't reach the internals directly, the root can enforce consistency rules (like total = sum of lines) on every mutation.
What is a Bounded Context, and how does it relate to microservice boundaries?
tap to reveal answer
A boundary within which a domain model and its terminology are consistent — the same word can mean different things in different contexts. It's the natural seam for splitting a system into services/event-driven components, since each context can own its own model independently.
What is Ubiquitous Language and why does it matter beyond just 'good naming'?
tap to reveal answer
Using the same domain vocabulary in conversations with business stakeholders, in code (class/method names), and in documentation — it closes the gap between how the business describes the domain and how the code models it, reducing translation errors.
Why might the word 'Customer' legitimately mean different things in two different bounded contexts of the same company?
tap to reveal answer
Because each context models only the aspects of the concept relevant to it — Sales' Customer might carry credit limit and deal history, Support's Customer might carry ticket history and SLA tier. Forcing one shared 'Customer' model across contexts usually causes bloat and coupling instead of accuracy.
Give a rule of thumb for what belongs inside an Aggregate boundary.
tap to reveal answer
Whatever must be consistent together in the same transaction — if two things can be eventually consistent (updated in separate transactions/messages) rather than needing to be atomic together, they probably belong in separate aggregates.