CQS – an easy, yet powerful pattern

CQS – an easy, yet powerful pattern

CQS stands for the command query separation. There’s a chance that you may have not heard about it, but on the other hand the CQRS might ring a bell. Even though these 2 patterns have very much in common, there is a significant difference (definitely a bigger one than the additional “R” character within the CQRS acronym) in how do they apply to the architecture of our system. In this post I’ll focus on the CQS – the older brother of the CQRS – that will help you understand how to design the software that is less error prone.

 

At first, I do encourage you to read the formal definition of the CQS on the Martin Fowler’s blog, in case it’s really the first time you have ever heard about this term. Honestly, it’s quite easy pattern to understand, basically it all boils down to just a two principles: first one about executing an action via command that has side effects, and the second one about fetching the results via query that has no side effects. But let us not be mistaken, simple is powerful (especially here). So what is the CQS really about? Well, there are two things to remember:

  1. The command mutates the state, but does not return a value.
  2. The query returns a value, but does not mutate the state.

So what does it really mean? Let’s take a look at the example below:

As we can see, the method Create() does not return any value. Its only job is to create a new user account (and probably perform some validation first etc.). The important part here is that we are certain that this action has some kind of “side effects” (new user account will be created), so it does mutate the state.
On the other hand, both the GetByEmail() and FindAllByName() functions, do not have any kind of “side effects” (do not mutate the state). These actions (queries) are responsible only for fetching the users from some data storage. It means that we can execute them N number of times, and we will always get the same results.
Having that knowledge, we can redefine the above principles into something like this:

  1. The command has side effects (e.g. creates and saves a new entity) and will be of type void (or Task for the async methods).
  2. The query has no side effects and will be idempotent (always returns the same output e.g. the list of users).

And these are the most important pieces of the CQS pattern. You don’t really have to use the command and query handlers to follow these principles. Surely, they do fit well with this pattern but are not crucial. The important lesson here is to keep in mind that if you try to design the business logic in a way that the read & write operations will be separate from each other, it will help to reduce the number of errors (some unknown behavior/side effects) and also improve the scalability of the application (you could move read & write operations into the separate services, like physically separate not just logically). Anyway, before you try the CQRS (which is a far more advanced pattern) make sure you master the CQS first.

13 Comments CQS – an easy, yet powerful pattern

  1. Pingback: dotnetomaniak.pl

  2. Pingback: I command you (pattern) | Piotr Gankiewicz

  3. Pingback: .NET Core + RabbitMQ = RawRabbit | Piotr Gankiewicz

  4. Pingback: Async HTTP API and service bus | Piotr Gankiewicz

  5. Gemma Black

    For the query side, would you ever use a viewmodel or just plain data objects that feed into the view? …or maybe something else. And thanks for the article. I love the principles of CQS and CQRS and am trying to figure a good way of passing data to my views with a separate model.

    Reply
    1. Piotr Gankiewicz

      Hi Gemma,
      For me, the CQS is all about separating queries and commands. The CQRS, on the other hand, is a sort of sophisticated implementation of the CQS extended with the fast read database (or any other type of storage).
      I’m using the CQRS in some of my recent projects (based mostly on the microservices architecture), and I have a single database for fast reads that stores already flattened objects (e.g. ViewModels or DTOs) that can be directly returned to the consumer – I hope that helps.

      Reply
  6. Pingback: Becoming a software developer – episode VIII | Piotr Gankiewicz

  7. Pingback: Becoming a software developer – episode XIII | Piotr Gankiewicz

  8. B

    First let me say that I’m a huge fan of your writing…very informative yet super simple to digest!!
    Question – Lets say you were to write a method to generate a csv file with some data pulled from a bunch of tables. After you’ve generated the csv and stored it somewhere successfully you’ll need to update the status in some table indicating the operation was succesful.

    How would you apply CQS in this scenario? As i understand CSV generation is an idempotent action (Q of the CQS) however updating the status of that action is a side effect which you can’t avoid if you need to report it right away. One thing I could think of is to use Domain Events to update the status however I’d like to know your professional opinion. Also are Domain Events considered a side effect?

    Reply
      1. Piotr Gankiewicz

        Hi, thank you, happy to hear that! 🙂
        At first, domain events, or other types of events are not really a side effect, well, as long as they’re part of the method that already processes the data. I’d probably just pull the data (Q) and then either directly process it and update the status of an action (C) or pull and then send a domain event that could be consumed by a specific command handler.

        Reply
        1. B

          Thank you the response, Piotr. So as I understand and just to confirm you’d write this operation/method in the query part of our code since it’s a read from the db but then you’d write the “export the data to a csv” functionality in the query part as well? Or would you send the data read from the Db as a domain event to be exported aka written it in the “command” part?

          Also would the command and query part live in the same solution and project or same solution different projects or two separate solutions all together?

          Reply
          1. Piotr Gankiewicz

            I’d write 2 separate methods or maybe even components. The first one would be responsible for reading only (Q), and the second one for storing the updates (C). Most likely, I’d make these operations asynchronous, so you could either stream the data (read from a file and push it further), so it goes to the component responsible for the updates or from time to time invoke its method.
            You could also make use of the domain events or even send the data through the service bus (yet be careful here) and have the 2 separate applications (services) running.

Leave A Comment

Your email address will not be published. Required fields are marked *