introduction to cqrs
DESCRIPTION
A brief overview of CQRS pattern.TRANSCRIPT
©2014 GlobalLogic Inc. CONFIDENTIAL
2 CONFIDENTIAL
Introduction to CQRS
3 CONFIDENTIAL
Command-query separation (CQS)
Introduction to CQRS
A method should either change the state of an object or return a result, but not both.
1. Queries. Return results.
2. Commands. Change state.
Pros
• Method intents are well understood
• No side effects
4 CONFIDENTIAL
Command query responsibility segregation (CQRS)
Introduction to CQRS
• A pattern based on CQS principle.
• Conceptual model is split into separate models depending whether it is a Command or Query.
5 CONFIDENTIALIntroduction to CQRS
CustomerService
Customer GetCustomer(CustomerId) CustomerSet GetCustomersWithName(Name) void CreateCustomer(Customer) void EditCustomerDetails(CustomerDetails)
Applying CQRS on this would result in two services:
CustomerServiceCommands
void CreateCustomer(Customer) void EditCustomerDetails(CustomerDetails)
CustomerServiceQueries
Customer GetCustomer(CustomerId) CustomerSet GetCustomersWithName(Name)
6 CONFIDENTIALIntroduction to CQRS
And that’s it!
There is nothing more to it than that…
7 CONFIDENTIAL
Typical web architecture
Introduction to CQRS
8 CONFIDENTIAL
Domain objects are natural for CrUD operations
Introduction to CQRS
public void Undismiss(DismissedObjectDTO dto)
{
var dismissedObject = _uow.DismissedObjectRepository.Get (dto.ObjectId, dto.ObjectTypeId);
dismissedObject.EndDate = DateTime.Now;
_uow.DismissedObjectRepository.Save(dismissedObject);
if (dismissedObject.ObjectType.ID == (int) Enums.CoachingObjectType.Observation)
{
var reviewDetail = _uow.EventReviewDetailDAO.Get(dto.ObjectId);
erd.ObservationScore = 100;
_uow.EventRepository.Save(erd);
}
_uow.CommitChanges();
}
9 CONFIDENTIAL
But can be extremely inefficient for reads
Introduction to CQRS
Lazy loading:
public Company GetCameraCompany(Camera camera)
{
return camera.Vehicle.Driver.Company;
}
10 CONFIDENTIAL
One more example
Introduction to CQRS
Incorrect fetching strategy.
private static void SomeOperation(List<Customer> customers)
{
foreach (var customer in customers)
{
foreach (var order in customer.Orders)
{
// do something
}
}
}
11 CONFIDENTIAL
Something that is more natural for Read operation
Introduction to CQRS
Plain data instead of Domain Model.
private static void SomeOperation(List<Customer> customers)
{
var customerOrderDTO = _uow.customerRepository.GetCustomerOrders(customers);
foreach (var order in customerOrderDTO .Orders)
{
// do something
}
}
12 CONFIDENTIAL
Queries
Introduction to CQRS
• What’s the purpose of queries? To show data. Not objects.
• So why should the data from the database come across 5 layers through 3 model transformations? It’s a bit overkill to display data.
• Why not just this: The UI read data from the database and displays it?
13 CONFIDENTIALIntroduction to CQRS
Consequence 1
Commands and queries use the same data but they should not necessarily use the same data model
14 CONFIDENTIAL
CQRS way
Introduction to CQRS
It is natural to use a different model to update information than the model you use to read information.
15 CONFIDENTIAL
Simple query for grid
Introduction to CQRS
SELECT
c.Name, o.Name, ot.Type
FROM Customer c
INNER JOIN CustomerOrder co ON co.CustomerId = c.CustomerId
INNER JOIN Order o ON co.OrderId = c.OrderId
INNER JOIN OrderType ot ON o.OrderId = ot.OrderId
WHERE
o.CustomerId = 20
AND ot.Type = ‘Active’
16 CONFIDENTIAL
What if the query is slow?
Introduction to CQRS
1. Execution plan and query optimization.
2. Add indexes.
3. Move to stored procedure.
4. Completely remove ORM.
The fact is that some queries simply cannot be quick.
17 CONFIDENTIAL
Let’s add denormalization
Introduction to CQRS
SELECT
CustomerName, OrderName, OrderType
FROM CustomerOrderView co
WHERE
CustomerId = 20
AND OrderType = ‘Active’
18 CONFIDENTIALIntroduction to CQRS
Consequence 2
Database can contain denormalized data for reads
19 CONFIDENTIAL
CQRS way
Introduction to CQRS
Queries tend to use denormalized data rather then classical database approach.
20 CONFIDENTIAL
Let’s go further and separate storages
Introduction to CQRS
21 CONFIDENTIAL
Read storage can be actually anything you want
Introduction to CQRS
22 CONFIDENTIAL
How to populate read storage? Synchronous way.
Introduction to CQRS
23 CONFIDENTIAL
How to populate read storage? Async way.
Introduction to CQRS
24 CONFIDENTIAL
CQRS is …
Introduction to CQRS
• CQRS is a small tactical pattern
• CQRS is learnable in 5 minutes
• CQRS can open many doors
25 CONFIDENTIALIntroduction to CQRS
Benefits• Handles domain complexity
• Applies different optimization strategies for reads and writes
• Scalability
When to use• Complex domains
• High performance applications
• Only on specific portions of a system (Bounded Context in DDD)
26 CONFIDENTIAL
Questions?