Remark from me. It was not easy to choose terminology, so I am ready to edit the translation in the process in order to improve the understanding of the text.Many are mistaken about what constitutes a CQRS. They view CQRS as an architecture, although it is not. CQRS is a simple template with many architectural features. CQRS is not the ultimate consistency, eventful, or messaging, it is not a model for reading and writing, and not the use of event sources. I will try to describe in a few paragraphs what a CQRS is, and then I will consider how it relates to other patterns.
CQRS Command and Query Responsibility SegregationWhen you start working with CQRS, you need to understand that CQRS is the creation of two objects that were previously one. The separation is based on the fact that methods are commands or queries (Meyer used the same definition in Command and Query Separation, a command is any method that changes state, and a request is a method that returns a value).
')
When most people talk about CQRS, they mean applying an approach to an object, which is an application service. Consider the following pseudo-service code.
CustomerServicevoid MakeCustomerPreferred (CustomerId)
Customer GetCustomer (CustomerId)
CustomerSet GetCustomersWithName (Name)
CustomerSet GetPreferredCustomers ()
void ChangeCustomerLocale (CustomerId, NewLocale)
void CreateCustomer (Customer)
void EditCustomerDetails (CustomerDetails)
Applying CQRS on this will result in two services.
CustomerWriteServicevoid MakeCustomerPreferred (CustomerId)
void ChangeCustomerLocale (CustomerId, NewLocale)
void CreateCustomer (Customer)
void EditCustomerDetails (CustomerDetails)
CustomerReadServiceCustomer GetCustomer (CustomerId)
CustomerSet GetCustomersWithName (Name)
CustomerSet GetPreferredCustomers ()
That's all. This is the whole picture of the CQRS template. No more. ... It seems entertaining when we describe it in this form, doesn't it? This division provides an opportunity to bring something interesting in architectural terms. And what is very important - it helps to stop the process of mental retardation, because two people use the same data, and besides that, they must also use the same
data model.The greatest advantage is that it recognizes different architectural properties when working with commands and requests ... For example, it allows us to place two services in different ways: we can place the read service on 25 servers, and the write service on two. Processing commands and requests is fundamentally asymmetrical, symmetric scaling of these services does not make much sense.
Task Based UI (Task Based UI)The task-based user interface is quite different from the CRUD-based interface. In it, you keep track of what the user is doing, and promote teams that represent his intentions. I would like to emphasize that CQRS does not require a task-based interface. You can apply CQRS in a CRUD application (although, for example, creating separate models will be much more difficult).
But there is one thing that really requires a similar interface - this is a domain model.
The application service layer in the domain model is the tasks that the system can perform. It is not just such processes as copying data into a domain object and saving it ... Do not forget about the behavior with the object. Before moving on, let's see what happens if we do it anyway.
In our ubiquitous language, there would be no other verbs other than “Create,” “Delete,” and “Change.” And as long as there are many domains in which the language is such, you should not use the principle of domain models to build a system.
The concept of such an interface does not intend to be part of the CQRS, and the domain may have similar commands, it must follow the user's intentions, which is very important. Was this update forced or not? What's the difference? Depends on what question you put before yourself.
Moving on to the next pattern that is misleading in CQRS
Sources of eventsI would like to clarify that when I use this term, I do not mean everything that is written in
bliki . I refer to the storage of the current state as a series of events and resume the system state by repeating these series of events ...
On the command side of the equation, since “reading” is no longer part of the domain, saving events can be a great way to maintain the current state. The value will increase if you decide on two separate models (a model for reading and a model for recording) and if you need to integrate them, then you will most likely do this through events. Since the event persists, why not just use one model to manage the state?
Messaging templateIt is not necessary to use this approach with CQRS. However, if you divide your data models, you will most likely use messaging between them, because in this case new possibilities appear.
Finally, I approached the last “approach”, although I don’t like to call it that, because in reality this is a concept that people put in their definitions of CQRS, which goes hand in hand with messaging ...
Ultimate consistencyThe principle of ultimate consistency is also quite often introduced between services. This is done in view of many architectural motives. But the biggest advantage is that it allows you to increase scalability and availability. If you remember the CAP theorem, it says that if there is no consistency, it reinforces the other two properties. This is very good for models if they are separated, but this is by no means a property of CQRS specifically.
Now we can see that CQRS is actually quite a simple template. Everything that revolves around CQRS is not only CQRS, but also the architectural properties of the integration of the two services. In other words, the most interesting thing is not the CQRS template, but the decisions that are made on the go. There are many interesting solutions that were involved in the system, where they decided to use CQRS ... but this is not only CQRS by itself.