Upload
derek-comartin
View
2.762
Download
1
Tags:
Embed Size (px)
DESCRIPTION
CQRS Tech Talk @ Windsor Hackforge
Citation preview
Command Query Responsibility Segregation
(CQRS)
Derek Comartin
@derek_comartinCodeOpinion.com
Agenda
• Why?
• Typical Architecture
• What is CQRS
• How to apply CQRS
• Other benefits
• Why Not?
• Takeaways
Why?
• Complex Domain
• Read & Write Boundaries
• Divergent Change
• Scalability
• Skill Set Segregation
• Architecture Choices
Typical Architecture
Data Storage
Domain Object
Domain Object
Application Service
Client
DTODTO
Facade
Typical Architecture - Client Side
Request DTO
Modify/Rebuild
DTO
Send DTO to
Server Display DTO in
View
Ack/Nak Response
1
2
34
5
6
XML of DTO
<BankAccount>
<Id>123</Id>
<CustomerId>456</CustomerId>
<Type>Savings</Type>
<Overdraft>200.00</Overdraft>
<InterestRate>0.0035</InterestRate>
<Active>True</Active>
</BankAccount>
Typical Architecture - Analysis
• Simple & Common
• Tooling: ActiveRecord, ORM, AutoMapper.
• Data Driven
• Potentially Anemic Domain Model
• Hard to scale data storage
Command Query Separation
Every method should either be a commandthat performs an action, or a query that returns data to the caller, but not both.
Command Query Responsibility Segregation
”CQRS is simply the creation of two objects where there was previously only one.”
-Greg Young
Typical Service
BankAccountService
{
BankAccount CreateBankAccount(BankAccount);
BankAccount GetBankAccount(AccountId);
decimal UpdateBalance(AccountId, Balance);
void UpdateBankAccount(BankAccount);
decimal GetBankAccountBalance(AccountId);
}
CQRS Services
BankAccountReadService
{
BankAccount GetBankAccount(AccountId);
decimal GetBankAccountBalance(AccountId);
}
BankAccountWriteService
{
BankAccount CreateBankAccount(BankAccount);
decimal UpdateBalance(AccountId, Balance);
void UpdateBankAccount(BankAccount);
}
"Defining the CQRS pattern is easy. Realizing the benefits that implementing the CQRS pattern can
offer is not always so straightforward."
– Microsoft Patterns & Practices
"This simple notion leads to some profound consequences for the design of information
systems."
–Martin Fowler
Complex Domain
• (Distributed) Domain Driven Design
• Behavior
• Intent
Typical Architecture
Data Storage
Domain Object
Domain Object
Application Service
Client
DTODTO
Facade
Simple CQRS
Data Storage
Domain Object
Domain Object
Application Service
Client
CommandDTO
Facade
Read Layer
Facade
QueryDTO
CQRS - Client Side
Request DTO
Build Command
Object
Send Command
Object to Server Display DTO in
View
Ack/Nak Response
(optional)
1
2
34
5
6
Command = Intent
DepositCommand
{
Guid AccountId;
decimal DepositAmount;
}
CQRS Services
BankAccountReadService
{
BankAccountViewModel GetBankAccount(AccountId);
decimal GetBankAccountBalance(AccountId);
}
BankAccountWriteService
{
void Send(OpenBankAccountCommand);
void Send(DepositCommand);
void Send(WithdrawlCommand);
void Send(DeactivateCommand);
}
More Options
• Multiple Models
• Domain Model = 3rd Normal Form
• Read Model = 1st Normal Form
Read & Write BoundariesDivergent Change
Data Storage
Domain Object
Domain Object
Application Service
Client
CommandDTO
Facade
Read Layer
Facade
QueryDTO
Skill Set Segregation
Data Storage
Domain Object
Domain Object
Application Service
Client
CommandDTO
Facade
Read Layer
Facade
QueryDTO
Scalability
Data StorageDomain Object
Domain Object
Command Handlers
Client
CommandDTO
Message Queue
Read Layer
Facade
QueryDTO
Event Storage
Events
Message Queue Event Handlers
Data Storage
Notes
• CRUD (not with DDD)
• Not top level architecture
• Determine per bounded context
Takeaways
• Separate reads and writes between two objects.
• That’s it.
• Everything else (DDD, Event Sourcing, Messaging…) is not CQRS. They just fit extremely well.
Resources
Greg Young
@gregyoung
goodenoughsoftware.net
Udi Dahan
@udidahan
udidahan.com
Microsoft Patterns & Practices
CQRS Journey