Back to Catalog
Software Design
architectural
Domain-Driven Design (DDD)
Model your code around real business concepts — bounded contexts, ubiquitous language, aggregates — so the software mirrors how the business actually works.
Intent & Description
🎯 Intent
Eliminate the translation gap between what the business says and what the code does.
📋 Context
Your domain is genuinely complex — insurance underwriting, financial instruments, healthcare workflows. Business rules are subtle, frequently misunderstood, and deeply interconnected. Developers and domain experts talk past each other constantly.
💡 Solution
Key DDD building blocks:
- Ubiquitous Language — one shared vocabulary between business and dev. Same words in meetings and in code.
- Bounded Contexts — explicit boundaries where a model applies. ‘Customer’ means different things in Sales vs. Support — model them separately.
- Entities — objects with identity that persists over time (a User with an ID).
- Value Objects — immutable objects defined by their attributes, not identity (a Money amount, an Address).
- Aggregates — a cluster of objects with one root that enforces consistency boundaries.
Real-world Use Case
Use for complex enterprise domains with rich, evolving business rules — finance, healthcare, logistics, e-commerce at scale. Not worth it for CRUD-heavy apps with simple data flows.
📌 TL;DR
Your code vocabulary = your business vocabulary. Model the domain explicitly with bounded contexts and aggregates. Massively valuable for complex domains. Massively wasteful for simple ones.
Advantages
- Code and business logic stay in sync as requirements evolve — the model is the documentation.
- Reduces costly miscommunication between stakeholders and developers.
Disadvantages
- Requires significant upfront investment in domain exploration and ongoing collaboration with domain experts.
- Overkill complexity for straightforward CRUD applications — you’ll build abstractions for problems you don’t have.
Implementation Example
// Value Object (Immutable, no identity, compared by value)
class Address {
constructor(street, city, zip) {
this.street = street;
this.city = city;
this.zip = zip;
Object.freeze(this); // Make immutable
}
equals(otherAddress) {
return this.street === otherAddress.street &&
this.city === otherAddress.city &&
this.zip === otherAddress.zip;
}
}