When starting out with CQRS, designing the ‘events’ is not always obvious or easy. The more experienced you are, the more likely your habits will lead you astray. This post will help you spot the problems early and stay on the right track.
Watch out for event names that include the word ‘Updated’ or ‘Edited’. These are usually associated with state based operation like those found in REST (Representational state transfer) or CRUD (Create, Read, Update and Delete). Through heavy use of ORM’s like Entity Framework and NHibernate, we have trained ourselves to think in CRUD terms. In the classic bank account scenario, when depositing money, what would make a good event name? A sensible answer may be ‘AccountUpdated’, why not, after all you have just updated the account, right? So here’s the issue. Can you read from the name of the event what just happened? AccountUpdated could refer to a deposit, a correction of the account holder name, a credit or the application of a charge etc. Event message names should reflect what just happened, as well as describe the actual change in it’s content. In fact, the words you use for event names are important and should reflect the ‘ubiquitous language’ of the domain.
Another indicator of bad event naming can be found when looking at the event stream. Would a domain expert be able to infer from the names alone what has just happened in the system? The following 2 event streams clearly illustrates the difference:
Stream 1 – Badly named events
Stream 2 – Well named events
This also makes it easier to debug your application. Out of place events stand out in an event stream when they are clearly named.
Another common temptation is to put the view model fields into your event. The key purpose of an event message is to represent what has just happened. The message should contain the information needed to rebuild the state of the domain object. It may well end up looking like a view model but that should not be the driving force behind its design. Given the bank account example above, you can spot this kind of issue when looking at the fields. A deposit event may have the current balance but will have have the amount deposited. i.e. the change in state!
Events are also subscribed to by de-normalisers which can use the information to build out a highly optimised read model. By keeping the contents of the event focused on describing the state change, it gives you greater scope to produce better and potentially more diverse read models.
This seems obvious but remember that an ‘Event’ is always something that has happened. It should, therefore, reflect this in its name being in the past tense.
Here is a list of common fields found in a typical event and what they are used for:
* Idempotence refers to the ability of a system to produce the same outcome, even if an event or message is received more than once.
There are no hard and fast rules as to what to include, however, the list above will give you some guidance toward the right direction.
Given the reliance of events to be the source of truth, it is vitally important to ensure they are immutable. That is to say, once an event object is created, it should not be possible to change any of its fields. This property of messaging, in general, has some profound implications on your over all system. Immutable objects are far easier to test with, can be reliably sent around a system or communications bus and play well in a multi threaded environment. I follow a very simple pattern when creating my events:
The 6 indicators described above are just rules of thumb. Use them as a guide, not a rule book. They should help you avoid some common early mistakes. The process of naming events gets easier as your knowledge of the specific domain grows and matures. It is often harder to find the right names early in a project and usually hints at missing concepts and lack of understanding. When you do get it right and your events form the basis of a common language, domain experts are then able to clearly reason about your system and feel able to communicate their ideas and requirements far more clearly.
I'm a professional software engineer of near on 15 years. Lucky enough to work for a small but rapidly growing company in London called Redington. They have given me the technical freedom to learn some cutting edge technologies like CQRS and Event Sourcing. Now I'm sharing what I learn here.