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)
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 ChangeCustomerLocale(CustomerId id, Locale locale )
void CreateCustomer(Customer customer)
void EditCustomerDetails(CustomerDetails details)
void EditCustomerDetails(CustomerDetails details)
CustomerReadService (Query)
Customer GetCustomer(CustomerId id)
CustomerSet GetCustomersWithName(Name name)
CustomerSet GetPreferredCustomers()
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.
No comments:
Post a Comment