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