Q: Can I apply just the tactical design elements of DDD without going through strategic design?
A: Technically, yes, it is possible to apply the tactical design elements of DDD without going through the strategic design phase. However, doing so may limit the benefits you can gain from DDD.
The tactical design patterns of DDD are designed to help developers tackle specific design challenges that are common in complex domains, such as aggregate design, domain events, and bounded contexts. These patterns can be applied to a codebase without necessarily needing to engage in a larger strategic design effort.
However, the strategic design phase is crucial in establishing a shared understanding of the domain between the domain experts and the development team, as well as identifying the key business concepts and boundaries that should be reflected in the software architecture. Without this shared understanding, it can be difficult to apply the tactical design patterns effectively.
Moreover, DDD is not a one-size-fits-all approach, and not all of the tactical patterns may be relevant to every project. The strategic design phase can help determine which patterns are most appropriate for the specific domain and identify additional patterns that may be needed.
In a brownfield project, which is a software development project that starts from an existing codebase or system, applying DDD involves identifying and understanding the existing domain concepts and aligning them with the ubiquitous language. This may involve refactoring the codebase to better represent the domain concepts and separating the concerns of the application into appropriate bounded contexts.
Applying DDD from the bottom up can be more challenging than applying it from the top down. However, it is still possible to apply the tactical design patterns of DDD incrementally and iteratively. For example, a team could start by applying the repository pattern to a portion of the codebase, and gradually expand the use of DDD patterns as the team gains more familiarity with the domain and the codebase.
Q: Is CQRS complementary to DDD?
A: Yes, CQRS (Command Query Responsibility Segregation) is complementary to DDD (Domain-Driven Design) as they both aim to improve the design of complex software systems. CQRS is an architectural pattern that separates the read and write responsibilities of a system, while DDD is a set of principles and patterns that focus on the domain model and its behavior.
CQRS can be used to implement the query side of a DDD application, by providing a way to efficiently retrieve data from the system. By separating the read and write concerns, CQRS can also help to reduce the complexity of the domain model and make it easier to reason about.
Furthermore, CQRS can also help to improve scalability and performance by allowing the system to optimize the read and write paths independently. This can be particularly useful in systems with high read or write loads, where traditional CRUD (Create, Read, Update, Delete) operations may not be sufficient.
Finally, it is important to note that CQRS is not necessary to implement DDD. DDD can be implemented without using CQRS. CQRS is a separate architectural pattern that can be used in conjunction with DDD to achieve certain benefits, such as improved performance and scalability. However, it is not a requirement for implementing DDD.
Q: Is being event-driven necessary to implement DDD?
A: No, being event-driven is not necessary to implement DDD. While event-driven architecture is often used in DDD to help model complex business processes and ensure consistency between different parts of the system, DDD can be implemented using other architectural styles such as layered architecture or microservices architecture. The key focus of DDD is on the modeling of business domains and the use of a common language to facilitate better communication between stakeholders and developers.
Q: Without being event-driven, won’t we have a solution that is tightly coupled? Which then goes against the grain of the principles of DDD?
A: Yes, being event-driven promotes looser coupling, and it is a good practice to use it in conjunction with DDD. However, being event-driven is not a mandatory requirement to implement DDD. DDD can be implemented using different architectural patterns, such as layered architecture, hexagonal architecture, or the vertical slice architecture, and still achieve loose coupling between the different parts of the system. It is up to the architecture and design choices made by the development team to ensure the desired level of coupling and modularity in the system.
Q: What is the difference between event sourced and state stored aggregates? When should I use either?
A: In Domain-Driven Design, an aggregate is a cluster of domain objects that can be treated as a single unit. An aggregate has one of its objects designated as the aggregate root, which acts as a gateway for accessing the other objects inside the aggregate.
Event sourcing and state storing are two different approaches for persisting the state of an aggregate.
In event sourcing, an aggregate’s state is represented as a sequence of domain events that have occurred to the aggregate. The events are stored in an event store, and the current state of an aggregate is calculated by applying the events to the aggregate. In other words, the current state of an aggregate is derived from the sequence of events that have occurred to it.
In state storing, the state of an aggregate is stored directly in a database. Whenever an aggregate’s state changes, it is persisted to the database.
The choice between event sourcing and state storing depends on the specific needs of the domain and the application.
Event sourcing is useful when:
- There is a need to keep a historical record of changes to an aggregate’s state.
- There is a need to track the reason for a change in an aggregate’s state.
- There is a need to reconstruct the state of an aggregate at any point in the past.
- There is a need to support optimistic concurrency control.
State storing is useful when:
- There is no need to keep a historical record of changes to an aggregate’s state.
- There is no need to track the reason for a change in an aggregate’s state.
- There is no need to reconstruct the state of an aggregate at any point in the past.
- There is no need to support optimistic concurrency control.
It is also possible to use a hybrid approach, where some aggregates are event sourced while others are state stored, depending on their specific needs.
As for the relation to DDD, both event sourcing and state storing are techniques that can be used in conjunction with DDD’s aggregate concept. In event sourcing, the domain events are part of the ubiquitous language, and they represent the history of the domain. In state storing, the state of an aggregate is also part of the ubiquitous language, as it represents the current state of the domain. The choice of which technique to use depends on the domain’s needs and the specific requirements of the application.