Domain Driven Design
The content here is under the Attribution 4.0 International (CC BY 4.0) license
Domain Driven Design (DDD) is a software development approach that emphasizes collaboration between technical and domain experts to create a shared understanding of the problem domain. It focuses on modeling complex business domains and aligning software design with business goals. This approach has for years been with me as a software engineer, and I have seen its benefits in various projects. Recently, (Colla & Acerbis, 2025) elaborated on a timeline that depicts the evolution of DDD through a series of publications:
I came across DDD by the blue book “Domain-Driven Design: Tackling Complexity in the Heart of Software” by Eric Evans, which introduced me to the principles and practices of DDD. The book emphasizes the importance of understanding the business domain and creating a shared language between technical and non-technical stakeholders. At that time, I found the book quite challenging to digest, but it laid the foundation for my understanding of DDD (Evans, 2004). The concepts presented in the book about DDD were along with a complex domain related with electrical engineering (another complex domain to get along with).
The read book helped me to understand the importance of modeling complex domains and how DDD can help to create a shared understanding of the problem domain. It also introduced me to the key concepts of DDD, such as Bounded Contexts, Entities, Value Objects, Aggregates, Repositories, Domain Events, and Ubiquitous Language. Vaughn Vernon, in his book “Implementing Domain-Driven Design,” further expanded on these concepts and provided practical examples of how to apply DDD in real-world projects. This book was a game-changer for me, as it provided a more hands-on approach to DDD and helped me to see how these concepts could be applied in practice (Vaughan, 2018).
In this page, I will share my experience with DDD, its key concepts, and how it can be applied in practice, along with examples of how DDD can help improve software design, reduce complexity, and enhance collaboration between teams. I will also discuss the challenges of implementing DDD and how to overcome them.
Part I - The theory
DDD is based on several key concepts that help to create a shared understanding of the problem domain and align software design with business goals. These concepts include:
- Ubiquitous Language
- Bounded Contexts
- Entities
- Value Objects
- Aggregates
- Repositories
- Domain Events
We will explore each of these concepts in detail, providing examples and practical applications in an organized fashion. The goal is to provide a comprehensive understanding of DDD and how it can be applied in practice based on theory.
Strategic patterns
Ubiquitous Language
Ubiquitous Language is a common language used by both technical and domain experts to describe the problem domain. It helps to create a shared understanding of the domain and ensures that everyone is on the same page. This language should be used consistently throughout the project, including in code, documentation, and discussions.
Bounded Contexts
The first key concept of DDD is Bounded Contexts. A Bounded Context is a boundary within which a specific model is defined and applicable. It helps to create a clear separation between different parts of the system, allowing teams to work independently on different contexts without interfering with each other. This separation also helps to reduce complexity and improve maintainability. A Bounded Context can be thought of as a mini-domain within the larger domain, with its own set of rules, language, and models. The boundaries of a Bounded Context is defined by a business capability or a specific area of the problem domain. It is important to note that a Bounded Context is not necessarily a physical boundary, but rather a conceptual one.
Whenever working with bounded contexts, it is essential to identify the relationships between them. This can be done using context mapping, which helps to visualize the interactions between different Bounded Contexts and how they relate to each other.
Contex mapping
Context mapping is a technique used to visualize the relationships between different Bounded Contexts. It helps to identify the boundaries of each context and how they interact with each other. Context mapping can be done using various techniques, such as diagrams, tables, or even text descriptions. According to Eric Evans, context mapping is a crucial step in the DDD process, as it helps to clarify the relationships between different parts of the system and ensures that everyone is on the same page (Evans, 2004). In addition to that, (Colla & Acerbis, 2025) suggests three types of context mapping:
- Core subdomain: The core subdomain is the most critical part of the system, representing the key business logic and functionality. It is the heart of the system and should be designed with care to ensure that it meets the business requirements.
- Supporting subdomain: The supporting subdomain provides additional functionality that supports the core subdomain. It is not as critical as the core subdomain but still plays an essential role in the system.
- Generic subdomain: The generic subdomain is a part of the system that is not specific to the business domain but provides common functionality that can be reused across different contexts. It is often used to provide infrastructure or utility functions that are needed by multiple contexts.
Communication between Bounded Contexts
The communication between bounded contexts are defined by the relationships between them. There are several types of relationships that can exist, based on the work by (Colla & Acerbis, 2025) and complemented by the work of (Colla & Acerbis, 2025) this section elaborates on the different types of relationships that can exist between bounded contexts.
Shared Kernel
A Shared Kernel is a part of the model that is shared between two or more Bounded Contexts. It allows teams to collaborate on a common set of concepts and ensures that they are using the same language and understanding of the domain. However, it can also lead to tight coupling between contexts, so it should be used with caution.
Customer/Supplier
The Customer/Supplier relationship is a type of relationship where one Bounded Context (the customer) relies on another Bounded Context (the supplier) for certain functionality or data. The customer context consumes the services provided by the supplier context, and any changes made in the supplier context can impact the customer context. (Colla & Acerbis, 2025) points out that this relationship should be collaborative.
Tools for communication
- Context Mapper: A tool for modeling and visualizing Bounded Contexts and their relationships.
Tactical patterns
Entities
Entities are objects that have a distinct identity and can change over time. They are the core building blocks of a domain model and represent the key concepts of the problem domain. Entities are defined by their attributes and behaviors, and they can be persisted in a database or other storage system (Colla & Acerbis, 2025).
Entities are typically long-lived and can have complex relationships with other entities. They are often used to represent real-world objects, such as customers, orders, or products.
Value Objects
Value Objects are objects that do not have a distinct identity and are defined by their attributes. They are immutable and do not change over time. Value Objects are used to represent concepts that do not require a unique identity, such as dates, money, or addresses. Value Objects are often used to encapsulate complex logic and provide a clear representation of a concept. They can be used to simplify the design of entities and reduce complexity in the domain model.
Aggregates
Aggregates are clusters of related entities and value objects that are treated as a single unit for data changes. They help to maintain consistency within the domain model by ensuring that all changes to the aggregate are made in a single transaction. Aggregates are defined by their root entity, which is the entry point for accessing and modifying the aggregate. Aggregates help to enforce business rules and invariants within the domain model. They also provide a clear boundary for data changes, making it easier to reason about the system and maintain consistency.
Repositories
Repositories are responsible for managing the persistence of aggregates. They provide an interface for accessing and modifying aggregates, allowing the domain model to remain independent of the underlying storage mechanism. Repositories are typically implemented as interfaces, with concrete implementations provided for different storage systems, such as databases or in-memory storage. Repositories help to decouple the domain model from the persistence layer, allowing for greater flexibility and maintainability. They also provide a clear separation of concerns, making it easier to test and evolve the domain model.
Domain Events
Domain Events are events that represent a significant change in the state of the domain model. They are used to communicate changes between different parts of the system and can trigger actions or processes in response to those changes. Domain Events help to decouple different parts of the system, allowing for greater flexibility and maintainability. Domain Events are typically used to represent events that occur within a Bounded Context, such as a customer placing an order or a product being added to inventory. They can also be used to communicate changes between different Bounded Contexts, allowing for greater integration and collaboration between teams.
References
- Colla, A., & Acerbis, A. (2025). Domain-Driven Refactoring: A hands-on DDD guide to transforming monoliths into modular systems and microservices. Packt.
- Evans, E. (2004). Domain-driven design: tackling complexity in the heart of software. Addison-Wesley Professional.
- Vaughan, V. V. (2018). Implementing Domain-Driven Design. Addison-Wesley Professional.