DDD & co., part 2: Semantics over CRUD

tl;dr: Domain-driven design aims to improve communication in interdisciplinary teams. This is done by defining bounded contexts with their respective ubiquitous language. For that, domain events are the most important building blocks, as they describe facts that have happened in the domain.

The first episode mentioned the TodoMVC application, a simple task list, which at first glance looks like a prime example for software development using CRUD: There are to-do's, and they can be created, updated, deleted and read. This is CRUD in pure culture.

We have internalized this approach to such an extent that we hardly notice any more that the generic applicability of CRUD comes at a high price, the lack of semantics. Neither domain experts nor users think in the verbs CREATE, READ, UPDATE and DELETE. They lack any significance because their context is a purely technical list: The relational database table. There is nothing wrong with this if the domain is a SQL table, but these verbs are not very useful when talking to domain experts and users.

Missing semantics leads to misunderstandings

Even worse, they are not only useless, they are even harmful! As developers, we automatically and unintentionally map every business process to CRUD. We don't realize that we don't understand the domain language at all and that we create a lot of confusion along the way.

Constant mental mapping is one of the reasons why working in interdisciplinary teams is so tedious. Everyone involved believes that they are talking about the same thing, but in fact everyone is talking at cross purposes.

Those who deny this claim at the same time that a language which essentially does not use verbs is as expressive as a language which can express and present activities in a multifaceted way. Steve Yegge shows in his blog post Execution in the Kingdom of Nouns in a very vivid and entertaining way how wrong this assumption is. But what other options do we have?

Semantics instead of CRUD

A simple way is to ask the domain experts and users to describe what events can have occured in the application. If you omit the four verbs of CRUD, you will probably get answers to this question similar to the following:

  • A task was noted.
  • A task was ticked off.
  • A task was discarded.
  • A task has been completed.

This much better reflects the way people think about a task list than what a developer would typically do. The statements are colloquial, and it is possible to get multiple formulations for the actual (or supposed) same thing. This can be discussed, however, because the choice of words makes different thoughts explicitly visible.

For example, it is now possible to talk about whether A task has been ticked off means the same action as A task has been completed. If both statements actually denote the same thing, it would be helpful to agree on a common terminology. If not, two different concepts have been discovered, which otherwise might have remained hidden - and which would have been noticed as wrong much later, namely in the implemented application.

A ubiquitous language

The goal of the process is to find a common language so that all team members not only understand each other, but also understand what is being talked about from the domain's point of view. However, this language is only valid in a limited context, it is not universal. This is because task lists can serve different purposes, which is reflected in the choice of words.

Therefore, it is important to know the context when you want to express yourself with someone in a domain language. For this very reason, we speak of a bounded context within which the ubiquitous language applies.

What does this language look like for the task list? To be able to answer this question, one has to ask for and question the intention of the users and understand why actions are carried out. For example, the original intention of the users is not to forget a task that needs to be done. Therefore, the task is noted.

In contrast, it is not the intention of the users to add an entry to the technical construct of a list (CREATE). For them, it is not even important that from a technical point of view it's a list at all - for the intention of the users it could just as well be a grid containing tiles.

The remaining verbs are quickly found: A task can be edited, it can be ticked off, and it can be resumed if it has been ticked off for the wrong reason. A task can also be discarded if it is not relevant any more. Ticked off tasks can also be archived when they no longer need to be present.

Intention leads to domain events

It is noticeable that all these verbs are in the past tense. The reason for this is that they are domain events relevant to the domain of the task list. It is also noticeable that more than three verbs (CREATE, UPDATE, DELETE) have been found, so the semantics of a task list itself seems to be more complex than expected from a database's point of view.

To ensure consistency with the user interface of the TodoMVC application, we recommend to model the verbs in English. In general, however, events should first be formulated in your mother's tongue, and then translated into the language in which the core of the business logic is described. This way you get the following events:

  • noted
  • edited
  • ticked off
  • resumed
  • discarded
  • archived

Finding these domain events is the first step in modeling an application with domain-driven design. Even if the result may not make you that enthusiastic yet, there is one thing that has already been achieved: There is a common domain language, whose meaning has been carefully shaped and which did not evolve accidentally.

This is the ultimate goal of DDD: To improve communication in interdisciplinary teams so that better software can be built in less time, solving actual problems and fulfilling the actual needs and wishes of the users. The only way to achieve this goal is to talk to each other as early as possible.

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.