Domain-Driven Design (DDD) is a great technique bringing designs closer to the domains we are working in, but too often we make early design decisions with a focus on structure, which is not the intention of DDD. Instead, we should start with the events in a domain, Russ Miles recently claimed while describing advantages of going “events-first” when building microservices.
Miles believes that besides focusing on structure, we are also focusing the ubiquitous language too much on things, especially on domain objects. To make things even worse we have also started to create libraries with domain objects for reuse across domain boundaries, effectively preventing different bounded contexts from evolving separately.
In Miles’ experience, this approach has become the default architecture style for enterprise layered architecture, the reason being to make things easier, not simpler or to help in improving a design. This has caused things, like entities, to move from being ubiquitous in one context to being canonical across all contexts, a direct contradiction with the ideas of DDD.
Instead Miles claims that we should start with what happens in a domain- the events. They are better in capturing the ubiquitous language in a domain, and often the easiest way to describe the domain, especially when collaborating with domain experts. He has found that this approach works well both when building a new system and when evolving an existing system.
The first step that Miles favours when working with events is Event storming, a modelling workshop technique created by Alberto Brandolini. The basic idea is to explore a domain by the things happening in it, the domain events, and capturing these events using stickers on a large modelling surface along a timeline. Examples of what can cause an event include a user action, something happening in an external system, and time passing. Events can also help in finding the boundaries within a domain; different interpretations of terms involved may indicate a boundary.
Another cause of complexity for Miles is using the wrong model for the wrong job. DDD has the repository pattern for dealing with persistent state but often uses the same model for read and writes. One advantage this gives is consistency, but if the needs are distinctively different we can gain significant benefits by separating reads from writes with different models.
Command Query Responsibility Segregation (CQRS) is a technique for doing this separation:
- Commands works on the write model and modifies it in a consistent manner, preferably on one aggregate, which will produce one or more events. Miles notes that the created events are not a side-effect, they are the actual result of the command.
- Queries uses one or more read models, optimized for the queries at hand. Events emitted by the write model and received by the read models ensure that the read models are updated to reflect the state of the write model.
Event sourcing is a natural extension to CQRS, where all events emitted by the aggregates are persisted and used to recreate the state of an aggregate, instead of storing the state itself. This ability to recreate state, according to Miles, is a way of reducing the fragility of state.
CQRS together with event sourcing bring other complexities like eventual consistency; Greg Young, who coined the term CQRS and is behind today's interest in event sourcing, notes that they are not top-level architectures. According to Young, they should normally be applied selectively just in few places, and he emphasizes that a whole system based on event sourcing is an anti-pattern.