0

I'm having trouble grasping the value proposition of the "command" half of the CQS principle in a system that doesn't implement command query responsibility segregation.

The CQS principle states that a method that returns a value is a query, and should never affect state. A method that affects state, should never return a value.

The principle that a query should not affect state makes perfect sense to me. If you have queries in your system that change state it's hard to reason about the logic in your code, and if you forget that your code relies on the state change provided by the "query" call then it's easy to introduce bugs.

Even if your system has nothing to do with CQRS, you should strive to never change state in your methods that return a value.

I don't understand the value proposition of not returning a value from your commands.

What are the pitfalls of having methods that let's say return a "result" that contains information about the success of the command call?

What benefits does following that principle bring to your application?

  • 1
    A command that returns a value is a query that affects state. – Goyo Jan 21 at 0:32
  • 1
    @goyo That seems like a meaningless semantic argument. A command "SendEmail" does not become a query because it returns a "EmailSentResult" confirming it's success. Nobody is going to use the "SendEmail" command as a query to get it's result, and this isn't likely to cause issues later. The name of the method makes it clear what it does. A query "GetSentEmail" however, would pose a problem if it sent an email occasionally. It would be undocumented behavior, and could cause problems in the code since people would assume it has no effect. – Suren Jan 21 at 2:09
  • 1
    Well " a method that returns a value is a query", that's in the question itself and it is the usual meaning of "query" when people talk about CQS. According to that, your SendEmail command is also a query and whether it has Get in the name is irrelevant. If you want to use an alternate definition of "query" you should clarify. – Goyo Jan 21 at 7:54
1

According to Martin Fowler at https://martinfowler.com/bliki/CommandQuerySeparation.html, by returning a value in your command, you blur the line between mutator and accessor, and except under circumstances that require atomicity what you gain is limited to convenience. Success/failure is itself communicated either through exception handling, or by setting the system in a queryable failure state. Either way, the command would not need to return a value. If, on the other hand, you are returning information about the newly altered state, then that information can be queried for and again the command need not return a value.

What you gain by giving up that convenience is clear and specific confidence at a glance for which methods alter state and which do not. Using something like C as an example, you can be certain that any method with a non-void return type will never alter state, and you can use it as liberally as you please - whereas any method with a void return type will alter state and should be used more carefully. As Martin also mentions, there are times when it is useful to break CQS because it makes more idiomatic sense, such as the Pop method of a collection. It is a clearly defined operation, and splitting it into two separate methods, while fully possible, is less useful than keeping it as a single operation.

Likewise, as mentioned above, you also need to be careful in multithreaded settings where it is not guaranteed that the state is the same between adjacent operations and you require atomicity. In those cases, you may need to lock the state, mutate it, and return a value, which breaks the CQS principle but does so in a useful and mindful way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.