Thursday, 29 December 2016

Introduction to CQRS Command and Query Responsibility Segregation


CQRS means Command Query Responsibility Segregation. This was introduced by Greg Young and Udi Dahan. They took inspiration from a Command Query Separation which was defined by Bertrand Meyer.

The main idea behind CQS is: “A method should either be a command that performs an action ( change state of an object), or a query that returns data to the caller, but not both. In other words, asking the question should not change the answer. More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.” -- Wikipedia

Command and Query Responsibility Segregation was originally considered just to be an extension of this concept. 

Because of this we can divide a method into two sets:

  •  Commands - change the state of an object or entire system (sometimes called as modifiers or mutators).
  • Queries - return results and do not change the state of an object.



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 (in Command and Query Separation, a command is any method that mutates state and a query is any method that returns a value).

When most people talk about CQRS they are really speaking about applying the CQRS pattern to the object that represents the service boundary of the application. Consider the following pseudo-code service definition.


CustomerService

void MakeCustomerPreferred(CustomerId id) 
Customer GetCustomer(CustomerId id) 
CustomerSet GetCustomersWithName(Name name) 
CustomerSet GetPreferredCustomers()
void ChangeCustomerLocale(CustomerId id, Locale locale ) 
void CreateCustomer(Customer customer) 
void EditCustomerDetails(CustomerDetails details)

Applying CQRS on the CustomerService would result in two services - 

CustomerWriteService (Command)

void MakeCustomerPreferred(CustomerId id) 
void
ChangeCustomerLocale(CustomerId id, Locale locale ) 
void CreateCustomer(Customer customer) 
void
EditCustomerDetails(CustomerDetails details)

CustomerReadService (Query)

Customer GetCustomer(CustomerId id) 
CustomerSet
GetCustomersWithName(Name name) 
CustomerSet
GetPreferredCustomers()

The real strength of this pattern is that you can separate methods that change state (Commands) from those that don’t (Query). This separation could be very handy in situations when you are dealing with performance and tuning. You can optimize the read side of the system separately from the write side. for example it allows us to host the two services differently eg: we can host the read service on one (or more) server and the write service on another server (or set of servers). 

Another benefit of this pattern is in the case of large applications. You can split developers into smaller teams working on different sides of the system (read or write) without knowledge of the other side.