CQRS In Phases: Phase 1 - Separate Your Reads From Your Writes

(please read my Introduction post in this series for an explanation of what I'm trying to do)

The first "phase" in Command-Query Responsibility Segregation (CQRS) is probably the most straightforward and obvious - separating your reads (queries) from your writes (commands).  In a typical application (sorry, no samples), this basically means separating the queries that display data on the screen from the ones that perform inserts, updates and deletes on your database.

I should probably take a minute to explain the type of architecture I'm envisioning for this blog post, although benefits of the steps can be seen no matter your architecture.  For the phases, I'm imagining you have a domain model or at least a business logic layer which has business objects for each of the main entities in your system. In all likelihood, these business objects are being hydated from the database and also save their state back to the database.  Again, this isn't the only type of system that can benefit from some of the concepts of CQRS, but its what I have in mind mostly because it's what I deal with at work that I'm trying to improve :)

What do I mean by separate the reads from the writes?  Most them into different objects.  That's it.  If you use business objects, move the functions that read data from the database out of them and into another read-specific object.  If you just use a straight object for data access like a repository, break it up into two repositories - one for reading methods and one for writing methods.  Just separate the methods in your app that read data from the ones that write data.

With even just this simple step, you will see some benefits, including:

Your code, especially if you have business objects, will become simpler.
This may not be as applicable if you're not using business objects, but if you are - you have removed an entire responsibility from them.  The responsibility of hydrating themselves to display on the screen.  This means your business objects become more focused on what they're intended to do - validate things before they get created, updated, deleted, etc.

Increased ability to optimize your read query performance.
There are a few reasons for this.  The big one is that in most cases, your business object represents a row in a database table.  Even if you're using an ORM, you're mapping objects to database table rows. As such, you're usually querying entire rows, using lazy loading to get related child objects and other techniques in order to get the data you need to show a screen.

Once you've removed the concern of reading from business objects and put it into its own class, you're now able to use any techniques in order to get the performance you want.  You can write custom SQL queries to bring back just the data you need because you're not beholden to the business object definition.  If a stored procedure makes more sense here, use that.  If you only need two columns from a row instead of the entire row, just write a query that only returns those two values.  You have much more wiggle room this way.

So with just this simple change you've cleaned up your business objects and given yourself some leeway when it comes to optimizing your queries.  Not bad.

In the next post, I'll talk about the 2nd step as I see it - unifying the way data flows through the write side via the use of commands, events and handlers.

As I mentioned in my introduction post, if something here sounds wrong, or if I'm missing something - please let me know in the comments.  Feedback is very much appreciated.

  1. Introduction
  2. Step 1: Separating Your Reads From Your Writes
  3. Step 2: Commands, Events And Handlers

CQRS In Phases: Introduction

Lately, I've been a bit obsessed with Command-Query Responsibility Segregation (CQRS). I'm not quite sure if I'm late to the party or jumping on the bandwagon because I remember seeing a lot of noise around CQRS in my RSS feed a few months ago but didn't really bother with it at the time.  I'm not sure if it's still a hot topic or was a passing fad, but the more I read about it, the more interested I become.  I agree with a lot of the architectural principles, but I'm not going to re-hash those.

For anyone that wants to learn more about CQRS, http://cqrsinfo.com/ is a great starting place.  There are also great blogs out there maintained by Greg Young, Rinat Abdullin, Mark Nijhof, Jonathan Oliver and Udi Dahan - all of whom are far more knowledgeable on the subject than I am.

When you read about CQRS, you usually see what I call the full monty which includes using event sourcing (capturing all changes to an application state as a sequence of events), using separate databases for the read side and the write side and even distributing the application in the cloud.  There are very compelling benefits to using the full monty, but at the same time, I think there are benefits to using bits of the CQRS architecture without going all out.  So what I hoped to write about in these next few blog posts is dissecting some of the steps you can take in your code to achieve some of the benefits of CQRS without necessarily making it all or nothing proposition.

Allow me to reiterate - no CQRS information I've read has ever said that you need to do all the steps to see benefits in your application.  As a matter of fact, some things I've read have discussed the benefits as being independent.  I've just rarely seen the steps you can take broken out into logical pieces and the benefits of each discussed.  That's what I hope to do with this blog series.

Lastly, I hope to get some feedback from people with far more CQRS experience than I have.  If something I say sounds completely wrong, I'd love to know about it.  I'm just trying to distill the large amount of information I've digested into something that makes sense to me.  So I may have gotten something confused in all of my reading and I don't claim to be an expert.

My next post will talk through the first step I see towards CQRS - which is the most straightforward one... separating your reads from your writes.

  1. Introduction
  2. Step 1: Separating Your Reads From Your Writes
  3. Step 2: Commands, Events And Handlers