Searching...
English
EnglishEnglish
EspañolSpanish
简体中文Chinese
FrançaisFrench
DeutschGerman
日本語Japanese
PortuguêsPortuguese
ItalianoItalian
한국어Korean
РусскийRussian
NederlandsDutch
العربيةArabic
PolskiPolish
हिन्दीHindi
Tiếng ViệtVietnamese
SvenskaSwedish
ΕλληνικάGreek
TürkçeTurkish
ไทยThai
ČeštinaCzech
RomânăRomanian
MagyarHungarian
УкраїнськаUkrainian
Bahasa IndonesiaIndonesian
DanskDanish
SuomiFinnish
БългарскиBulgarian
עבריתHebrew
NorskNorwegian
HrvatskiCroatian
CatalàCatalan
SlovenčinaSlovak
LietuviųLithuanian
SlovenščinaSlovenian
СрпскиSerbian
EestiEstonian
LatviešuLatvian
فارسیPersian
മലയാളംMalayalam
தமிழ்Tamil
اردوUrdu
Domain-Driven Design

Domain-Driven Design

Tackling Complexity in the Heart of Software
by Eric Evans 2003 560 pages
4.15
5.8K ratings
Listen
Try Full Access for 7 Days
Unlock listening & more!
Continue

Key Takeaways

1. Cultivate a Ubiquitous Language for Shared Understanding

Use the model as the backbone of a language.

Fractured communication. On many software projects, communication is fractured. Domain experts use their jargon, developers use technical terms, and even different developers create their own abstractions. This linguistic divide leads to miscommunication, unreliable software, and prevents the deep interplay of knowledge needed for insightful models. Translation between these dialects muddles concepts and hinders effective knowledge crunching.

Model-driven language. The solution is to consciously cultivate a "Ubiquitous Language" derived directly from the domain model. This language, encompassing class names, operations, and explicit rules, must be used relentlessly in all forms of communication: speech, diagrams, written documents, and especially the code itself. This dynamic language evolves with the model, forcing weaknesses into the open and ensuring everyone shares a precise understanding.

Benefits of a shared language. A Ubiquitous Language ensures that when a term is used, its meaning is unambiguous and consistent across the team and the software. It allows domain experts to articulate requirements more precisely and developers to build software that truly reflects business principles. This shared vocabulary becomes the primary carrier of design aspects, fostering continuous learning and enabling the team to collectively refine their understanding of the domain.

2. Bind Your Domain Model Directly to the Code

Design a portion of the software system to reflect the domain model in a very literal way, so that mapping is obvious.

The analysis-design dichotomy. Many projects suffer from a disconnect between the initial "analysis model" (conceptual) and the "design model" (implementation-focused). This separation often leads to the analysis model becoming irrelevant as coding begins, losing valuable insights and creating complex, unmaintainable software. The code, devoid of a conceptual foundation, becomes a mere mechanism without explaining its actions.

Model-Driven Design. The core principle is to discard this dichotomy and strive for a single model that serves both analysis and design. This means the code itself becomes a direct expression of the domain model, making the mapping between concepts and implementation obvious. Each object in the design plays a conceptual role described in the model, ensuring that insights gained during analysis are retained and reflected in the running software.

Hands-on modelers. Achieving this tight binding requires developers to be "hands-on modelers." They must not only write code but also understand how their code changes the model. This approach demands a model that is both conceptually rich and practical for implementation, often requiring iterative refinement and refactoring. Object-oriented programming, with its direct analogs to conceptual objects, is particularly well-suited to support this literal correspondence.

3. Isolate the Domain Layer from Technical Concerns

Concentrate all the code related to the domain model in one layer and isolate it from the user interface, application, and infrastructure code.

Complexity diffusion. In many applications, domain-related code is diffused throughout UI, database, and other technical components. This entanglement makes it incredibly difficult to reason about business logic, as superficial UI changes can inadvertently alter business rules, and changing a business rule might require meticulous tracing through various technical layers. Coherent, model-driven objects become impractical to implement.

Layered Architecture. The solution is a "Layered Architecture," partitioning the program into distinct layers:

  • User Interface (Presentation Layer): Handles user interaction and display.
  • Application Layer: Defines software jobs, coordinates tasks, delegates to domain objects.
  • Domain Layer (Model Layer): Represents business concepts, rules, and state. This is the heart of business software.
  • Infrastructure Layer: Provides generic technical capabilities (persistence, messaging, UI widgets).

Benefits of isolation. By isolating the Domain Layer, domain objects are freed from responsibilities like displaying themselves or managing persistence. This allows the model to evolve, becoming rich and clear enough to capture essential business knowledge. This separation also makes each layer easier to understand, maintain, and test, as they evolve at different rates and respond to different concerns.

4. Structure Your Domain Model with Entities, Value Objects, and Services

When an object is distinguished by its identity, rather than its attributes, make this primary to its definition in the model.

Entities (Reference Objects). Some objects are fundamentally defined by their identity, not their attributes. An "Entity" has a thread of continuity through its life cycle, even if its attributes change. For example, a Customer is an Entity, uniquely identified by a customerID, regardless of changes to their address or name. Entities should be kept simple, focused on identity, and their class definitions, responsibilities, and associations should revolve around "who they are."

Value Objects. In contrast, "Value Objects" represent descriptive aspects of the domain with no conceptual identity. You care only about "what they are," not "which one." Examples include Address, Money, or Color. Value Objects should be treated as immutable; if a value changes, a new Value Object is created. This immutability simplifies design, allows safe sharing and copying, and enables performance optimizations.

Services. Sometimes, domain operations don't naturally belong to any Entity or Value Object. These are "Services"—operations offered as standalone interfaces, defined purely by what they can do for a client. Services are typically stateless, named for activities (verbs), and their interfaces are defined in terms of other domain objects. They are used judiciously to avoid stripping behavior from Entities and Value Objects, providing a natural home for important domain concepts that are actions or transformations.

5. Manage Object Life Cycles with Aggregates, Factories, and Repositories

Cluster the ENTITIES and VALUE OBJECTS into AGGREGATES and define boundaries around each.

Maintaining integrity. Complex object relationships can lead to tangled webs, making it difficult to maintain data consistency and enforce invariants. "Aggregates" address this by clustering associated objects into a unit for data changes. Each Aggregate has a "root" Entity, which is the only object outside the Aggregate allowed to hold references to. All invariants applying to objects within the Aggregate must be satisfied when the root is committed, simplifying transaction management and ensuring consistency.

Encapsulating creation. Object creation can be complex, involving intricate assembly and invariant enforcement. "Factories" encapsulate this complexity, shifting the responsibility for creating instances of complex objects or Aggregates to a separate object. Factories provide an intention-revealing interface that hides the internal structure and concrete classes, ensuring that only valid, consistent objects or Aggregates are produced. They are also crucial for reconstituting stored objects.

Accessing persistent objects. Clients need a practical way to acquire references to existing domain objects without being bogged down by persistence technology. "Repositories" provide this by representing all objects of a certain type as a conceptual in-memory collection. They encapsulate the machinery of database queries and metadata mapping, allowing clients to request objects based on criteria using a simple, model-focused interface. Repositories are typically provided only for Aggregate roots that need direct global access.

6. Refactor Relentlessly Towards Deeper Domain Insight

Each refinement of code and model gives developers a clearer view. This clarity creates the potential for a breakthrough of insights.

The iterative cycle. Software development is an iterative process of continuous learning and refinement. Developers constantly refactor code, not just for technical cleanliness, but to deepen their understanding of the domain and align the design more closely with that insight. This process involves:

  • Intention-Revealing Interfaces: Naming classes and operations to clearly describe their purpose, freeing clients from understanding internals.
  • Side-Effect-Free Functions: Placing complex logic into operations that return results without observable side effects, making them safe to combine and test.
  • Assertions: Explicitly stating post-conditions and invariants to characterize the guaranteed outcomes and state of objects, making behavior predictable.

Conceptual Contours. Effective decomposition aligns design elements with the "Conceptual Contours" of the domain—the natural, meaningful divisions. This leads to a supple design that is flexible where change is common and stable where concepts are fundamental. When refactoring, look for underlying consistency in the domain that explains patterns of change and stability.

Breakthroughs. While many improvements are incremental, continuous refactoring often sets the stage for sudden "breakthroughs"—profound shifts in understanding that dramatically simplify the model, increase its versatility, and make it resonate deeply with domain experts. These moments, though challenging, are crucial for achieving truly powerful and elegant designs.

7. Maintain Model Integrity Across Bounded Contexts

Explicitly define the context within which a model applies.

The challenge of large systems. In large projects, a single, unified domain model for the entire enterprise is often infeasible or not cost-effective. Multiple models inevitably coexist, leading to problems like duplicate concepts, "false cognates" (same term, different meaning), and unreliable software when code based on distinct models is combined.

Bounded Contexts. The solution is to explicitly define "Bounded Contexts"—bounded parts of a software system where a single, unified model applies. These boundaries are set in terms of team organization, specific application parts, and physical manifestations like codebases. Within a Bounded Context, the model is kept strictly consistent, but outside, other models apply, with their own terminology and rules.

Context Map. A "Context Map" provides a global overview, identifying each Bounded Context on the project and describing the points of contact and relationships between them. This map clarifies where models diverge and where translation is necessary. Within each Bounded Context, "Continuous Integration" (frequent merging, automated tests, relentless Ubiquitous Language exercise) is essential to prevent model fragmentation.

Relationship patterns. Various patterns define how Bounded Contexts interact:

  • Shared Kernel: Two teams agree to share a subset of the model and code.
  • Customer/Supplier: Downstream team acts as a customer to the upstream team, negotiating requirements and using automated acceptance tests.
  • Conformist: Downstream team slavishly adheres to the upstream model, simplifying integration but limiting design freedom.
  • Anticorruption Layer: An isolating layer that translates between a client's domain model and another system's (often legacy or external) model, protecting the client's model from corruption.
  • Separate Ways: Two contexts have no connection, allowing simple, specialized solutions.
  • Open Host Service: A subsystem defines a public protocol for access as a set of services for many integrators.
  • Published Language: A well-documented shared language (e.g., XML DTD) is used as a common communication medium between systems.

8. Strategically Distill Your Core Domain

Boil the model down. Find the CORE DOMAIN and provide a means of easily distinguishing it from the mass of supporting model and code.

Obscured value. In large systems, the true business asset—the "Core Domain"—can be obscured by a mass of supporting components. This leads to:

  • Difficulty in understanding and changing the system.
  • Misallocation of talent (top developers gravitate to generic technical problems).
  • Weak design in the most critical, differentiating parts of the software.

Core Domain. The Core Domain comprises the most valuable, specialized, and distinctive concepts central to the application's purpose. It's where top talent should be focused to find a deep model and develop a supple design. Investment in other parts of the system should be justified by how they support this distilled core.

Distillation techniques:

  • Generic Subdomains: Identify cohesive subdomains not central to the project's motivation (e.g., time zones, generic accounting). Factor them into separate modules, consider off-the-shelf solutions, or outsource their implementation. This reduces clutter around the core.
  • Domain Vision Statement: A short (one-page) document describing the Core Domain's value proposition, guiding resource allocation and modeling choices.
  • Highlighted Core: Flagging Core elements within the primary model repository (e.g., diagrams, code comments) to make them effortlessly visible.
  • Cohesive Mechanisms: Partitioning conceptually cohesive computational problems (e.g., graph traversal algorithms) into separate, lightweight frameworks. This allows the Core Domain to focus on expressing the problem, delegating the "how" to the mechanism.
  • Segregated Core: Refactoring the model to physically separate Core concepts into their own modules, strengthening their cohesion and reducing coupling to supporting code.
  • Abstract Core: Factoring the most fundamental concepts into distinct abstract classes or interfaces in their own module, expressing most interactions between significant components.

9. Impose a Large-Scale Structure for System Comprehension

Devise a pattern of rules or roles and relationships that will span the entire system and that allows some understanding of each part's place in the whole—even without detailed knowledge of the part's responsibility.

Overwhelming complexity. Even with well-defined modules and distillation, a large model can be too complex to grasp as a whole. Without an overarching organizing principle, developers struggle to understand how parts fit together, leading to inconsistent designs and fragmented knowledge.

Large-Scale Structure. A "Large-Scale Structure" is a language of high-level concepts or rules that spans the entire system, guiding design and aiding comprehension. It helps coordinate independent work by providing a shared understanding of the big picture. This structure evolves with the application, avoiding rigid, up-front architectural impositions that can stifle development.

Types of structures:

  • System Metaphor: A concrete, easily understood analogy (e.g., "firewall") that captures the imagination and guides design decisions across the system.
  • Responsibility Layers: Natural strata in the domain are cast as broad abstract responsibilities (e.g., "Potential," "Operations," "Decision Support," "Policy," "Commitment"). Layers are aware of and use services below, but are independent of layers above.
  • Knowledge Level: A distinct set of objects that describes and constrains the structure and behavior of the basic model, allowing for customization (e.g., Employee Type defining rules for Employee objects).
  • Pluggable Component Framework: A very mature model with an "Abstract Core" of interfaces and interactions, allowing diverse implementations to be freely substituted. This is typically for systems with many interoperating applications.

Benefits and caveats. A fitting large-scale structure clarifies the system, makes it easier to transform, and helps developers make consistent decisions. However, an ill-fitting or overly restrictive structure can hinder development, so minimalism and continuous evaluation are crucial.

Last updated:

Want to read the full book?

Review Summary

4.15 out of 5
Average of 5.8K ratings from Goodreads and Amazon.

Domain-Driven Design receives mixed reviews. Many praise its groundbreaking ideas on software development, emphasizing the importance of focusing on the business domain and creating a common language between developers and domain experts. Readers appreciate the real-world examples and valuable insights. However, some criticize the book's length, repetitive content, and dense writing style. While considered a must-read for experienced developers, it may be challenging for beginners. Despite its flaws, the book is widely regarded as influential in shaping modern software architecture practices.

Your rating:
4.56
3 ratings

About the Author

Eric Evans is a software development consultant and architect with extensive experience in various projects. He is best known for pioneering the concept of Domain-Driven Design, which he introduced in his influential book of the same name. Evans' work focuses on improving software design by aligning it closely with the business domain. He emphasizes the importance of collaboration between developers and domain experts to create more effective and maintainable software systems. Evans has contributed significantly to the field of software architecture and continues to be a respected figure in the software development community, frequently speaking at conferences and conducting workshops on Domain-Driven Design principles.

Listen
Now playing
Domain-Driven Design
0:00
-0:00
Now playing
Domain-Driven Design
0:00
-0:00
1x
Voice
Speed
Dan
Andrew
Michelle
Lauren
1.0×
+
200 words per minute
Queue
Home
Swipe
Library
Get App
Create a free account to unlock:
Recommendations: Personalized for you
Requests: Request new book summaries
Bookmarks: Save your favorite books
History: Revisit books later
Ratings: Rate books & see your ratings
250,000+ readers
Try Full Access for 7 Days
Listen, bookmark, and more
Compare Features Free Pro
📖 Read Summaries
Read unlimited summaries. Free users get 3 per month
🎧 Listen to Summaries
Listen to unlimited summaries in 40 languages
❤️ Unlimited Bookmarks
Free users are limited to 4
📜 Unlimited History
Free users are limited to 4
📥 Unlimited Downloads
Free users are limited to 1
Risk-Free Timeline
Today: Get Instant Access
Listen to full summaries of 73,530 books. That's 12,000+ hours of audio!
Day 4: Trial Reminder
We'll send you a notification that your trial is ending soon.
Day 7: Your subscription begins
You'll be charged on Jan 15,
cancel anytime before.
Consume 2.8× More Books
2.8× more books Listening Reading
Our users love us
250,000+ readers
Trustpilot Rating
TrustPilot
4.6 Excellent
This site is a total game-changer. I've been flying through book summaries like never before. Highly, highly recommend.
— Dave G
Worth my money and time, and really well made. I've never seen this quality of summaries on other websites. Very helpful!
— Em
Highly recommended!! Fantastic service. Perfect for those that want a little more than a teaser but not all the intricate details of a full audio book.
— Greg M
Save 62%
Yearly
$119.88 $44.99/year/yr
$3.75/mo
Monthly
$9.99/mo
Start a 7-Day Free Trial
7 days free, then $44.99/year. Cancel anytime.
Scanner
Find a barcode to scan

We have a special gift for you
Open
38% OFF
DISCOUNT FOR YOU
$79.99
$49.99/year
only $4.16 per month
Continue
2 taps to start, super easy to cancel
Settings
General
Widget
Loading...
We have a special gift for you
Open
38% OFF
DISCOUNT FOR YOU
$79.99
$49.99/year
only $4.16 per month
Continue
2 taps to start, super easy to cancel