Command Query Responsibility Segregation (CQRS)

 

Link CQRS stands for Command Query Responsibility Segregation. At its heart is the notion that you can use a different model to update information than the model you use to read information.

Link

View at Medium.com

Commands

A command tells our application to do something. Its name always uses the indicative tense, like TerminateBusiness or SendForgottenPasswordEmail. It’s very important not to confine these names to create, change, delete… and to really focus on the use cases (see CQRS Documents at the end of this document for more information).
A command captures the intent of the user. No content in the response is returned by the server, only queries are in charge of retrieving data.

Queries
Using different data stores in our application for the command and query parts seems to be a very interesting idea. As Udi Dahan explains very well in his article Clarified CQRS, we could create a user interface oriented database, which would reflect what we need to display to our user. We would gain in both performance and speed.
Dissociating our data stores (one for the modification of data and one for reading) does not imply the use of relational databases for both of them for instance. Therefore, it would be more thoughtful to use a database that can read our queries fastly.

If we separate our data sources, how can we still make them synchronized? Indeed, our “read” data store is not supposed to be aware that a command has been sent! This is where events come into play.

Events

An event is a notification of something that has happened. Like a command, an event must respect a rule regarding names. Indeed, the name of an event always needs to be in the past tense, because we need to notify other parties listening on our event that a command has been completed. For instance, UserRegistered is a valid event name.
Events are processed by one or more consumers. Those consumers are in charge of keeping things synchronized in our query store.
Very much like commands, events are messages. The difference with a command is summed up here: a command is characterized by an action that must happen, and an event by something that has happened.

 

Link Command Query Responsibility Segregation (CQRS) is an architectural pattern that separates reading and writing into two different models.

This means that every method should either be a Command that performs an action or a Query that returns data. A Command cannot return data and a Query cannot change the data.

So thinking back to the Ecommerce example from earlier, we would need to create two separate models for reading and writing. We would have an Order Aggregate that would have only Command methods and a OrderRepository that could only add and update Order objects. This would be the write model.

In order to read data from the database we would need a separate read model. For example, this might be a dedicated Repository that is specifically tuned to return the correct data for an appropriate view.

By splitting the application into dedicated read and write models, you move the responsibility into dedicated objects. The write model does not need to be concerned with returning data and the read model can be specifically written to return the correct data to satisfy the application’s requirements.
Using two separate data stores
The main principle behind CQRS is that you use two different models for reading and writing. However, the actual implementation of this idea can be handled in a number of different ways.

Firstly you might use two different models that talk to the same database. When a user issues a Command, the write model will update the database and then the read model will query the database to present the data to the User Interface. This is good solution for applications that require synchronous processing and immediate results.

However for other types of applications, it might be desirable to use two different data stores.

Rather than writing and reading from the same database, the write model will send commands to one database, and then the data will asynchronously update the read database.

This approach has a number of benefits.

Firstly, this allows you to store the data in the read database as denormalised data. This has the advantage of allowing you to write more efficient queries, but also store data that makes more sense as to how it should be displayed in your application.

Secondly, it allows you to scale the two different sides of your application separately. If you have a very high number of reads, and a low number of writes, you can scale the query side of the application without worrying too much about the write side. This would be advantageous if your application is required to do intensive reporting queries.

Leave a comment