CQRS Best Practices and
Misconceptions
Vladimir Khorikov
@vkhorikov www.enterprisecraftsmanship.com
CQRS and Event Sourcing
CQRS Event Sourcing
CQRS and Event Sourcing
Event Sourcing
CQRS
No segregation
CQRS can provide a lot of
benefits without
Event Sourcing.
CQRS and Event Sourcing
The bar for Event Sourcing is
much higher than it is for
CQRS
There's still a lot of value
in event sourced systems
CQRS and Event Sourcing
Finance tech
Has to keep track of all events
A trail of the financial
transactions
CQRS and Event Sourcing
CQRS Event Sourcing
Doesn’t require
Requires CQRS
Event Sourcing
Event Sourcing without CQRS
is a less scalable solution
Evolutionary Design
You don't have to implement all
the techniques from this course
Defer these decisions until you
have proven their need
Evolutionary Design
Costs Benefits
Ensure the benefits outweigh the
costs before applying a pattern
Evolutionary Design
API
Client App Domain
services model
API
Database
Evolutionary Design
Bounded Context 1 Bounded Context 1
CQRS
Evolutionary Design
Bounded Context 1 Bounded Context 1
Full CQRS Task-based interface
Separation down to the domain
model level is the sweet spot
Using Commands and Queries from Handlers
Can you use other commands
and queries from command
and query handlers?
Using Commands and Queries from Handlers
Command Query
Command
handler
Query handler
Using Commands and Queries from Handlers
public sealed class UnregisterCommandHandler : ICommandHandler<UnregisterCommand>
{
public Result Handle(UnregisterCommand command)
{
var unitOfWork = new UnitOfWork(_sessionFactory);
var repository = new StudentRepository(unitOfWork);
Student student = repository.GetById(command.Id);
if (student == null)
return Result.Fail($"No student found for Id {command.Id}");
_messages.Dispatch(new DisenrollCommand(student.Id, 0, "Unregistering"));
_messages.Dispatch(new DisenrollCommand(student.Id, 1, "Unregistering"));
repository.Delete(student);
unitOfWork.Commit();
return Result.Ok();
}
}
Our application shouldn't trigger commands
Using Commands and Queries from Handlers
Write model Events Read model
State
Commands
(via queries)
Client
Command: what can be done with application
Event: what has happened to the application
State: sum of all the events
Using Commands and Queries from Handlers
Command Query
Command
handler Nope
Query handler
Using Commands and Queries from Handlers
Do you have a reliable way to
request the current state in the
command side?
Query the command database directly
Use a query from a command handler
Using Commands and Queries from Handlers
Event Sourcing
Event log State
Have to use the read database
Whole set of issues related to consistency
Using Commands and Queries from Handlers
Command Query
Command Only with
handler Nope Event Sourcing
Query handler
Using Commands and Queries from Handlers
Command Query
Command Only with
handler Nope Event Sourcing
Query handler Nope
One-way Commands
Unidirectional commands
Should not return anything
CQS principle
Poll for the result
One-way Commands
Truly one-way commands are impossible
Why return a locator?
Complete the operation synchronously
An Id is fine too
CQRS vs. the Specification Pattern
CQRS vs. Specifications
CQRS vs. the Specification Pattern
Specification
Data retrieval Input validation
Construction-to-order
CQRS vs. the Specification Pattern
Specification
Data retrieval Input validation
Queries Commands
CQRS vs. the Specification Pattern
CQRS vs. Specifications
Separate domain model Single domain model
Loose coupling The DRY principle
Domain knowledge duplication is a lesser evil
High coupling puts too many restrictions
Resource List
https://github.com/vkhorikov/CqrsInPractice
Source code
http://bit.ly/cqrs-code
https://www.pluralsight.com/courses/domain-driven-design-in-practice
Domain-Driven Design in
Practice
http://bit.ly/ddd-ps
CQRS book by Greg Young https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf
https://enterprisecraftsmanship.com/2018/06/13/ef-core-vs-nhibernate-ddd-
Use of event listeners in perspective/ (Section 7)
NHibernate and the change
tracker in Entity Framework http://bit.ly/ef-vs-nh (Section 7)
https://www.enterpriseintegrationpatterns.com/ramblings/18_starbucks.html
Starbucks doesn't use two-
phase commit
http://bit.ly/starbucks-cons
CQRS pattern: what it is and how to
implement it in practice
Goals of CQRS:
Course - Simplicity, performance, and scalability
Summary Gradually introduced the separation
- API endpoints
- Explicit commands, queries, and
handlers, decorators
- No domain model in reads
- Separate database
Synchronization between the read and
write databases
CQRS best practices and common
misconceptions
Contacts
http://bit.ly/ddd-new
vladimir.khorikov@gmail.com
@vkhorikov
http://enterprisecraftsmanship.com/