Understanding design by contract is, I think, important for software quality in OOP because the principles are clear and efficient.
Assertions are associated to an object method and qualified in one of three categories :
- Preconditions are assertions true before executing the method
- Postconditions are assertions true after executing the method
- Invariants are assertions true before and after executing the method
Meyer includes his idea in the Eiffel programming language : the assertions are checked in a static way (at compile time).
If the Java programming language provides support for assertions, these are checked only in a dynamic way (at runtime) and disabled by default. Because of runtime checking, exceptions are largely used instead of assertions. In Java, a proper use of exceptions can be more meaningful to the programmer than a proper use of assertions because it provides more details about the malfunction conditions (the stack trace). At first glance, assertions (in the design by contract way) seem to be very far from exceptions. This is to some extent a paradox: I think the developer should consider assertions concepts every time he uses exceptions.
I think that, to respect Bloch terms,
- Runtime exceptions should be used for checking preconditions
- Checked exceptions should be used when preconditions are true but postconditions can not be satisfied, assuming that the method is correct (e.g. the network connection is broken).
If a runtime exception is raised, the calling method should be bugged (or its preconditions are not properly checked).
Some extensions to the Java platform provide support for static testing (assertions checking at compile time). For example, JML takes advantage of Java comments: this is interesting for traditional compiling compliance.