The Evolution of Events in Domain Driven Design
Most aspects of modern software engineering can be found in or traced back to Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans. EventSourcing is something that has evolved in the world of DDD practitioners and has become more mainstream in recent years. Why are Events so important when designing and implementing software, and why are they so well suited to Domain Driven Design?
Software is complex
Software models the real world and the real world is complex. Keeping the complexity to a minimum mitigates the risks that complexity brings in successfully delivering and maintaining software. There are two types of complexity. Essential Complexity and Accidental Complexity:
Essential Complexity exists because of the real world complexity that software implements. We can't avoid Essential Complexity.
Accidental Complexity is introduced by us as software developers as we design and architect systems. Accidental Complexity can and should be avoided, although it isn't always easy to identify and minimise.
How we can avoid Accidental Complexity
When designing software it helps to be explicit about where essential complexity exists. Everything else should be simple. To begin with, it helps to be explicit about what is an Entity and what is a Value Type. Value Types are immutable so they should be very simple. Entities will contain Essential Complexity because they are mutable, they have an identifier and we need to manage state changes during their thread of continuity.
Events signify a change of state
An Event signifies that the state of an Entity has changed. This is where your Domain Model's Essential Complexity is:
Storing and updating state can be complex in itself
Confirming the new state is valid, and handling what to do if it isn't is complex
Does the state change trigger another Event, or chain of Events, that can lead to further state changes?
Does anybody or anything need to be notified of the Event?
Can Events happen at the same time?
Events describe an Entity's Thread of Continuity
Entity's have a thread of continuity. We are interested in every Event that happens in an Entity's Thread of Continuity. This is why Events fit so well with DDD.
Event Sourcing is a good way to implement the thread of continuity on Entities in your Domain Model With Event Sourcing, rather than updating the data persisted for an Entity, the data on the Entity itself never changes after it has been created. You persist Events that can be linked to an instance of an Entity by the Entity's Identifier. To see the current state of an Entity you load the persisted data into the Entity and then apply the Events in the order they happened.
A common example of Event Sourcing is a bank account that is created with an opening balance. Transactions then happen on the account. To see the current state of a bank account you start with the opening balance and apply every withdrawal or deposit made on the account since it was opened.
An Event Sourcing implementation enables you to audit the events that have occurred on an Entity throughout its lifetime, especially if each Event you store contains information about when it happened and who triggered the Event.
EventStorming - Designing Event Sourced Domain Models
A great way to design Event Sourced Domain Models following a DDD approach is Alberto Brandolini's EventStorming. In an EventStorming workshop, Software Developers and Domain Experts talk about the Domain and map it out using sticky notes. They start by adding an Orange sticky note for each event that occurs in the Domain on a timeline. Further sticky notes are added to each Orange one to indicate the Command that triggers the Event, the Role that runs the Command, and Policies that describe other Events that are triggered by each Event.
The output of an EventStorming workshop is a Domain Model represented by sticky notes centred around each Event that happens in each Entity's Thread of Continuity. This truly is Domain Driven Design and gives a Domain Model that can be implemented directly in code using Event Sourcing.
Events fit so well with the Domain Driven Design approach because we can use Event Sourcing to implement the Thread of Continuity of an Entity. We can design a Domain Model based on the Events that happen throughout the Thread of Continuity of each Entity using EventStorming workshops. By understanding that Essential Complexity in Software Systems happens when state changes we can be explicit about the Events that change state, encapsulating Essential Complexity in these Events. This helps identify and reduce Accidental Complexity that we might otherwise introduce outside of Events where the implementation should be simple.