6

Since CQRS and DDD do not imply one another I was curious what terms belong to DDD and what terms belong to CQRS. Because the two concepts are so much used together in the literature I usually mix them up.

I came up with this list of the terms that I think go to one camp or the other.

DDD

  • Domain model
  • Aggregate (and aggregate root)
  • Value objects, entities, services
  • Bounded context
  • Ubiquitous language
  • Events?

CQRS

  • Command (Command Handlers)
  • Events? (Event Handlers?)
  • Saga, process managers
  • Read model / Write model
  • Projections (different read models)
  • Eventual consistency

Could anyone correct me (and/or explain), what is where?

  • 1
    If you read original book "Domain-Driven Design" by Eric Evans, you should get terminology of DDD without it being muddled by CQRS. – Euphoric Nov 19 '15 at 6:37
12

CQRS and DDD are separate/orthogonal concepts, and I think you divided the terms pretty close to right.

Events under DDD are called Domain Events, and are somewhat different from the Messaging events often mentioned with CQRS. Messaging events usually have more to do with Event Sourcing.

Your CQRS category is a conglomeration of a number of patterns, and only one of those (Read model / Write model) is actually definitional to CQRS.

  • Messaging, implemented as commands and events. Messaging gives you a lot of flexibility over something like, say RPC. Messages, being just request or event data, can be examined, prioritized, queued, partitioned across nodes, forwarded, retried, subscribed to, etc. Conversely, they can also be lost, poisoned, etc.

  • Saga and Process Manager are often used interchangeably when referring to a Process Manager. Both are strategies for avoiding distributed transactions, usually in order to maintain scalability.

  • Projection goes way back. You probably know this most commonly from SQL. The SELECT expr [as name] statement is the Projection operation in relational algebra, on which SQL is based. A projection is just a subset or transformation of the underlying data.

    In the context of CQRS, projections are usually referring to views (aka read models). Although technically an event-sourced aggregate is also a projection -- it's an event stream transformed into a structured model, just like with views.

  • Separating read and write models is the essential definition of CQRS. CQRS is helpful because the data you need for views (reads) is different from what is needed for writes. In a traditional 3-layer system (presentation, business, data layers), you often naively start with the same class being used by all 3 layers. As complexity increases, you will end up with extra fields which are used by only one layer, but add mental weight at all layers. "I just added something to this collection. Do I need to update the DisplayCount here or will the view do that? Do I need to persist this DisplayCount or does the view recalculate that each time? Wait, why is DisplayCount a string?!"

    You start to realize that read and write needs are different enough to warrant different objects to isolate concerns. That can lead to mapping business object to a view object, which is arguably a form of CQRS. (This also happens in DDD systems not using CQRS, mapping from domain model to view). However when claiming CQRS, people often mean they are persisting both read and write models, not loading the write model and mapping it to a read model. There are typically multiple read models for a given write model to accommodate the specific needs of different ui screens/reports/views.

  • Eventual consistency is not unique to CQRS either. Any time you create a report that gets run periodically, you have created an eventually-consistent read model. When it is talked about with CQRS, it usually means that most/all read models are eventually consistent. This is optional to CQRS. You could use CQRS in a fully consistent manner, and this would simply shift the IO burden from reads to writes. This by itself is probably an okay trade-off for most system, because IO is likely dominated by reads.

    Systems with a single model of data are optimized for writing (normalized) and reads are expensive (i.e. JOINs in SQL). With CQRS, you trade towards cheap reads by making separate (and probably multiple) read models which are denormalized (all necessary data put into each read model so no JOINs are needed). In a fully consistent system, you have to update the write model and all read models at the same time to maintain read/write consistency. You are trading write performance for read performance.

    Enter eventual consistency, which buys you cheap reads and writes, with the trade-off that read models will be slightly behind (eventually consistent with) the write model. This is due to an out-of-band process (often called a denormalizer) updating the read models after-the-fact.

Many people have developed "CQRS systems" which are combinations of these patterns plus CQRS. However, the CQRS pattern really only amounts to separating read and write models. It doesn't mean you have eventual consistency, event sourcing, process managers, messaging, or anything else. However, the mentioned patterns do synergize well with CQRS and are basically progressive optimizations to take further advantage of it.

Also, CQRS is based on another pattern, Command-Query Separation, but takes it a step further.

Edit: For a more detailed explanation on the difference between Domain Events and Events used for event sourcing, please see this classic Greg Young post.

  • This is terrific. Are events in ES really part of messaging? I thouht they are part of the domain (domain events) as they are handled by aggregates to create their state. – redhead Nov 19 '15 at 11:45
  • @redhead Yes, events are considered messages which communicate something interesting that happened in the domain. DDD's Domain Events do this, but were originally more limited in scope as aggregates were loaded from repositories. People started using events as a means to notify external systems and then to construct views, which greatly expanded their use. ES further says events are the book of record, and everything else (including the aggregate) is a model built from them. – Kasey Speakman Nov 19 '15 at 14:38
  • Also note that Event Sourcing is a pretty old concept as well. You observe it in action every time you look at a bank statement. Your account balance is just a projection of the transaction events on the account. Imagine this with the Active Record pattern where your statement only had your current balance, not the transactions that got you there. – Kasey Speakman Nov 19 '15 at 14:43
  • I am not arguing about ES principles or that it's not old. I just can't wrap my head around the ES events not being domain events. As they are events (book of records) representing something that happened in the domain (money withdrawal/deposit). Could you provide an example of domain event and messaging event (for use in ES) where the distinction is clear (or point me to some article)? Thanks – redhead Nov 19 '15 at 19:55
  • Here. Scroll down to Introducing Domain Events. Just mentioned ES background for the general audience (all 3 of you) to reinforce that these are not new ideas, but combinations of old ideas. – Kasey Speakman Nov 19 '15 at 20:41
0

Most of the terms belong to both domains because they are intertwined. In fact, Martin Fowler writes that

CQRS should only be used on specific portions of a system (a Bounded Context in DDD lingo) and not the system as a whole.

It is a way to implement a DDD-application and as such will have terms intermingled. Udi Dahan has a good writeup on CQRS and says

Arguably, you could have some commands be processed by transaction script, others using table module (AKA active record), as well as those using the domain model. Event-sourcing is another possible implementation.

If you really want to, you can talk about your domain in DDD terms and avoid talking about saga's, commands and the read/write model in the same way that you can talk about an application without talking about tables and primary keys of the underlying persistence mechanism, but you will occasionally mix the two. I wouldn't really focus on putting the terms in the DDD or CQRS basket...

0

Just a few thoughts :

DDD

  • Domain model
  • Aggregate (and aggregate root)
  • Value objects, entities, services
  • Bounded context
  • Ubiquitous language
  • Domain Events

CQRS

  • Command (Command Handlers)
  • Events? (Event Handlers?) See Event Sourcing instead
  • Saga, process managers Sort of a neighboring approach, but not "core" CQRS per se
  • Read model / Write model
  • Projections (different read models)
  • Eventual consistency Not invented here, but definitely a key underlying concept

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.