mandag, september 26, 2011

Why CQRS may not be the answer you are looking for

With CQRS I mean Command Query Responsibility Segregation. If you have never heard of this before then you are probably better off reading about CQRS elsewhere on the web.

If you know CQRS already then, please, read on.

Have you ever tried to implement some kind of CQRS and had that feeling of friction - not really getting it to work and then wondering why? I mean - everybody else is using it, right? Like this quote from the NServiceBus forum states it:

> I think CQRS has been getting a lot of hype recently and one frustration for a beginner (like me) is that if all these people are using these concepts/technologies, rather than just telling conventional crud/n-tier folks that CQRS is the "future", let's have some good examples and documentation that helps us learn why.

I have been there myself - trying to do CQRS exercises for training and ultimately giving up. Lately I have been digging more into it and now I would like to share some thoughts based on my own experiences and learnings from Udi Dahan's Advanced Distributed Systems Design Course. To be honest, lot's of it is just rephrasing of stuff from the course.

First of all, CQRS is one of those annoying technologies that looks very simple in theory, but turns out to cost a bit to build in practice.

Lets try with an example from the NCQRS project (I do not hold anything against that project, they just have a good on-line example) - creating a Tweet in a Twitter-like system:

Now compare the CQRS solution with a Ruby on Rails solution: Which one is the simplest? I hope you agree with me that the Ruby on Rails solution is simpler - it is after all only a matter of writing a tweet to a database. Right?

And that is the most important point: it is after all only a matter of writing a tweet to a database! Right? None of the two examples has addressed the more difficult problems of making sure the right people gets the right tweets, re-tweeting and so on.

So why use CQRS when it can be done in a much simpler way? Here are some arguments:
  1. Its never going to scale!
  2. Of course RoR is easier, CQRS is for complex/collaboration scenarios, you won't see any gain in such a simple example!
  3. Okay, the RoR solution is simpler, but(!) when we add complex business rules then it will be a mess!
Regarding (1): the code we are seeing so far will scale - it is simple CRUD operations and it can easily be scaled out on a database level with a one-master/multiple-slaves setup.

Regarding (2): that it is the whole point - CQRS is not for simple scenarios. You can do it, but it may hurt and work against you all the time.

Regarding (3): you may be right! So lets take out the complex business rules and handle them elsewhere - asynchronously using messaging.

Our message handlers can parse the tweet, looking for #tag and @name, and distribute tweets to other users. All of it the same (eventually consistent) query database!

Duh! You probably say. Only Command handlers modify command state and send out events that the query context listens for. But is any command state involved here? No - all we have done is the simple RoR style direct update of the query model, and some background processing also working directly on the query model.

How can we do this? Where is the command handling? Well, it is not here ... as I started out saying, CQRS may not be the answer you are looking for. CQRS is not to be applied to any and all problems - it carries a big overhead (even if it is simple in theory).

What is left is then to explain where CQRS really applies - but that is beyond the scope of this blog post (and also beyond my current knowledge of CQRS).

So who am I to judge what CQRS is and is not? Well, not any better than so many other people out there. I am no expert. I build my opinion on my own experiences and some valuable input from Udi. Read this as one advice out of many and use it to make your own decision.


Ingen kommentarer:

Send en kommentar