Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
scroll top