CQRS: Command Query Responsibility Segregation
Jason Gerard and I were talking about document databases the other day, and he said "Have you heard about CQRS?" This was news to me, so I started doing some research. Wikipedia, which usually provides good information, said the following "CQRS is simply the creation of two objects where there was previously
only one. The separation occurs based upon whether the methods are a
command or a query (the same definition that is used by Meyer in Command
and Query Separation, a command is any method that mutates state and a
query is any method that returns a value)."
Ok, that was clear as mud. Maybe a picture will help.
This diagram is from Udi Dahan's excellent presentation on CQRS at the London .NET User Group. Udi is an amazing presenter & his presentation is well worth the watch. He is also the guy behind NServiceBus.
Here are the basics as I understand them:
- In a multi-user environment, data on the screen is always stale. Due to this fact, we don't need a complicated ORM to pull "live" data out of our OLTP database. Instead, we can use a persistent view model to pre-cache the data needed by the UI.
- The user interface needs to capture the user's intent, not just their input. It can then build up commands that are submitted asynchronously to the services layer. This is a more imperative way of doing things and provides the opportunity to inject business processes without changing the user interface.
- Validation is performed at both the UI & services layer using a shared component. This decreases the chance of the command being rejected. If it does fail, we can notify the user via email or some other out-of-band means.
- This allows our backend process to have as much time as it needs to perform the business logic & update the database.
By decoupling the queries and the commands, this pattern provides great scalability & simplifies the individual components. Of course this isn't the silver-bullet architecture, but it does solve a number of problems I've faced with scalable systems.
One problem for this pattern seems to be how to handle user input that should be reflected in the view model. Since the view model is read-only, Udi talks about overlaying the input over the data from the view model. This may work in some basic scenarios, but would break down in others. This is probably an area you'll want to evaluate before using this pattern.
Besides watching the presentation you can also read Udi's post: Clarified CQRS.
There is even a .NET framework called Ncqrs that in its words "helps build scalable, extensible and maintainable applications by supporting developers apply the CQRS architectural pattern." It has support for some interesting technologies: NServiceBus, SQLite, Microsoft Azure Platform, StructureMap, and RavenDB.