240 likes | 446 Views
CQRS in an hour or so. Who is jdn?. Me, aka John Nuechterlein Blog: http://www.blogcoward.com Operations Manager – Developer – Architect -Raging Douchebag eCom then Finance hopefully ecom again background Ph.D. in Philosophy (University of Miami at the age of 25) HI JEREMY!!!!!!!.
E N D
Who is jdn? • Me, aka John Nuechterlein • Blog: http://www.blogcoward.com • Operations Manager – Developer – Architect -Raging Douchebag • eCom then Finance hopefully ecom again background • Ph.D. in Philosophy (University of Miami at the age of 25) • HI JEREMY!!!!!!!
Sources • Greg Young • http://codebetter.com/blogs/gregyoung/archive/2009/08/13/command-query-separation.aspx • UdiDahan • http://www.udidahan.com/2009/12/09/clarified-cqrs/ • Mark Nijhof • http://elegantcode.com/2009/11/11/cqrs-la-greg-young/
CQRS • CQRS = “Command Query Responsibility Segregation” • Huh? • A design – pattern -architecture – Framework – Principle – Something • Makes stuff better • Huh?
CQS Defined • Bertrand Meyer (via Wikipedia) • “Command Query Separation” • “every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer.”
CQRS defined • Meyer: Separate command methods that change state from query methods that read state. • Greg Young: Separate command messages that change state from query messages that read state. • Can have significant architectural implications
Nihjof Categories • 1 – Queries • 2 – Commands • 3 – Internal Events • 4 – External Events
Queries • ‘Reporting’ • Misleading description (Greg’s fault), but makes some sense • Simple Query Layer • Simple views or sprocs or selects from denormalized tables • Simple DTOs, no mapping needed • Don’t go through the Domain Model, as it pollutes it • ViewModel per query perhaps • Why should the data come across 5 layers through 3 model transformations to populate a screen? (Udi) • ‘Traditional Reporting’ • Can (almost always will) have its own Model as well (and perhaps/probably its own data source) • Synchronous, no messaging needed • Eventual Consistency (more later)
Queries • No mapping code, don’t even bother getting a domain object at all, e.g.: • public class ModelDetailBrickDTOMapper : IMapper<Model, ModelDetailBrickDTO> • { • public ModelDetailBrickDTO Map(Model m) • { • return new ModelDetailBrickDTO(m.ID, m.Name, m.Description, m.Details, m.ShippingMessage, m.GetPrice("Current"), m.GetPrice("MSRP"), m.Sizes, m.Images, DisplayProductBrick.GetRelatedDisplayProductBricksByModel(m)); • } • }
Queries • Data store • Cache it (it’s already stale) • Why not on web-tier? • Why relational? • Horizontal scalability • If you cache, add a new server to handle it
Commands • Commands capture intent, DTOs don’t • CustomerDTOvsCustomerChangedAddressCommand • Part of the ‘Ubiquitous’ Language • Handler per command • Can be validated outside of domain entities • This is why no getters/setters on domain entities, their state is updated by processing commands according to the rules of the business • This is why domain entities are never invalid, commands that would produce invalid state are rejected
Commands • Separate Data Modification • Make preferred • Change address • Delinquent payment event example • Comes in 1 ms after make preferred event • What to do? • A generic DTO could do these things, of course, but after the fact, how do you know what actually happened? • UI Implications • Excel-like screens don’t work • Commands require specific intent
Commands • Commands can be queued • Split into separate queues • Scale where needed • Commands don’t have to be handled by the domain
Internal Events • Triggered by commands • Can be persisted • Could be RDBMS, ODBMS, Document DB, etc. • Event sourcing (big topic, punting) • Can be replayed • Production support benefit • Snapshots can also be created & persisted • Don’t delete original events • Domain can accept command or reject it • Raise event either way
Internal Events • Write-only • “Accountants don’t use erasers” • Compensating Actions/Events • Instead of rolling back a transaction, you compensate for some failure • Automatic audit log • You have all the events that happened • No more ‘impedence mismatch’ • You are persisting events, not rows • Data mining • Like I said, you have all the events that happened
External Events • Publishing • Typically, message bus • Could use views or ETL to process in a ‘simpler’ architecture • Data stores can subscribe • Only process when a read request comes in (GY)
External Events • Publishing external events and persisting internal events done in a transaction • Eventual Consistency • Latency is almost always okay • Question is, how much? • Availability trumps correctness • Acting on incomplete data is normal • Event handler per view model, perhaps
Why not CQRS? • It’s new, it’s different, I’m stupid • Multiple data stores • Operational Complexity • Losing ACID/Transactions is scary • Lots of Commands and Events and Handlers and Lions and Tigers and Bears oh my! to Code