Why You Should Separate Commands from Queries
This article is NWH, standing for Not Written Here. The concept of NWH is inspired from the NIH (Not Invented Here) syndrome which consists in refraining from using existing code from outside the company and reinventing the wheel every time. Just like it is good practice to look out for solutions developed elsewhere, we’re going to look at an article written elsewhere. Or said differently, an article that is NWH.
The NWH of today is Martin Folwer’s CommandQuerySeparation post. Check it out, it’s relatively short.
Even if the post dates back to the previous decade, I think its content is still valid today, if not evergreen. When reading it as a C++ developer, you’ll note how it sounds like marking member functions const
. Martin Fowler guesses it at the end of the article.
There is also another aspect of the separation of commands and queries in C++: exception safety. Indeed, beyond making interfaces more expressive, separating commands from queries is a great tool to make code exception safe.
And it’s amusing that pop
–which Martin Fowler regards as an exception to the rule–is a typical case to illustrate this.
The case of pop
Whilst we’re in an NWH, let’s check out another reference: Item 10 of Exceptional C++. Exceptional C++ is the best reference I know to understand exception safety in C++. In Item 10, Herb Sutter considers the very example of a stack’s pop
member function.
Here is the idea in a nutshell. pop
can throw an exception, if you call it on an empty stack. Now let’s assume that pop
returns the top element of the stack (by value), and consider the following code:
X x = s.pop();
After pop
has returned, the temporary value returned needs to be copied into x
. If this throws an exception, then the stack has been popped, the temporary has been destroyed, and all in all the value that was on the top of the stack has been lost.
However, the strong exception safety guarantee stipulates that the failed operations should have no side-effect.
Granted, in modern C++, the value would probably be moved and not copied, and in practice moves tend to throw less exceptions than copies.
But a stack is generic code and needs to work with any type. And some types don’t have move facilities implemented, only copies. Whether on purpose, or whether moves were accidentally deactivated because someone missed something about the rules of compiler generated functions.
Should private methods always be const
?
In a next post (homemade this time), we’ll explore another question that is related to the command-query separation: should private member functions be const
?
As we will see, this makes the code of class member functions more expressive, and as a result easier to maintain.
You will also like
- What Books to Read to Get Better In C++
- Should private methods always be const?
- The Rule of Zero in C++
- Compiler-generated Functions, Rule of Three and Rule of Five
Share this post!