DDD & co., part 3: Commands and events

tl;dr: Domain events are usually triggered by commands that express the wishes of the user. They belong to the ubiquitous language of a domain and hence are only valid within a bounded context.

The domain events defined in the past episode are the core of the ubiquitous language that acts as the base for communication in an interdisciplinary team. One of the peculiarities of this language is that it is only valid in a bounded context. Hence the ubiquitous language is not a universal one.

Domain events describe facts that have happened over time in a domain. Since they refer to something from the past, you name domain events using verbs in the simple past. As with anything that occured in the past, you can not undo them. In other words, you can't reverse time.

The only way to change the outcome of events that have already occurred is to create new events that neutralize them. This means that the effect of the events can be reversed by creating contrary events - but the events themselves cannot be reversed.

As an example, think of an already ticked off to-do. You can decide to resume work on it anyway, if you discover that it was ticked off for the wrong reason. So you do not consider it to be completed any more, but the fact that it once was ticked off remains.

Wishes become facts

All this raises the question of what causes domain events to be created at all. Whoever says that a to-do has been ticked off has to reckon next with the obvious question of who has ticked it off - and why.

The answer to this question is also the answer to the question about the cause of events: Ticking off the to-do was executed by a user in order to mark the to-do as completed. So, events are caused by user actions, to which the system then reacts with one or more events.

These actions of the users are encapsulated in so-called commands. They correspond to a wish, and they always have an intention that explains what the purpose of executing the command is.

In contrast to domain events, commands are described by verbs in the imperative. They therefore represent orders from users to the system, which when realized lead to the domain events. In contrast to events that can't be reversed and undone, commands at least can be rejected by the system.

This happens, for example, if the execution of a command depends on a validation that fails. For example, the system could reject the command edit if the corresponding to-do has already been ticked off. In this case, either no domain event or only an error event would be created.

A one-to-one relationship?

Except for error events, the simplest case consists of a 1:1 relationship between a command and a domain event: The command creates exactly one domain event, if it is allowed by the system.

However, this rule is not carved in stone. It is conceivable that a command creates several events, or that one and the same event is the result of different commands. There are also events that are not triggered by a command at all, but are, for example, time-controlled.

Commands and domain events are both part of the same ubiquitous language, and thus operate in the same bounded context. In the example of the to-do list, this is ultimately about planning, which is why one could call the context planning and describe the commands as follows:

  • note
  • edit
  • tick off
  • resume
  • discard
  • archive

In addition to the domain events, the commands and the context name are now fixed.

What is still missing is the actual logic, which is concerned with validating the commands and ensuring consistency. This task will be performed by aggregates, which will be discussed in the next episode.

Twitter Facebook LinkedIn

Golo Roden

Founder, CTO, and managing partner

Since we want to deliver elegant yet simple solutions of high quality for complex problems, we care about details with love: things are done when they are done, and we give them the time they need to mature.