Posts
1150
Comments
891
Trackbacks
1
cqrs for dummies – an interlude – has it all been a waste of time?

Now that I have completed the long project that has sucked up a huge amount of time (which was necessary because it was important to the client, and because it pays the bills), I have returned much of my attention to one of my own projects, which might hopefully help pay some of the bills down the road and which involves an oddly opinionated version of CQRS.

As it happens, Udi Dahan has written a post entitled “When to avoid CQRS” that suggests I shouldn’t be putting in the effort.  Some of the key snippets here:

“It looks like that CQRS has finally “made it” as a full blown “best practice”.  Please accept my apologies for my part in the overly-complex software being created because of it.”

“Most people using CQRS (and Event Sourcing too) shouldn’t have done so.”

“Therefore, I’m sorry to say that most sample application you’ll see online that show CQRS are architecturally wrong.”

“So, when should you avoid CQRS?  The answer is most of the time.”

Given all of that, it would seem that, for the most part, putting in all this effort has been a mistake.

Rinat Abdullin then posted a response that suggests perhaps things aren’t so grim.  Some of the key snippets here:

“In essence, synergies within CQRS work, whenever you need to:

  • tackle complexity;
  • distribute teams;
  • scale out under massive loads.”

“Yet, for some strange reason, the mental model of CQRS provided much friendlier and faster implementation route here.”

So, what should we make of this?

My response is going to be that both Udi and Rinat are correct.  To see why seemingly disparate viewpoints could both be correct, you have to consider context.

Isn’t CQRS supposed to be about simplicity?

That’s a bit of an over-statement, but think about what Greg Young has talked about in terms of what I call ‘strict CQRS’.  It’s about separating your commands from your queries in your code.  That’s it.  CQRS doesn’t mean event sourcing, in particular.

Think about the whole concept of a thin view layer as Udi has described.  No translating through your domain model, no mapping of Domain objects to DTOs, or any of that stuff, just reading a simple view model (where your queries don’t even have to go through a layer of any kind, just straight from your denormalized data source).  That’s it.

A lot of the complexity in CQRS frameworks comes in when you try to implement Event Sourcing and re-creating an AR off of the event store.  But what if you take some of the simple principles of CQRS and apply (pun intended) only those, before you embrace full blown Event Sourcing architectural principles?

An EventLog doesn’t have to be gold-plating

Udi says:

“Architectural gold-plating / stealing from the business.

Who put you in a position to decide that development time and resources should be diverted from short-term business-value-adding features to support a non-functional requirement that the business didn’t ask for?

If you sat down with them, explaining the long-term value of having an archive of all actions in the system, and they said OK, build this into the system from the beginning, that would be fine. Most people who ask me about CQRS and/or Event Sourcing skip this step.”

Imagine if you build a system that has some of the architectural principles of CQRS but doesn’t try to implement full-blown Event Sourcing?  You can still have your commands being handled (and saved to a command store) and generating events (which are saved to an event store) which are published and subscribed to, and dealt with accordingly, but the state of your domain objects are saved in a traditional, boring database.

The infrastructure for such a system can be pretty simple (more or less).   Your event store can still give you a (mostly for) free log that can still give you insights into the history of how your application is used.  It doesn’t, obviously, let you replay events to rebuild a system from some particular point in time.  You do need to build additional infrastructure for that.

But then is it still CQRS?

Yes and no.  You can argue semantics forever, and if you want to do that, you can.  But the idea I’m expressing here is that you can gain a lot of benefits from applying some of the basic/strict CQRS principles in a low cost manner.

I don’t know that anyone has ever claimed this, but in my mind, when I think of a domain where full blown CQRS + Event Sourcing makes sense is in a full-blown, real-time trading system.  A lot of what I consider to be basic/strict CQRS is probably just coming to terms with understanding basic messaging concepts.

CQRS is a helpful mental model

Rinat says:

“Yet, for some strange reason, the mental model of CQRS provided much friendlier and faster implementation route here (despite the fact that there is not a single book published on the subject, yet). Diverse solutions being delivered to production, share similar architecture, development principles, reduced complexity levels and teams. They just work.”

Some of what I’ve taken from in learning what people have been talking about with CQRS is probably really just getting down to brass tacks and learning how to apply SRP.

Every action in my application that changes state is a command, and that command completely consolidates all of the information needed for the state to be changed.  It doesn’t include any other information.

Every request in my application for data is a query, and that query completely consolidates all of the information needed to get the data that I need.  It doesn’t include any other information.

From just thinking about these two things, I learn quite a lot about what to do with the infrastructure of my application.  I don’t need to create a domain object that then gets transformed for every command or query I need to produce.  Once I have simple commands and queries, I can do a lot of pretty simple things without having to build a really complicated infrastructure.

In the long project I just completed, I did something like that. I had commands and I had queries. I didn’t have events and I didn’t even implement command handlers, but instead had each ICommand implementation implement an Execute method. One could argue that what I did was simply implement ‘bad’ Transaction Script procedural code, but you know what, I’m fine with that. The system (which was an entirely back-end system with no UI) is now such that, if there is a failure, it occurs within the single Execute method of a single ICommand implementation.

Is this really CQRS?  You could very easily argue that, no, it is not.  But, I’m fine with that.  It used principles and concepts from CQRS that helped make the existing application better, and that met the need that I had with application in question.

Should you avoid CQRS?

It is completely unfair, and, technically speaking, rather inaccurate, but I would recast this question in large part to asking whether you should avoid Event Sourcing.  The answer to that is, usually yes.  Think of commands (and the events they produce) and queries as messages, and then learn better ways of dealing with messaging.

To take another route, if you do try to go the more ‘advanced’ CQRS framework route, ask yourself a basic question.  Suppose you avoided some of the intricate problems you can get when you submit commands that you don’t know for sure will succeed, and so you don’t know for sure how to handle letting the caller (be it a UI element or not) handle when it fails down the road (so to speak).  Why not make the whole process be synchronous?  A command is created, sent, and handled, and the resulting events from that command are then published.  Technically, you don’t know for sure that once an event is published that the subscriber you care about picks it up and processes it.  So, as a thought experiment, why not have the calling code that creates and sends the command subscribe to the event publisher that tells you it worked? 

If that’s too complicated, as it could be, why not set up your command handler infrastructure to allow you to create command handlers that have a return value?  This is something that ‘breaks orthodoxy’ that I’ve had some success with.

It hasn’t been a waste of time

As with everything else in software development, you have to use judgment.  I am very ‘unorthodox’ in the sense that I don’t think it is a requirement that you be a software craftsman, or use TDD, or even have unit tests, in order to create successful software. 

When it comes to CQRS, though I attempt to understand all of the most sophisticated concepts involved in the most sophisticated expressions of it, I pick and choose the pieces that I think are the easiest and most productive.  Part of this is simply understanding my own limitations, where I know I’ll never be the greatest software developer in the world.  Part of this is simply understanding the limitations of the applications that I deal with, where I know that e.g. Event Sourcing is something that is genuinely overkill or gold-plating.

I still think that learning CQRS in toto can help you greatly as a developer to find ways to make your applications better.

And I don’t think you need any justification other than that.

posted on Sunday, April 24, 2011 11:17 PM Print
Comments
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
Justin
4/25/2011 1:49 PM
I think you've really hit the nail on the head with this post. It has not been a waste of time at all for me to learn about the concepts present in CQRS, even when my implementation choices do not include event sourcing, no-sql, or eventual consistency. I've gotten a lot of mileage from the ideas of separating domain/read models and encapsulating commands that have simplified the systems I'm building. Ironically, studying the advanced CQRS implementations have even resulted in using techniques I had once given up as "bad" design like writing t-sql and transaction scripts.

AS you said, all of the CQRS concepts may already have been present in SOA, messaging, and good OO in the first place, but for me, they really came together well when I started to see blogging on CQRS.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
jdn
4/25/2011 5:33 PM
@Justin:

Thanks.

In another part of his post, Udi says:

"And the biggest caveat – the above are generalizations, and can’t necessarily be true for every specific scenario. If you’re Greg Young, then you probably can (and will) decide on your own on these matters. For everybody else, please take these warnings to heart. There have been far too many clients that have come to me all mixed up with their use CQRS in areas where it wasn’t warranted."

Now, I wouldn't be surprised if there was a little bit of an inside joke going on here, but I also think you can extrapolate a little bit, especially as it relates to OO.

There's the standard apocryaphal joke of someone who says "This application only uses 19 of the 23 GOF patterns, but with the next iteration, I hope to use the remaining 4."

Despite what I've seen suggested, I've never argued that you shouldn't learn GOF design patterns. If you want to become a 'serious' developer (whatever that means, actually if you want to become a serious developer you should probably be coding in either C, C++ or Perl, but I digress), you should learn them.

At the same time, you should have it as a goal to learn when you don't need them. Though it isn't an exact parallel, I think you could say something similar when it comes to learning CQRS in its most sophisticated forms.

And, to be blunt, another reason why I don't think CQRS has been a waste of time is because I find it intellectually interesting/challenging. Along with Kanban, learning these concepts has made software development more interesting to me.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
Jack Jones
4/26/2011 10:37 AM
This post is "awesomely pragmatic" if that makes any sense. It's the best distillation and "use your head" advice of anyone I have seen on the topic. I have taken both Greg and Udi's courses, have applied what fits best and would agree with your entire post.

Learn all that you can, think about what makes sense, and do what works best. Blindly duplicating something that works well for others will often lead to difficulty. Applying knowledge to current context is what wisdom is all about.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
jdn
4/26/2011 6:24 PM
@Jack

Thank you for your comment, I appreciate it very much. I'm glad that someone grasped what I was trying to say.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
Matt
5/12/2011 1:42 AM
Great post. I have found it very frustrating reading so much material on CQRS that seems to imply Event Sourcing is tied into it.

I have found the logical separation of Reading and Writing so beneficial in itself.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
jdn
5/12/2011 5:39 PM
@Matt

Yeah, I think that's because so many of the sample implementations, as well as various blog posts from Udi and Greg, always include it.

I think there are many potential benefits of implementing full blown event sourcing, but it also can be pretty complicated, and doesn't have to be done.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
Vasilio
6/1/2011 2:40 PM
John, I couldn't agree more with everything here. Every bit of information is a useful, thought-out conclusion. And superbly pragmatic - which is a good thing - after all we need to use those "patterns" to create better software, not for the sake of patterns themselves.

The funny thing is that while learning about CQRS, I've finally come up with _exactly_ the same conclusions/architectural opinions (say, e.g. "Commands returning value", "CQRS can live without ES" and others).

The bad thing about CQRS in general is because not too much is info about that, and every piece of info is written in a "this-is-a-best-practice" fashion. And this "best practice" always tied up with Event Sourcing (which is a good thing too but has a much more narrow usage context IMO). But all you really need is concept understanding - separation of "C" and "Q" (isn't that the ONLY what CQRS stands for?).

You have to rethink everything by yourself but once you've come up with a really working solution, people are saying something like "commands shouldn't return value", "it's not a CQRS" which makes you doubtful about you even understanding the CQRS. This is a bad thing. As a side note: same story with strict following DDD which is sometimes leads to just unnecessary complexity.

To summarize:
Understanding benefits of separating C and Q _is_ understanding of CQRS imho. Event Sourcing, Messaging and so on are just different stories.

So, John, very nice opinion. I think this "opinion" is actually much more useful for the practical than the naked CQRS theory.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
jdn
6/1/2011 8:08 PM
@Vasilio:

Thanks for the kind comments.

I think your DDD comment is insightful, in that it cuts both ways. On the one hand, I think there is a bit of hero-worship involved with following Evans' book as if that is the be all and end all of what DDD is or isn't (and if I understand it correctly, even Evans thinks there was too much focus on the book in some respects).

On the other hand, I remember doing an open spaces type session at the Chicago Alt.Net group at one point a few years ago and one of the topics that came up was DDD, and there was this common misperception that if you had a model that was based on POCO, that meant you were doing DDD. At some point, I gave up trying to correct people about it.

There could be some of that in terms of people wanting to define CQRS in such a way that commands can't return values, etc., though I doubt it would be a conscious effort.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
nick
11/20/2013 8:53 PM
i hate how programmers are quick to jump into MVC, CQRS, WebApietc... without consideration of re-usability & security.
so many MVC projects i've involved in (not me making the architectural desicions), are so easily hackable, because they assume client-side javascript can't be hacked/overridden.
there's no tables relationship in one CQRS project, and yet there are no double checking after HTTP post
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
jdn
11/21/2013 12:09 AM
@Nick:

Your comment seems somewhat tangential, as there is nothing about client-side javascript that makes it more or less reusable or secure with, e.g., non-MVC projects.

But, it certainly is true that it is easy to be distracted by what is bright and shiny without learning important basics.
Gravatar
# re: cqrs for dummies – an interlude – has it all been a waste of time?
tuespetre
8/18/2014 5:01 PM
After scouring the webbernets for every morsel of software architecture conjecture I could find, I'm happy to see your post which confirms me in my recent realizations.

Virtually nobody needs events, dependency injection, domain driven design, messaging, javascript event stores, etc., at least at the start. Those who do will probably find that they need it as they come across problems that actually call for that stuff.

As for me, now... well, I'll be writing 'transaction scripts', which are known nowadays as commands... except I don't need:

- an ICommand interface,
- an ICommandHandler interface,
- an injection framework,
- a hierarchy of event-publishing domain driven design objects, and
- a weighty ORM

to make it work. I just need a static method, maybe with a 'FooCommandArgs'-style object, because:

- I'm not writing a piece of software intended to support multiple vendors and varying deployments, so if the day comes when our company changes database technologies, a port will take less effort than writing a new interface implementation
- Very few concepts truly need domain driven design principles applied, and even then, you could just extract the logic from the transaction script into specific methods or objects and *use the objects in the transaction scripts*
- I want everyone to be able to understand what the hell is going on in the code I write, I don't want to have to drag them through learning the nuances of a particular DI framework or ORM when something like a static GetConnection() method and some Dapper extensions will suffice

Post Comment

Title *
Name *
Email
Url
Comment *  
Please add 7 and 8 and type the answer here: