What situations are best suitable for implementing assertions?
Internal Invariants:
Assertions can be used in if-statement construct where asserting an invariant is obvious.
e.g.
Before assertions were available: the following code snippet could be replaced
if (k % 3 == 0) {
...
} else if (k % 3 == 1) {
...
} else { // as is obvious (k % 3 == 2)
...
}
with
if (k % 3 == 0) {
...
} else if (k % 3 == 1) {
...
} else {
assert k % 3 == 2 : k;
...
}
Another good example for an assertion is a switch statement with no default case. An absence of default indicates that a programmer believes that one of the cases will always be executed. The assumption that a particular variable will have one of a small number of values is an invariant that should be checked with an assertion. For example, suppose the following switch statement appears in a program that handles playing cards:
switch(condition) {
case condition.ONE:
...
break;
case condition.TWO:
...
break;
case condition.THREE:
...
break;
}
One should add the following default case:
default:
assert false : condition;
If the 'condition' variable takes on another value and assertions are enabled, the assert will fail and an AssertionError will be thrown.
An acceptable alternative is:
default:
throw new AssertionError(condition);
Control flow Invariants
One of the most significant use of assertion is in placing it at any unreachable location. The assertions statement to use is:
assert false;
For example:
void testMethod() {
for (...) {
if (...)
return;
}
// Execution should never reach this point!!!
}
Replace the final comment so that the code now reads:
void testMethod() {
for (...) {
if (...)
return;
}
assert false; // Execution should never reach this point!
}
According to JLS if a program contains an unreachable code then it faces compile time error,if asserted that it is not reached.Another alternative for this could be throwing AssertionError.
Assertion do not support design by contract facility formally but some level of this feature can be used by using them.The set of preconditions ,postconditions and class invariant give that leverage to implement design by contract.
Preconditions
It means what set of conditions that must be satisfied before executing a method.A public method always guarantees checking of its arguments so use of assertions should be avoided in case of public methods.One can use an assertion to test a nonpublic method's precondition that will be true no matter what a client does with the class.
An assert can be applied in case of multithread blocks or methods which are private to ensure whether a lock on the object is retrieved before actually executing the code within.
Postconditions
The postcondition can be tested with assertions in both public and nonpublic methods. For example, the following public method uses an assert statement to check a post condition:
A simple operation of pushing an element on a stack can have a precondition that the element going to be pushed have a position less than the capacity of the stack and while element being pushed over the stack, it is equally important that new index is equal to old index plus one alongwith surety of an element being pushed on stack.This could be done using assertion as an example shown below:
public void push(int element) {
// precondition
assert num<capacity : "stack is full";
int oldNum = num;
stack[num] = element;
// postcondition
assert num == oldNum+1 && stack[num-1] == element : "problem with counter";
}
Class Invariants
A class invariant is applicable to every instance of a class at all times, except when an instance is in transition from one consistent state to another. A class invariant can specify the relationships among multiple attributes, and should be true before and after any method completes.