Event Modeling on prooph board

This page provides a step-by-step guide of how to design an event-driven system using Event Modeling on prooph board. The resulting artifact is called Event Map.

Throughout the guide we’ll use an example from a car rental business.

Start from an Idea

Let’s assume we are a startup team that wants to develop a new car rental SaaS from scratch. We just finished our Big Picture Event Storming and now want to get our hands dirty with some product development.

The first module of our new SaaS should be some kind of Fleet Management. We need to be able to Add a Car to our fleet and Create a Rental Offer for it so that it can be booked by customers.

Right now, we are in our first Event Modeling Design session. We should look at each event from above and think of it as a Slice of the new system.

Where - Identify the Entry Point

In the early version of our SaaS, adding a car will be a manual task. Later we want to add batch imports and derive car details from a third-party service, but for now we keep things simple since we want to have a fast feedback loop.

So we start with a UI Card to sketch a rough idea of a UI screen showing a list of cars in the fleet and a button to add a new car.

Instead of using UI cards, some teams prefer a more visual approach by uploading screenshots from wireframes (especially when UX is part of the team). That’s totally fine. The only advice is that those wireframes should not be too detailed as this can become a bottleneck in the flow.

Who - Identify the Actor

A Slice either represents an action that a user can perform in the system or an automated process step. You can associate a story to it and for this you need an Actor (aka. Role or Persona).

As a Fleet Manager
I want to add a car to the fleet
so that it can be booked later.

Pull a new Slice from the sidebar. Each Slice has one or more user lanes with an Actor Card as a label. Either change the existing Actor or add another lane, then put the UI card into the corresponding lane.

What - Identify the Intention

The Fleet Manager wants to add a car to the fleet. Adding a car is their intention, and they can tell the system about it by triggering a command. Let’s put a Command Card into the API lane of the Slice. When the system accepts and processes the command an event occurs, so we also move the Car Added Event Card into the slice. Events are placed in the module lane of the system module where they occur. In our case, this is the Fleet Management module.

Input - Which Information

As a next step we should define which information is needed for the command to be accepted by the system. In a collaboration session the best way to do that is by using an Information Card per field or property. This allows all participants to contribute by adding cards in parallel.

After a collaboration session you might want to clean up the Event Map and structure such information in the Card Metadata

How - Command Handling

Some service or function in the system needs to handle the command. And for each one you should ask: Do we need to check some rules when handling the command? If the question is answered with yes, write down the rules on a Business Rules Card and place it between command and event in the same module lane as the event.

Output - How does State change

Handling a command usually results in some changed state in the system. The state change is represented by an Event Card (like Car Added here) and the new/changed state (or the new/changed information) can be visualized by using an Information Card again.

One Slice at a Time

As a last step, we should mark the Slice as planned.

We put Slices along an imaginary timeline from left to right just like we do with events in a Big Picture Event Storming. You might have noticed that the Cards within a Slice are ordered from top to bottom: UI > Command > Business Rules > Event. This illustrates a specific point in time.

Each Slice should only contain one action (Command > Business Rule > Event) not more. This ensures, that the system as a whole is composed of small, simple building blocks. Connect the Slices through events and/or steps in the UI.

If you strictly follow this rule and learn how to design a system in such a way, you’ll notice after some time that your code is very clean and easy to understand. Refactorings become a no-brainer. You can add new slices as reactions to existing events. You can replace or remove slices. And you can do this for years without increasing complexity. Sure, your system becomes larger, but zoomed-in to a single Slice it will still be as simple as the one we just designed. The Event Map will help you navigate through the system and keep an overview. So make sure that it stays in sync with the implementation.

Story Writing

Story Writing is optional. In fact, you already have all the information on the board, writing it down in a ticket might be useful, but it is not strictly necessary.

Now that we have designed a Slice on prooph board, we can easily create a ticket for it. We use a Github issue here as an example, but this could also be a User Story in Jira or similar.

Here is our recommended issue template:

Section Description
Title Slice Name
User Story Derive from Actor + Command + Event(s)
Image Make a screenshot of the Slice on proooph board -> paste in issue
Link to Event Map Right click on prooph board Slice -> choose “Direct Link” -> paste in issue
Sub Tasks Split design and development work into small chunks

With some routine you can create issues using this template in less than a minute. Compare this to your normal story writing and task breakdown sessions!

You can also link the prooph board Slice with the issue by choosing “Link to Task” from the Slice context menu:

Feature Slicing

The key for any system to be maintainable over a long period of time is composition. A complex system should be composed of simple parts. When designing Slices around events, you can use a heuristic to keep them simple:

Too much cards in a single Slice are an alarming signal that the feature is probably too big.

Let’s have a look at the next event on our Event Map: Car Updated. Sounds like a simple CRUD operation, right? But wait, what exactly do we want to update? A design session should give us some insights.

We quickly realize that a car is going to have a lot of information assigned to it. When adding a car, we only focused on the bare minimum information needed. The update command on the other hand should support the full set, even thought it’s a lot.

We know that the Fleet Manager will update a car step by step. Not all information is available right from the beginning for example the licence plate or the equipment list. So does it make sense to have this huge update command? Wouldn’t it be better to split the command into smaller chunks and give the task more structure?

So instead of one big update command, we now have 5 distinct commands for updating different parts of a car. Those commands can be represented as 5 tabs in the UI or a 5-step editing process. In the backend we gain some benefits from this design:

1. Fine-grained events

If we want to add more automation later, the events can act as triggers. Let’s say we want to run an image optimization process whenever an image is assigned to a car. To add this feature, you don’t need to touch existing code at all. Just implement a listener on Image Assigned events and call it a day!

2. Simple Slices

What if we later discover that car equipment can always be changed no matter if the car is booked or not, but basic and technical information are not allowed to change? You can adjust the business rule for the Set Equipment command without any risk of introducing a bug in the other commands!

3. Possibility to analyse behavior

We want to make our users happy and help them with our software as much as we can. We do have the feeling that fleet managers spent a significant amount of time maintaining car information. To validate our assumption we can look at the events and see how often a car is updated until it is ready to be published. We can also see what information is updated last or more often than other information. This can give us an idea how to improve the system and provide a metric to measure if our changes improve the situation or make it worse.

Prototyping

The Event Map is basically a blueprint of the system. You can use Cody Play to translate it into a working prototype.

results matching ""

    No results matching ""