Understanding Domain-Driven Design (DDD): Core Concepts, Patterns, and Architectural Practices
This article explains the fundamentals of Domain‑Driven Design, covering its core ideas such as model‑driven design, ubiquitous language, bounded contexts, layered and hexagonal architectures, and key building blocks like entities, value objects, aggregates, repositories, factories, and services, with practical examples and diagrams.
Enterprise applications are often complex and rely on specialized technologies such as persistence, AJAX, and web services, but a system that does not solve business problems is useless regardless of how well‑engineered it appears.
Domain‑Driven Design (DDD) Overview
Originally described by Eric Evans, DDD focuses attention on the core domain and its inherent complexity, separating the core domain (business‑specific) from support sub‑domains (generic concerns like money or time) and placing most design effort on the core.
Model‑Driven Design
In DDD the model is the set of concepts we choose to implement in code; therefore, "code is the model". Visual tools such as UML class diagrams or Spring bean docs can aid understanding, but the definitive model lives in the source code.
Ubiquitous Language
DDD encourages developers and domain experts to communicate using the same model concepts, ensuring that every business idea can be expressed in the shared language and that missing concepts are identified early.
Bounded Contexts
A model always exists within a specific bounded context (BC) . Each BC contains a single domain model, and relationships between BCs are expressed through patterns such as Published Language, Open Host Service, Shared Kernel, Customer/Supplier, Conformist, and Anti‑Corruption Layer, forming a spectrum of collaboration.
Layered and Hexagonal Architecture
DDD assumes a layered architecture (presentation, application, domain, infrastructure) but also promotes a hexagonal (ports‑and‑adapters) view where the domain sits at the center and interacts with the outside world through well‑defined ports.
Modules, Entities, and Value Objects
Modules (packages or namespaces) organize the model. Entities are mutable, persistent objects with identity; Value Objects are immutable, represent concepts like Money or SocialSecurityNumber, and provide value semantics (equals, hashCode).
Aggregates and Aggregate Roots
An aggregate groups related entities and value objects under a single aggregate root , which enforces invariants and is the only entry point for external access.
Repositories, Factories, and Services
Repositories abstract persistence for aggregate roots, often defined as generic interfaces (e.g., Repository<Customer> ) with concrete implementations per storage technology. Factories create new aggregates, while domain services encapsulate business logic that does not naturally belong to an entity or value object. Application services orchestrate use cases, handling transactions, security, and coordination between the presentation layer and domain services.
Code Example
Money m1 = new Money("GBP", 10);
Money m2 = new Money("GBP", 20);
Money m3 = m1.add(m2); // m3 represents 30 GBP, m1 remains unchangedThe article concludes by noting that while DDD provides a rich set of patterns, many practitioners struggle with applying them in real projects, especially when dealing with bounded contexts and integration.
Architects Research Society
A daily treasure trove for architects, expanding your view and depth. We share enterprise, business, application, data, technology, and security architecture, discuss frameworks, planning, governance, standards, and implementation, and explore emerging styles such as microservices, event‑driven, micro‑frontend, big data, data warehousing, IoT, and AI architecture.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.