Around the web there is a lot of noise about CQRS and Event sourcing. Almost everybody involved in a layered application is now trying to see if CQRS can fit in its current platform.
I also found some nice tutorial series about CQRS and some good explanation of event sourcing but what I didnt see yet is a nice architectural overview of these two techniques and when they are needed, what are the pros and the cons.
So lets start as usual on my blog with a brief introduction to CQRS. In the next post I will show Event Sourcing.
CQRS, when and who?
Around the end of 2010, Greg Young, wrote a document about Command Query Responsibility Separation, available at this link. The documentation highlights the advantages of this pattern, the different concepts of command UX (task based UX), the CQRS pattern and the event sourcing mechanism. So, if you want to read the real original version of this architectural pattern you need to refer to the previous mentioned doc.
In the meantime also M. Fowler started to talk about it, with the post CQRS. Without forgetting the series of posts published by Udi Dahan (the creator of NServiceBus).
Last but not least, Microsoft patterns and practices created a nice series related to CQRS called CQRS Journey. Its a full application with a companion book that can also be downloaded for free form MSDN. It shows what would really happen within your team when you will start to apply concepts like: bounded context, event sourcing, domain driven design and so on.
CQRS in brief
In brief CQRS says that we should have a layer in charge of handling the data requests (queries) and a layer in charge of handling the command requests (modification). The two layers should not be aware of each other and should/may return different objects, or better, the query layers should return serializable objects containing information that need to be read, while the command layer should receive serializable objects (commands) that contains the intention of the user.
Why? Because during the lifecycle of an application is quite common that the Logical Model become more sophisticated and structured, but this change may impact also the UX, which should be independent from the core system.
In order to have a scalable and easy to maintain application we need to reduce the constraints between the reading model and the writing model.
The picture below show a brief explanation of how a CQRS application should work (this is just one of the possible architecture and its not the silver bullet solution for CQRS):
We will use REST API to query the data because they provide a standard way of communication between different platforms. In our case the REST API will host something like the following API URLs:
|Get Persons||api/Person||api/Person?Name eq Raf|
These APIs dont offer Write or Delete support because it will break the CQRS principles. They return single or collection of serializable objects (DTO), result of a query sent previously by the user.
For the write model we can use WCF, send a command message (see pattern here) and handle the command on our server side. The command will change the domain model and trigger a new message in the bus, a message that acknowledge everybody about the status changed. It will also update the write datastore with the new information.
Whats important is that the command is not anymore a CRUD operation but the intent of the user to act against the model.
How does it work?
The first question I try to answer as soon as I start to read about a new architectural pattern like CQRS is, yes nice but how it is supposed to work?. Usually I dont want to read code to understand that, but I would like to see a nice diagram (UML or similar) that shows me the flow of the application through the layers, so that I can easily understand how it is supposed to be done.
I tried to apply this concept to CQRS and again, I split the diagram into read and write.
The read part
- A User ask some data to the view
- The view send an async request to the REST API
- The REST API query the datastore and returns a result
- The result is returned by the callback in the view
- The User will see the data requested when the view refresh
The write part
- A User send a command from the UI (save, change, order
) containing the intention of the user
- The command is sent using JSON to a WCF endpoint (one of the 1,000 possible solutions to send a serializable command) and return an acknowledgment
- The WCF endpoint has a command handler that will execute the command
- The command changes the domain which
- Raise an event
- Save its state on the database
- The service bus receive the events and acknowledge the environment
(for instance, here you can have event sourcing that listen to the event)
- The user interface is updated by the events and the acknowledgments
As you can see, Domain Model, Event Sourcing, Data Mapping and Service Bus are optional and additional architectural patterns that can be merged with CQRS, but not part of it.
With CQRS your primary concern is to loosely couple the reads from the writes.
CQRS Pros and Cons
Ok, this architectural pattern (there are different opinions here ) its quite helpful but there are some cons that we should keep in consideration when we want to adopt CQRS.
When not to use it?
- You have a simple (no complex logic) application that executes CRUD, in this case you can easily map the domain with an ORM an provide DTO back/forward to your client tier. Even the UX can reflect the CRUD style.
- Your concern is not about performances and scalability. If your application will not be on a Saas platform, but only internal to a company, probably CQRS will over engineer the whole architecture, especially if the user interface is complex and data-entry based.
- You cant create a task based UI and your customer doesnt have yet the culture for a custom task based application.
Also, remember that CQRS is just a portion of your architecture, the one that take care to expose data and/or receive commands. You still have to deal with the data layer, your domain or your workflows, your client logic and validation and more.
If you have already analysed those concepts and you feel confident about your architecture, then you may consider to see how it will fit CQRS inside it, or you can simply start by splitting the reading endpoints of your API from your writing endpoints. Especially because right now the primary requirement for a modern application is to expose data through a simple and standardize channel like REST, so that the integration with external platform its easier and more standardized.
There are a couple of alternatives that we can keep in consideration if we dont want to face the complexity of a CQRS solution. It really depends on what type of User Experience we need to provide.
Data entry application
In this case its quite easy to keep going with a solution similar to the classic CRUD applications, maybe a sort of master/details approach where a View is mapped to a Domain Entity which is bind to the database using an ORM.
This is a classic, very efficient and productive way of creating a CURD application with the unnecessary over engineering SOA on top of it. We dont need DTO and probably we will just have a data-layer that takes care of everything.
SOA platform or API public
Sometimes we may need to provide access to the system through a public API, at the moment REST seems the most feasible and globalized way. In this case we may still have a Domain and an ORM behind the hood but we cant directly expose those to the web. So? So we need a DTO and a communication channel where we can expose those simple objects in order to send and receive data in a standardized way.
In this case we are starting to face more complexity due to the SOA constraints:
- Reuse, interoperability and modularity
- Standard compliance
- Service identification, classification and categorization
In this case we can have a client app that works using ViewModels bind to the DTO exposed by our Web API, but we are still not using CQRS at all because we dont distinguish between data and intention of the user.
I hope that my two notes can give you a bit more clear picture of what is CQRS and what is supposed to be from my point of view, of course!