CQRS

What Is CQRS?

What is Command Query Responsibility Separation—CQRS? I have noticed that software engineers sometimes confuse CQRS with Event Sourcing. Although Event Sourcing is related to CQRS, the two concepts are separate and distinct. 

Event Sourcing represents a high-level architectural pattern. Here the system records incoming state-changing events, so-called commands, and then generates the system’s current state from the recorded commands. We’ll take a deep dive into Event Sourcing another time.

Let’s take a look at CQRS.

Firstly, what are Queries and Commands?

These terms are also known to us under different names: reads and writes

Commands or writes, alter the data—or state—within a system. In this context, a ‘write’ has little to do with the traditional idea of writing to disk. Think of it more as a logical rather than a physical write. It’s a system state change—whether to memory, disk or remote service. 

Queries, or reads, are requests for data from a system. Again, we are referring to logical rather than physical reads—the data can come from disk, memory, etc.

 

OK, so what is CQRS? 

CQRS is the idea that we should compose our systems of command and query operations and keep these separated whenever possible. 

Interesting. But why should we separate read and write operations?

Because when we encounter a function that queries for data while at the same time making system state changes, we may not always understand what’s going on. The reverse is also true—functions modifying state shouldn’t return a value—we haven’t asked for data. Both are confusing situations.

An example may help.

 

What do you make of this method signature? 

  bool SetStatus(bool newStatus);

Judging from the signature alone, it appears to set a status. But what about that return value? What is its purpose? Why does this state-changing method return a boolean value? Is it the value of the updated status? Or is it an indicator of whether the update operation succeeded?

 

We’re left scratching our heads. It’s a command with query aspects. Confusing.

CQRS offers wise counsel: 

Avoid mixing query and command behaviour.

As much as you can, make it one or the other, not both.

Why as much as you can?

When a command creates an entirely new entity, we may discover that it’s frequently advantageous for the caller to have access—via a return value—to the new object. 

For example:

  public async Task<Customer> Register(CustomerRegistration registration);

This method tries to register a new customer in a system. If the method succeeds, it returns the newly created Customer. A return value seems appropriate—the returned Customer object likely contains essential identifiable information, such as a CustomerNumber.

What if the method does not succeed?

It will throw an appropriate exception relaying the specific problem.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply