Bertrand Meyer first introduces the principle of Command Query Separation in his book Object-Oriented Software Construction. The principle states that a well designed object should have methods that are either commands or queries. A command changes the state of an object, but does not return any data, while a query returns data and does not change any state. By dividing methods into these two categories, you will have a better understanding of what does, and what does not, change the state of your system.
[E]very method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, Asking a question should not change the answer.
Command Query Responsibility Separation, or CQRS, takes this principle one step further.
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).
Conceptually, CQRS is very simple. The interesting part is what leveraging CQRS affords you. For large systems, this typically allows you to separate the querying of data from the updating of data (splitting the “read side” from the “write side”). The read side can use a data store well-suited for reads and queries, while the write side can use a data store well-suited for transactional updates. The following picture from A CQRS Journey highlights the separation between reads and writes.
On the read side, only query methods are available, while on the write side, only update (or command) methods are available. Dividing your application in this way allows you to independently scale the read capacity from the write capacity, separate business process logic for updates from logic for simple reads, and allows you to model your database to handle both read and write operations well.
Starting with this separation of concerns, we can start to dive into how to separate our business logic into commands, events and queries. Commands are requests for the system to perform an action. This action typically involves performing some transactional business logic that are processed once by a single recipient. A sample command may be “book two flights to Hawaii”. Events are notifications that something has happened. Events can be processed multiple times by multiple consumers. A sample event is “two seats have been reserved for flight AC-1234”. Lastly, queries, are requests for information. A sample query may be “show me my bookings for next two weeks”. If you implement the CQRS pattern using a separate read and write data store, events are how you keep the two sides synchronized. For example, the following figure, again from A CQRS Journey, shows how events are used to update the read side.
Separating the logic in this way allows the read side to build an index suitable for processing efficient queries to display to the user, while the write side handles the complex business logic required to fulfill the commands, with a clean separation between the two.