Command Query Separation

FunctionalProgramming takes advantage of functions that do not change the state of the program through the use of LazyEvaluation and ReductionSemantics. These strategies delay calling a function until it's absolutely needed (possibly never) and caching values once they are calculated, respectively. DesignByContract uses non-state changing functions in order to expose the conditions enforced by the contracts. Some changes of state are unavoidable and even desirable while others don't change the externally visible state of the system. Most programs change the persistent state of the computer. So while there are appealing strategies that can only be applied to state-preserving operations it must be recognized that these operations must co-exist with state-modifying operations.

Therefore:

Separate state-preserving operations (call them queries, or selectors) from state-modifying operations (commands, or modifiers). Implement CallByNeedSemantics and contract enforcement only in terms of queries.

In C++ "const" methods almost have to be queries. No -- in C++ selectors almost have to be "const".


As an example, see IteratorSemanticsAreWrong, where we look at the Iterators of the JavaLanguage, which probably violate CQS.


Is it desirable to restrict all Query functions to be non-throwing?

No, some queries may only make sense in a particular state and so should raise a precondition failure or throw an IllegalStateException, for example.


KevlinHenney wrote an article in the December 2000 issue of JavaReport where he demonstrated that CommandQuerySeparation is not an absolute design rule, but a pattern that applies in some situations and not in others. In particular it does not work well in concurrent systems.

Article URL: http://www.adtmag.com/java/articleold.asp?id=1923&mon=12&yr=2000 Another link in case of trouble with previous link: http://www.two-sdg.demon.co.uk/curbralan/papers/ATaleOfTwoPatterns.pdf

E.g. issuing queries and commands to the same object is not atomic unless you synchronise externally to the object (which is error prone, and therefore a CodeSmell).


CommandQuerySeparation is a special case of the idea that a method should do one just identifiable thing for the caller. Notice that if you were really going to name a command-query bundled method nicely, you'd probably use the word "and" in the name.

For instance, if there were no stack metaphor, pop might be called removeAndReturnLastElement.


See also: ResultSetSizeIssues


CategoryObjectFunctionalPatterns


EditText of this page (last edited October 10, 2014) or FindPage with title or text search