How I learned to love separation (CQS / CQRS)

I’ve mentioned it before: I’m lazy. When it comes to writing code, I’d like to read as little code as possible. I don’t want to have to read the code for every class I want to use. I don’t want to have to investigate side effects for every method I want to call. All of that is additional work when it comes to writing code — and none of it is writing code.

Why do we generally only apply this rigorous look to code within our own code bases instead of third party libraries? It’s because so many of us are well aware of the issues and code smells existing within our code bases but aren’t familiar with the smells in the third party code that we rely on every day. How did this trust issue come about? When did we stop trusting our own code?

Gotta have trust

As with most technical debt, it likely happened a little bit over time. Someone was running out of time and hacked together a quick fix that added an unexpected side effect to a method. Then the same thing happened again and again until we could no longer be sure what our code was going to do once it compiled. This code isn’t generally written with the idea that it’s going to be permanent debt. It’s just temporary! We’ll come back and fix that the right way a little later! Right? Wrong. Generally, that debt is going to exist in our code base for a long time.

Broken windows are just the start of serious degradation

That small amount of debt will act like a broken window. Technical debt will cling to it as people work around it instead of fixing it. Over time, trust in our code base is eroded, and development velocity slows to a crawl. We are all to blame.

But the good news is, this does not need to be a permanent condition! We can rebuild it. We have the technology. Where should we start? I recommend updating the code so that it behaves in the manner you expect. Every developer will implicitly read intent out of every line of code you write. You used FirstOrDefault() instead of SingleOrDefault()? Someone is going to think that multiple values are expected and not cared about. Developers don’t want to have to think that hard when they are writing code. We all want things to behave as expected, it’s just good design philosophy.

Let’s move towards command-query separation.

Sometimes separation can be a good thing

“Every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer. More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.” -Wikipedia, Command-query separation

When code that performs an action or side effect doesn’t return anything, we can infer from the method signature that a side effect is occurring. Otherwise there wouldn’t be any reason to call a method that has no return value. The intent of the contract is implicit. These are command methods.

Query methods have a return value, and no side effects. You can invoke them again and again and the state of the application never changes. The method signature has a return value, and the user should be able to infer that no side effects are occurring and they have no need to worry about what they might be doing by invoking this method.

“Functions should either do something or answer something, but not both.” -Robert C. Martin, Clean Code

Based on these definitions, we can come to the conclusion that it is okay for a command method to invoke query methods. The inverse is not true. It is not okay for query methods to invoke command methods, since that would be introducing side effects into your query.

This has the positive impact of allowing you to minimize the time you’re spending reading code and maximize the time you spending writing code.

Let’s take a look at some examples of using command-query separation:

public class PhoneBook
{
  public class PhoneBookEntry
  {
    public string Name { get; private set; }
    public string PhoneNumber { get; private set; }

    public PhoneBookEntry(string name, string number)
    {
      Name = name;
      PhoneNumber = number;
    }
  }

  public Dictionary<string, PhoneBookEntry> Entries { get; private set; }

  public PhoneBook()
  {
    Entries = new Dictionary<string, PhoneBookEntry>();
  }

  public PhoneBookEntry Add(string name, string number)
  {
    var entry = new PhoneBookEntry(name, number);
    Entries.Add(name, entry);
    return entry;
  }
}

This breaks command-query separation. Add() is both adding a new entry, and returning that entry. This is how that should be refactored:

public class PhoneBook
{
  public class PhoneBookEntry
  {
    public string Name { get; private set; }
    public string PhoneNumber { get; private set; }

    public PhoneBookEntry(string name, string number)
    {
      Name = name;
      PhoneNumber = number;
    }
  }

  public Dictionary<string, PhoneBookEntry> Entries { get; private set; }

  public PhoneBook()
  {
    Entries = new Dictionary<string, PhoneBookEntry>();
  }

  public void Add(string name, string number)
  {
    var entry = new PhoneBookEntry(name, number);
    Entries.Add(name, entry);
  }

  public PhoneBookEntry Get(string name)
  {
    return Entries[name];
  }
}

I have removed the return from Add() and added a Get() that grabs the entry requested and does nothing else. (Keep in mind that this whole example is over-engineered to being with, but it’s just an example.)

What other benefits do you get with command-query separation?

Developer velocity is not the only benefit from this. It is also easier to write tests when code is written this way. No longer do your tests for a method need to be worried about both command and query. Instead, you can just test a single thing and end up with more flexible and readable tests.

Overall, you should see an increase in developer happiness and that excites me. I hope to one day work in a utopia where none of the developers are complaining that the existing code base has significant technical debt (which is every mature code base I’ve ever worked in) and instead can talk not only about specifics, but what they are going to do to resolve those issues.

“The other main benefit is in handling high performance applications. CQRS allows you to separate the load from reads and writes allowing you to scale each independently. If your application sees a big disparity between reads and writes this is very handy. Even without that, you can apply different optimization strategies to the two sides. An example of this is using different database access techniques for read and update.” -Martin Fowler, CQRS

Advertisements

One thought on “How I learned to love separation (CQS / CQRS)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s