CQRS vs Specification pattern



This is an article about how two DDD patterns contradict each other.

CQRS vs Specification pattern

These two Domain-Driven Design patterns – CQRS and the Specification pattern – contradict each other. And not just lightly, they are at odds in the most fundamental way.

Let’s first recap what they stand for. The CQRS pattern is about splitting a single unified model into two: one for reads and the other one for writes. This seemingly simple exercise leads to quite significant benefits, the most important of which is simplicity.

The command side and the query side of your application have drastically different needs. Introducing a separate model for each of these sides is a natural way to make this difference explicit. This, in turn, allows you to offload a lot of complexity from your code base. With such a separation, you don’t have to worry about handling two completely different use cases with the same code. You can focus on each of them independently and come up with a solution that makes the most sense in each particular case. You can view it as the single responsibility principle applied at the architectural level. In the end, you get two models, each of which does only one thing, and does it well.

I published an online course about CQRS recently, check it out here: CQRS in Practice.

The Specification pattern is about encapsulating a piece of domain knowledge into a single unit – called specification – and then reusing in different scenarios. There are three such scenarios: data retrieval, in-memory validation, and creation of a new object (“Construction-to-order” on the figure below).

CQRS vs Specification pattern

Specification pattern

The scenario of creating a new object using a specification is quite rare and not relevant here so I’ll omit it. Data retrieval is about fetching data from the database – finding records that match the specification. And in-memory validation is when you check that some object complies with the criteria described by the specification.

This is useful because it allows you to avoid the domain knowledge duplication. The same specification class can be used for both validation of the incoming data and filtration of the data from the database when you show it to the user.

At the same time, the CQRS pattern proposes the separation of the two:

CQRS vs Specification pattern

CQRS vs Specification pattern

Validation belongs in the command side. It precedes data mutation as you normally validate the incoming data before you change something. Whereas data retrieval belongs in the read side. It’s what the client queries to see what data there is in your system.

And so there’s a clear contradiction here. On the one hand, the Specification pattern advocates for having a single domain model for these two concerns. On the other – CQRS advocates for splitting the domain model into two and dealing with those concerns separately.

What you can see here is the classic example of the contradiction between the DRY principle, which stands for don’t repeat yourself, and the principle of loose coupling. Both of these principles are foundational, they are at the core of most software development practices you employ at your day-to-day work.

CQRS vs Specification pattern

CQRS vs Specification pattern

So, which one should you prefer?

The guideline here is this: loose coupling wins in the vast majority of cases.

When choosing between high coupling and domain knowledge duplication, the latter is the lesser evil. When you duplicate the domain knowledge, it’s not very convenient but it’s not that bad when you compare it to the alternative.

And the alternative – the high coupling – can be devastating. With it, you are pretty much stuck with your hands tied behind your back. Your options are severely limited as you have to take into account not only the requirements posed by the component you develop but also by all other components that depend on this implementation.

In the scenario with the input validation and data retrieval, this manifests itself in inability to efficiently query data from the database. You can’t employ native querying mechanism of the underlying data storage and have to fall back to the lowest common denominator. That is, come up with a solution that handles neither of the two scenarios well.

Unfortunately, the Specification pattern works only in simple cases, where you don’t need sophisticated querying logic. And in such cases, it may be fine to use this pattern.

However, it large systems, you should almost always choose the loose coupling over preventing the domain knowledge duplication between the reads and writes. The freedom to choose the most appropriate solution for the problem at hand trumps the DRY principle.

Interestingly enough, I have an online course about the Specification pattern too, here it is: Specification Pattern in C#. It’s a short one – just north of 1 hour – and its shortness it partly due to this fact that there’s not much use for it in the real-world projects. I didn’t mention this when I was writing this course (despite being fully aware of this contradiction at the time of recording) and I feel slightly bad about it now. But hey, better late than never. And it’s still an interesting topic to learn, even if you don’t find a use for this pattern in your own projects.

Summary

So, here you go, the great contradiction between the CQRS and Specification patterns is now revealed.

  • CQRS is about splitting reads and writes into separate models.
  • Specification pattern is about reusing bits of domain logic in reads and writes.
  • CQRS represents the overarching principle of loose coupling.
  • Specification pattern represents the overarching principle of DRY (Don’t Repeat Yourself, avoidance of domain knowledge duplication).
  • Loose coupling trumps DRY in the vast majority of cases, except the simplest ones.

Related

Share




  • Roger Brogan

    Great post! And kudos for fessing up about the specification pattern. I watched that course and enjoyed it but I did struggle to see a place I would actually use it in my code. I really appreciate when an architect takes a strong stand on the usefulness of patterns and explains where use is appropriate. Keep up the good work.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      Thanks Roger, appreciate the kind words.

  • David Kemp

    Thanks for the post, it’s certainly given me some food for thought.

    I have to admit that, with Linq, Expressions Trees and IQueryable being such powerful tools in C#, using Specifications for queries can be pretty hard work, and often involves fighting with the tooling (PredicateBuilder can help, but it doesn’t solve all the problems)

    However, looking back at the DDD book, the Specification isn’t just used for querying – “a SPECIFICATION is a predicate that determines if an object does or does not satisfy some criteria”.
    They can be used for Validation; Selecting an object from a collection; and, Specifying the creation of a new object.

    So, for example, FluentValidation’s AbstractValidator is a Specification, and I would argue that any of the Validation Attributes from System.ComponentModel are also Specifications.
    We also use Specifications with DI/IoC containers – we tell the container how to build the object graphs, and they build them based on the specifications.

    With C#, there are multiple ways to implementing simple specifications – as extension methods, with expression trees, anonymous functions, reflection and introspection, etc, and this often hides the fact that, underneath, we’re using the same pattern.

  • Mohammad Kariuki

    Thanks for the post @vladimirkhorikov:disqus . I have watched both courses and I must admit they are well thought out. I have implemented the specification pattern and it certainly has its place. Lately, it just feels more like an abstraction on top of already able Linq, Expressions Trees and IQueryable like @disqus_cnfgum6kN0:disqus points out. The contradictions are a good pointer.

  • Pavel

    Hi, first thanks for great post.
    I really like specification pattern, but when i have combine it with ddd model and CQRS i stuck on a problem.
    I have two separate models. First for my domain and second for queries.
    In domain, i have Invoice object and specification class which determines if invoice can be edited.
    My problem is: How to use the same specification rules (specification class) on read side (in query handler)?
    For example, i need to determine if the edit button (on user interface) should be active or not. It is the same rule like in domain (command side).
    After reading this post, best solution I see at this moment is duplication of specification class for the read model.
    Another idea is to use repository in query handler that returs Invoice class (domain model). After that, i can, apply the specification and finally create query result object.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      I’d recommend duplicating the logic. Just keep in mind that the command side has a priority in terms of the domain logic. Meaning that if the domain knowledge/logic in the two sides differ, the command side should be treated as the master storage of that domain knowledge.

  • Epsilekt

    Great post Vladimir!

  • Andrew Kuipers

    When you say “between high coupling and domain knowledge duplication, the latter is the lesser evil”, I think it’s worthwhile to note that the latter may not be an evil at all. The specifications used by the command model and the query model may appear to be the same (and may very well be the same code when you begin the project), however they likely have very different reasons to change, and so this appears to be a case of “accidental duplication” (Robert C. Martin, Clean Architecture, pg.154-155).

    There really isn’t a contradiction between the patterns themselves, but rather from the patterns conjoined with the premise “The same specification class can be used for both validation of the incoming data and filtration of the data from the database when you show it to the user.” Therefore, the contradiction derived from the combination of these patterns and this premise should be taken as a reason to reject the premise, and not the combination of those patterns.