Event Storming to Find the Domain
Previously we constructed a story map of our job board application and now we are going to use event storming to discover our commands and bounded contexts.
What is Event Storming
If you are unfamiliar with it, event storming is a collaborative workshop process for discussing user stories and finding domain events. You generally work with a small group of domain experts and focus on what happens as users interact with the application. Events are captured in domain terms and the collaborative nature of the workshop builds a shared understanding of the domain and what needs to be built.
Since I’m still a team of one I’m not running a workshop. I’m going to do my best to simulate the process and walk through the steps of event storming and the follow on activities.
The Story Map
In the previous post on story mapping we discussed taking the user journey and building a story map. We ended that post by firing a tracer bullet through a set of stories that provided value and created the backbone for the entire application. Here is what it looked like:
Clear the Map
Everything below the stories identified by the tracer bullet is possible future work. I’m going to clear them off along with our tracer bullet so we can focus on our stories.
Why do I clear the map? Because I don’t want to think about the future work. Isn’t the future work important to think about? Yes and No. Hopefully,through collaboration, everyone on the team has an understanding of where things are headed, but I have found that if you leave everything on the map during event storming the team will begin to try to squeeze in things that may (or may not) come later. This can lead to over engineering and delays. What you should be focused on is providing value as quickly as possible to the customer.
Identify the Command and Query Stories
Now that we have our tracer bullet stories in isolation we should recognize that there are two kinds of stories.
- Stories that change the system (Command)
- Stories that query the system (Query)
Command stories change the system and produce domain events. Query stories view the state of the system in different ways. By having these two types of stories, we are following the pattern of Command and Query Responsibility Segregation (CQRS). If you find a user sub-task story that seems to do both (change the system while viewing its state), you should analyze it and break it down into two or more Command and Query stories. Going back to the story map, I’ve put a red circle around the Command stories and blue circles around the Query stories.
Storm the Events
Now comes the fun part. We get to think about the Command stories and what kind of events would be produced by each story. Some things to keep in mind.
- Collaborate - This is a team effort
- Use words from the domain
- Events are things that happened, so use the past tense.
- More than 1 event can be produced.
- The same event can be produced by two separate stories
I worked through the story map and decided on the following events:
- User Registered
- User Logged In
- Job Posted
- Application Started
- Work Experience Added
- Resume Attached
- Application Completed
- Applicant Contacted
So we can see that the words of the domain are starting to emerge. I chose to use the word Applicant for the person applying to a job. I thought about using the term Job Seeker, but stuck with words that were more closely tied to the action of applying. Application Started and Completed came out of some brain storming. The applicant should be able to add multiple work experiences and attach a resume and change their mind and attache a different resume and then complete the application. I think the logical thing would be to have an event that signifies the start of the process. Going back to the story map I placed the events under their respective stories:
Work Backwards to Commands
We have the events, so now we need to figure out what commands trigger the events. Starting with the event, we think about what command would logically create it. Some things to remember when doing this:
- Commands do not have to follow the same name as the event.
- Commands are in the present tense
- Different commands may produce the same event
- Not all Commands are from a user or through user interaction
Here are the commands I came up with:
- Register User
- Log In
- Apply to Job
- Enter Work Experience
- Attach Resume
- Complete Application
- Contact Applicant
In practice, I like to put the events on a white board next to the command(s) that generate them.
Identify the Bounded Contexts
Now that the commands and events have been identified they can be grouped together into cohesive sets. For example, the registration and login command and events can be grouped together as they are directly related to the user. The commands and events pertaining to applying for a job can be grouped together leaving the ones associated with posting a new job together by themselves. Grouping them together this way helps to identify the bounded contexts. The bounded contexts can then be given names from the domain.
We have found our events, commands, and identified our bounded contexts. But what about those other stories? The query ones? Is there anything we can do with those?
Examine the Query Stories
The query stories describe the views or how users see the system. In our system these views will be built from the events. We now know the events, so lets take another look at these stories.
Determine the Query Building Events
Not all the events will be used to populate the query views. We can start by trying to determine which events will contain the data required by the views. I took a shot at this and came up with:
Unfortunately we still don’t have any idea of what kind of data will be needed by the views. In turn that means we don’t know what kind of data will need to be supplied by the events. How do we solve this?
UX Helps Identify the Data
An effective way of solving the problem is to use wireframes of the user interface. I don’t have a UX expert working on this (which I highly recommend) but I can make some reasonable guesses. By putting the wireframes in order over the stories it becomes easier to see how a user will interact with the application and what kind of data they will need.
Now it becomes easy to see the kind of data the events need to provide which in turn dictates the kind of data the commands need to contain. Next up we will dig further into this when we discover our aggregates and design our events.