Clarified CQRS - Reading Notes

By: Jeremy W. Sherman. Published: . Categories: reading-notes book-club.

On 19 Dec 2013, I read the article Clarified CQRS published by Udi Dahan on 9 Dec 2009, so four years ago.

(This reading was for the BNR Book Club: It’s open to all, and you should join the group!)

In it, Dahan elaborates their interpretation of CQRS.

Dahan’s new ideas:

Section-by-section notes follow.

Two appendices include notes from additional articles by other authors on CQRS, to provide context to the discussion:

Clarified CQRS

Why CQRS

Queries

Scaling

Data Modification

Commands

Commands & Validation

Validation is different from business rules in that it states a context-independent fact about a command. Either a command is valid, or it isn’t. Business rules on the other hand are context dependent.

Returns to example of delinquency update arriving before preferred status application causing the latter to be reject; reverse the order, and we would have accepted both changes.

This is basically just pointing out that “a valid command is one that has all necessary, valid data” rather than “a valid command is one that won’t be rejected”.

Rethinking UIs and commands

Can use query store to speed up updates - autocomplete from query store, update sends the ID we already have for the selected value rather than text. Again, less marshaling.

Reasons valid commands fail

The delinquent vs. preferred race is just bad design. Should have same business outcome regardless of which arrives first.

Outcome: Notify the user (email).

No rejection errors are ever returned to the agent submitting changes. They can do nothing but notify the user, anyway.

No need even to show pending commands: Instead, notify users as needed asynchronously out of band.

Commands and Autonomy

Autonomous Components

Acronym: AC = Autonomous Component

Command processor is an AC with its own queue.

Can go even further than that: Can have each command processed by its own AC.

This lets you get detailed queue and processing time metrics, and can scale up ACs on a per-command basis.

Service Layers

Per-command AC means each processor is independent. This is a stark contrast to the rat’s nest at each layer of many layered architectures.

Domain Model

Domain model is no longer used to service queries.

Not really necessary for commands either.

Scarcely need relationships – just precompute (denormalize) for queries, and have commands sent with needed IDs.

Persistence for Command Processing

No need for fancy DB queries.

Commands come in with IDs anyway.

So ORM not strictly necessary; can do key-value, optionally splitting out properties that benefit from uniqueness constraint into their own columns.

Key point here: “How you process the commands is an implementation detail of CQRS."

Keeping the Query Store in Sync

Bounded Contexts

“CQRS if used is employed within a bounded context (DDD) or a business component (SOA) – a cohesive piece of the problem domain. The events published by one BC are subscribed to by other BCs, each updating their query and command data stores as needed.”

Mash-up into a single UI as needed.

Summary

CQRS is about coming up with an appropriate architecture for multi-user collaborative applications. It explicitly takes into account factors like data staleness and volatility and exploits those characteristics for creating simpler and more scalable constructs.

One cannot truly enjoy the benefits of CQRS without considering the user-interface, making it capture user intent explicitly. When taking into account client-side validation, command structures may be somewhat adjusted. Thinking through the order in which commands and events are processed can lead to notification patterns which make returning errors unnecessary.

Appendix A: Martin Fowler on CQRS

Never expanded anywhere in the article is the acronym “CQRS”:

CQRS stands for Command Query Responsibility Segregation. It’s a pattern that I first heard described by Greg Young. At its heart is a simple notion that you can use a different model to update information than the model you use to read information. This simple notion leads to some profound consequences for the design of information systems.

[…]

The change that CQRS introduces is to split that conceptual model [integrating various views of the underlying data] into separate models for update and display, which it refers to as Command and Query respectively following the vocabulary of CommandQuerySeparation. The rationale is that for many problems, particularly in more complicated domains, having the same conceptual model for commands and queries leads to a more complex model that does neither well. (Martin Fowler)

Fowler introduces more terms, like Reporting Database and Eager Read Derivation, which can be used independently of CQRS but feature in it as well.

Points out that where CRUD fits, you should likely use it. CQRS should also be deployed on a per-“bounded context” basis - it’s effectively a domain modeling decision.

Not clear that commands and queries are often really separate enough that it’s worth having two entirely separate models.

CQRS is nice for high-load apps – you can scale reads and writes independently. But still can handle this in CRUD by splitting out the really high reads into a ReportingDatabase used to serve just those queries.

Appendix B: Greg Young on CQRS

Greg Young originated CQRS per Fowler.

Fowler links to this summary by Greg Young: