CQRS

In addition to already discussed ways to design domain models as polymorphic classes using object-orientation and using functions operating with instances of record types for some functional languages, there is a different way to express state transitions inside the domain. With this, I mean the CQRS patterns, coined by Greg Young a decade ago.

The term got its origins from the CQS - command-query separation, formulated by Bertrand Meyer, which states that object methods are separated into two categories. These categories are:

  • Commands, which mutate the system (most often the object) state and return void.
  • Queries, which return part of the system state and do not change the state of the system. It makes queries side-effect free (except things like logging) and idempotent so that they can be executed many times and the result would be the same.

CQRS, which states for command-query responsibility segregation, takes this principle outside of an object. It is the same principle, applied on a system level. Development of this pattern took a few years, from 2007, when Greg presented the early vision of it on the InfoQ conference, down to 2010, when the summary paper was published (https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf). It also took Google a few years to recognize the acronym. A few years back, people who were eagerly looking for CQRS got a suggestion from Google "did not mean CARS?", but today the pattern is widely known and praised.

Separating commands and queries on a system level means, that any state transition for the system can be expressed by a command and such command should be handled most efficiently, optimized to perform the state transition. Queries, at the other hand, return data derived from the system state, which means that queries can be executed differently and be optimized for reading the state or any derivative of state if such derivative exists.

Such separation is beneficial in scenarios when there is a clear disbalance between writes to the database and reads from the database. A typical business or consumer-oriented application is massively imbalanced towards reads. However, stereotypical implementations are optimized for writes, using normalized relational databases, where writes can be performed rather efficiently, but reads require numerous joins and extensive filtering.

CQRS with a single database

In simplest scenarios CQRS can be implemented just by using database-mapped domain objects to execute operations on a domain model that mutate the system state (usually it is done using ORM tools) and using direct SQL queries with joins across multiple tables to retrieve the system, completely ignoring the domain model class hierarchy. It leads to great optimization of reads and at the same time rightfully increasing awareness of the state persistence mechanism. While this method is entirely legit, one should realize that in this case queries need to be either adequately abstracted from the data persistence layer, or be designed outside of the domain model.

In more complex scenarios, we could have not only two different "clients" to manipulate the same domain entities, but also split these entities apart. We will be looking close to such techniques later in this book when we'll discuss event-sourcing.

You might be wondering why CQRS made it to the domain model design section of the book, instead of being explained in the part that belongs to the implementation. The reason for this is that CQRS makes commands and queries first-class domain objects. Domain events should always be seen as first-class domain objects, but in more advanced CQRS implementation models, domain events play the crucial role in keeping the whole system consistent and therefore the part of domain events becomes even more critical.

This is why CQRS is mentioned right here, for us to realize that we should not only include classes with properties and methods to our domain model, but things like commands, queries and domain events belong to the model just as much, and we will be looking at how to model all these elements in the next section.

My final note is that EventStorming is valuable no matter if you use CQRS or not for your implementation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.171.153