Command/Query Responsibility Segregation
What is CQRS?
CQRS means "Command-query responsibility segregation". We segregate the responsibility between commands (write requests) and queries (read requests). The write requests and the read requests are handled by different objects.
That's it. We can further split up the data storage, having separate read and write stores. Once that happens, there may be many read stores, optimized for handling different types of queries or spanning many bounded contexts. Though separate read/write stores are often discussed in relation with CQRS, this is not CQRS itself. CQRS is just the first split of commands and queries.
CQRS sounds like one of those newfangled diets. Who made up the term?
He has been complaining for years about search engines innocently asking "Did you mean CARS?" when one searches for CQRS.
I've heard there's something called CQS too. What is it, and how does it relate to CQRS?
CQS means "Command-query separation". It was introduced by Bertrand Meyer as part of his work on the Eiffel programming language.
It means that a method is either a command performing an action, or a query
that returns data, but not both. Being purely action-performing methods,
commands always have a
void return type. Queries, on the other hand, should
not have any observable side effect on the system itself.
Originally, CQRS was called "CQS", too. But it was determined that the two are different enough for CQRS to have its own name. The main distinguishing feature is this:
- CQS puts commands and queries in different methods within a type.
- CQRS puts commands and queries on different objects.
Can CQRS ever be a simplification?
Sure. Generic repositories are a common sight in many systems. They work well in CRUD scenarios - typically, those you may not be applying DDD to. They tend to work out fine for creates, updates, deletes, and reading individual entities. But as soon as there's a query that spans multiple entities where should it go?
Rather than agonizing over it, and trying to shoe-horn queries into the generic repository arrangement, it's far easier to put them on a separate object. No questions where they go, and they can return simple, lightweight DTOs of data.
CQRS doesn't have to mean doing event sourcing, introducing commands, event, read sides, sagas, and so forth.
Will CQRS not make my application more complex?
A typical CQRS + Event Sourcing system will seemingly have more components, since commands, events, exceptions, and queries become part of the public interface. Aggregates, command handlers, read side projections, sagas, and clients further contribute to the proliferation of components.
However, each component is neatly uncoupled from the rest. Originally, "complex" means "braided together". The components in a CQRS+ES system are independent in a way that favors reasoning about the system, and responding to changing requirements:
The division of the system into client, write side, and read side makes it easy to divide work between various teams.
Perhaps most importantly, testing becomes very natural, even of the most important and complex parts of the business logic.
Should the write side always be independent of the read side?
No. But it often helps - for example, by enabling event sourcing to be used on the write side, which can offer a lot of benefits.