An assertion enforces a rule about something that should be unchanging in your code and would otherwise go unchecked. You can use an assertion for added safety anywhere you want to verify your assumptions about program behavior that can’t be checked by the compiler. A common situation that cries out for an assertion is testing for multiple conditions or values where one should always be found. In this case, a failing assertion as the default or “fall through” behavior indicates the code is broken. For example, suppose we have a value called direction that should always contain either the constant value LEFT or RIGHT:
if ( direction == LEFT )
doLeft();
else if ( direction == RIGHT )
doRight()
else
assert false : "bad direction";
The same applies to the default case of a switch:
switch ( direction ) {
case LEFT:
doLeft();
break;
case RIGHT:
doRight();
break;
default:
assert false;
}
In general, you should not use assertions for checking the validity of arguments to
methods because you want that behavior to be part of your application, not just a test
for quality control that can be turned off. The validity of input to a method is called its
preconditions, and you should usually throw an exception if they are not met; this elevates
the preconditions to part of the method’s “contract” with the user. However,
checking the correctness of results of your methods with assertions before returning
them is a good idea; these are called post-conditions.
Sometimes determining what is or is not a precondition depends on your point of view.
For example, when a method is used internally within a class, preconditions may already
be guaranteed by the methods that call it. Public methods of the class should probably
throw exceptions when their preconditions are violated, but a private method might
use assertions because its callers are always closely related code that should obey the
correct behavior.
Finally, note that assertions can not only test simple expressions but perform complex
validation as well. Remember that anything you place in the condition expression of an
assert statement is not evaluated when assertions are turned off. You can make helper
methods for your assertions that may contain arbitrary amounts of code. And, although
it suggests a dangerous programming style, you can even use assertions that have side
effects to capture values for use by later assertions—all of which will be disabled when
assertions are turned off. For example:
int savedValue;
assert ( savedValue = getValue()) != -1;
// Do work...
assert checkValue( savedValue );
Here, in the first assert, we use the helper method getValue() to retrieve some information
and save it for later. Then, after doing some work, we check the saved value using
another assertion, perhaps comparing results. When assertions are disabled, we’ll no
longer save or check the data. Note that it’s necessary for us to be somewhat cute and
make our first assert condition into a Boolean by checking for a known value. Again,
using assertions with side effects is a bit dangerous because you have to be careful that
those side effects are seen only by other assertions. Otherwise, you’ll be changing your
application behavior when you turn them off.
0 comments:
Post a Comment