4.9.12

Assert Better Quality


In 1999, Andrew Hunt and David Thomas already suggested in "The Pragmatic Programmer" to Design with Contracts (TIP31) and to  use assertions (TIP33). They write about the benefits like concrete behavior  documentation or crashing early (TIP32). Furthermore, you tend to think more about the behavior itself and how you want to handle exceptions and failures.

In 2009, Janie Chang  found a relationship between Software Quality and assertions by conduct an empirical study on two Microsoft internal Software Components.
"The team observed a definite negative correlation: more assertions and code verifications means fewer bugs. Looking behind the straight statistical evidence, they also found a contextual variable: experience. Software engineers who were able to make productive use of assertions in their code base tended to be well-trained and experienced, a factor that contributed to the end results."
 So, time to take a look at the possibilities in Java :)

Assertions
Java has the reserved keyword assert  that can be used like
assert Expression1 ;
or
assert Expression1 : Expression2 ; 
The first expressions must result in a Boolean value, whereas the second  is used to specify the error message and must therefore return a value. Assertions are not enabled by default and must be activated using the JVM parameter -ea. Check the following code snippet for a concrete example:
public void doSomt(Integer i){
    assert i != null;
    assert i > 3 : "The first argument must be > 3";
}
A disadvantages of the Java assertions when enabled is the impact  on performance. However, in The Pragmatic Programmer it is suggested to leave the assertions turned on and remove only those assertions that really have an impact.
Furthermore, the possibility to turn them on or off can also be a disadvantage. If you are the only one in your team using assertions and other environments like daily or testing machines do not have assertions turned on, there is no benefit in using them.
Additionally, extra documentation is needed to carry these internal defined constraints to the outside world, e.g. interface method documentation.

Google Guava Preconditions
The guava-libraries include a class called Preconditions. It can be used to verify parameters in an easy and convenient way:

public void doSomt(Integer i) {
    checkArgument(checkNotNull(i) > 3,
                 "The first argument must be > 3");
}
If a constraint is a violated an standard RuntimeException is thrown: IllegalState, Nullpointer, IllegalArgument or IndexOutOfBounds. Therefore, the caller must be informed about these rules using documentation or tests. Thereby, the caller becomes responsible for passing the appropriate data (but not as strict as in Designing with Contracts).

 
So the question is how and when to use what!?

I think, a combination of both is more valuable than using just one subset. Use a library like guava-Preconditions or create your own classes for validating parameters. Add some documentation about the constraints and back them up with lots of unit tests.
Assertions on the other hand can be used for verifying internal states and post conditions, e.g. verifying that the last element is the lowest when the sorting algorithm is finished. During the local development phase assertions can be turned on and will definitely help to improve code quality.
The valuable part about it, is that you start thinking in more detail about the behavior and invalid states. Furthermore, you will save time as the program is going to crash early, meaning that you do not have to go through long stack traces just to find the real root cause.

In another entry I  will also write about Design by Contract and present some Java implementations.



No comments:

Post a Comment