11
CQRS
IN 4 STEPS
22
radblog.pl @RadekMaziarkaobjectivity.co.uk
Radek Maziarka
http://radblog.pl/CQRS
33
CQRS
Command Query Responsibility Segregation
44
BUILDING BLOCKS
55
WHY
YOU
SHOULD
EVEN
CARE?
66
INITIAL STATE
77
UI
CONTROLLERS
SERVICES
APP
Services
88
ProductsController ProductsService
OrdersServiceOrdersController
•GetProducts
•ChangeProductFieldValue
•GetOrder
•ChangeOrderDestination
Store application
99
Final state - NopCommerce
1010
1111
Disadvantages of this
approach
•Enormous controllers / services /
helpers
•Classes are not following SRP
•Refactoring is really difficult
•Complexity in writing unit tests
1212
1
COMMAND AND QUERIES
1313
JIMMY BOGARD
CQRS IS A SIMPLE PATTERN
Two objects for command/queries
where once there was one
https://lostechies.com/jimmybogard/2015/05/05/cqrs-with-mediatr-and-automapper/
1414
WRITE
SERVICES
READ
SERVICES
UI
CONTROLLERS
APP
Read / write services
1515
UI
CONTROLLERS
APP
Command / query handlers
Command Handler
Command Handler
Command Handler
Command Handler
Query Handler
Query Handler
Query Handler
Query Handler
1616
ProductsController
GetProducts
QueryHandler
ChangeProduct
FieldValue
CommandHandler
Mediator
GetProducts
Query
ChangeProduct
FieldValue
Command
Splitting to objects
1717
MediatR
Simple, umambitious mediator
• Simple mediator implementation in .NET
• In-process messaging with no
dependencies
• Request/response, commands, queries,
notifications, events
https://github.com/jbogard/MediatR
1818
public class ProductsController : ApiController
{
private readonly IMediator mediator;
public ProductsController(IMediator mediator)
{
this.mediator = mediator;
}
[HttpGet]
public IEnumerable<Product> GetProducts(GetProductsQuery query)
{
return this.mediator.Send(query);
}
[HttpPut]
public void ChangeProductFieldValue(ChangeProductFieldValueCommand command)
{
this.mediator.Send(command);
}
}
Splitting to objects
1919
public class GetProductsQueryHandler: IRequestHandler<GetProductsQuery, IEnumerable<Product>>
{
private readonly IProductDatabase _database;
// ctx
public IEnumerable<Product> Handle(GetProductsQuery query)
{
var products = this._database
.Products
.Include(p => p.Category)
.Include(p => p.FieldValues)
.Include(p => p.FieldValues.Select(fv => fv.Field));
// filter products by command values
return products.OrderBy(p => p.CreationDate)
.Skip((query.Page - 1) * query.Take).Take(query.Take)
.ToList();
}
}
Query handler
2020
public class ChangeProductFieldValueCommandHandler
:IRequestHandler<ChangeProductFieldValueCommand>
{
private IProductDatabase database;
private ICategoryFieldService categoryFieldService;
private IProductFieldHelper productFieldHelper;
private IFieldValidatorFactory fieldValidatorFactory;
//ctx
public void Handle(ChangeProductFieldValueCommand command)
{
this._categoryFieldService.ValidateIfFieldCanBeAssignedToProduct
(command.FieldId, command.ProductId);
var fieldValidator = this._fieldValidatorFactory(command.FieldId);
fieldValidator.Validate(command.FieldValue);
// business logic
_database.SaveChanges();
}
}
Command handler
2121
Project structure
2222
•Better structure of application
•Lower entry level
•Single responsibility + clean code
•Clearly defined target and
dependencies
•Simplicity of writing unit tests
Profits after this step
2323
•More difficult than simple controller-
database connection
Disadvantages of this step
2424
2525
UI
CONTROLLERS
APP
CQRS in the simplest form
Command Handler
Command Handler
Command Handler
Command Handler
Query Handler
Query Handler
Query Handler
Query Handler
2626
CQRS
AS A STEP
2727
2828
2
DIFFERENT
DATA ACCESS
2929
CONTROLLERS
APP
Command Handler
Command Handler
Query Handler
Query Handler
Command Handler
Command Handler
Query Handler
Query Handler
X
Different data access
3030
ProductsController
GetProductsQueryHandler
CategoriesController
GetProductsFieldsQueryHandler
AddProductCommandHandler
GetCategoriesQueryHandler
GetProductsWithinCategory
QueryHandler
AddCategoryCommandHandler
Multiple objects
3131
GetProductsFieldsQueryHandler
AddProductCommandHandler
AddCategoryCommandHandler
Objects without change
3232
GetProductsQueryHandler
GetProductsFieldsQueryHandler
AddProductsByBatch
CommandHandler
Request optimization
3333
SQL Views
Materialized
AutoMapper
ProjectTo
Dapper
MicroORM
EF No
tracking
OrmLite
MicroORM
SQL Queries
6
4
5
3
1
2
Plenty of options
3434
Profits of using CQRS
Different data access
•Ease of experiment
•Focus on bottlenecks
•No impact on other parts of the system
3535
3636
3
SIMPLE
READ MODEL
3737
CONTROLLERS
APP
Command Handler
Command Handler
Query Handler
Query Handler
Query Handler
Query Handler
Simple read model
3838
PlaceOrder
http://udidahan.com/2009/06/14/domain-events-salvation/
OrderPlace
d
SendEmai
l
DDD - Domain events
Core Logic Event Side Effect
3939
Command
Handler
https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/domain-events-design-
implementation
Mediator
Event Event
Handler
Domain events in CQRS
4040
AddProduct
CommandHandler
ChangeProductField
CommandHandler
MediatorMediator
ProductAdded
ProductFieldChanged
Publish store events
4141
Product
ReadModel
Handler
https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/domain-events-design-
implementation#single-transaction-across-aggregates-versus-eventual-consistency-across-aggregates
ProductAdded
ProductFieldChanged Product
Read
Model
Create read model
4242
https://github.com/jbogard/MediatR/wiki/Behaviors
Command
Handler
Mediator
Event
Event
Handler
Event
Handler
Event
Handler
Transaction
Behavior
Transaction per command
4343
•Ease of creating read model
•Domain events straightly connected to
command handlers
•No data loss
Profits of using CQRS
Simple read model
4444
4545
4
ASYNCHRONOUS
READ MODEL
4646
CONTROLLERS
APP
Command Handler
Command Handler
Query Handler
Query Handler
Query Handler
Query Handler
Asynchronous read model
4747
ProductAdded
ProductFieldChanged
Event
Bus
Product
ReadModel
Handler
Event bus
4848
Event
Bus
Product
SearchModel
Handler
Product
CacheModel
Handler
Different databases
4949
Event
Bus
Product
SearchModel
Handler
ProductsHub
SignalR
http://danielwhittaker.me/2014/10/27/4-ways-handle-eventual-consistency-ui/
Notify the user
5050
•Database focused on problem
•Non-blockable commands
•Designed for scale
Profits of using CQRS
Asynchronous read model
5151
•Distributed system
•Eventual consistency
•Operational complexity
Disadvantages of using CQRS
Asynchronous read model
5252
5353
5454
5555
DIFFERENT
DATA
ACCESS
SIMPLE
READ MODEL
COMMAND
AND
QUERIES
ASYNCHRONOUS
READ MODEL
2 3 41
CQRS
in 4 steps
5656http://radblog.pl/CQRS
CQRS implementation + MediatR:
Jimmy Bogard - CQRS with MediatR and AutoMapper - https://lostechies.com/jimmybogard/2016/10/27/cqrsmediatr-implementation-patterns/
Jimmy Bogard - CQRS/MediatR implementation patterns https://lostechies.com/jimmybogard/2015/05/05/cqrs-with-mediatr-and-automapper/
CQRS implementation:
Maciek Aniserowicza - CQRS pragmatycznie - https://kupdf.com/download/maciej-aniserowicz-cqrs-pragmatycznie_597c9425dc0d60997f2bb17f_pdf
Future Processing - CQRS Simple Architecture - https://www.future-processing.pl/blog/cqrs-simple-architecture/
Derek Comartin - Fat Controllers CQRS Diet - https://codeopinion.com/fat-controller-cqrs-diet-notifications
Radek Maziarka - First step - Split to commands and queries http://radblog.pl/2017/08/19/cqrs-first-step-split-to-commands-and-queries/
More generic about CQRS:
Greg Young - CQRS Documencts - https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf
Greg Young - CQRS and Event Sourcing - https://www.youtube.com/watch?v=JHGkaShoyNs
Microsoft - CQRS Journey - https://msdn.microsoft.com/en-us/library/jj554200.aspx
Udi Dahan - Clarified CQRS - http://udidahan.com/2009/12/09/clarified-cqrs/
CQRS in Node.js https://medium.com/@domagojk/patterns-for-designing-flexible-architecture-in-node-js-cqrs-es-onion-7eb10bbefe17
Herberto Graca - From CQS to CQRS - https://herbertograca.com/2017/10/19/from-cqs-to-cqrs/
Radek Maziarka - CQRS in 4 steps - http://radblog.pl/2017/09/17/cqrs-in-4-steps-lightning-talk/
CQRS in polish:
Bulldog - CQRS i Event Sourcing - https://bulldogjob.pl/articles/122-cqrs-i-event-sourcing-czyli-latwa-droga-do-skalowalnosci-naszych-systemow_
it-consulting - CQRS - http://it-consulting.pl/autoinstalator/wordpress/2012/10/18/cqrs-czyli-kto-co-i-jak-zamawia-i-dostarcza/
Łukasz Szydło - P&A + DDD + CQRS = 00 - https://www.youtube.com/watch?v=yhYFL4ujYqY
5757

CQRS in 4 steps

Editor's Notes

  • #5 The whole presentation is based on my own experience – my projects, my own decisions, my frameworks.
  • #39 And it fits well in CQRS, and not in service model of work, because you exacly know where to send event – at the finish of CH. With services you have different types and you would sometimes send event, sometimes not.
  • #40 And it fits well in CQRS, and not in service model of work, because you exacly know where to send event – at the finish of CH. With services you have different types and you would sometimes send event, sometimes not.