I am learning about preconditions and when to use them. I have been told
that the precondition
@pre fileName must be the name of a valid file
does not suit in the following code:
/**
Creates a new FileReader, given the name of file to read from.
@param fileName- the name of file to read from
@throw FileNotFoundException - if the named file does not exist,
is a directory rather than a regular file, or for some other reason cannot
be opened for reading.
*/
public FileReader readFile(String fileName) throws FileNotFoundException {
. . .
}//readFile
Why is this?
Edit: Another example
We are assuming that the following, as an example, is done the “right” way.
Note the IllegalArgumentException and the precondition. Note how the behavior
is well defined, and how the throws declaration is made even though
a precondition is set. Most importantly, notice how it doesn’t contain
a precondition for the NullPointerException. Once again, why doesn’t it?
/**
* @param start the beginning of the period
* @param end the end of the period; must not precede start
* @pre start <= end
* @post The time span of the returned period is positive.
* @throws IllegalArgumentException if start is after end
* @throws NullPointerException if start or end is null
*/
public Period(Date start, Date end) f
Are these examples avoiding use of extra preconditions? One could
argue that if we are avoiding preconditions, then why have them at all?
That is, why not replace all preconditions with @throws declarations (if
avoiding them is what is done here)?
Ok, so this is what I’ve found out:
Background
Based on the following principles, as described in Bertrand Meyer’s book
Object Oriented Software Construction:
, these two points answer this question:
system. Although, assertions are turned on to do this testing when debugging the system.
More on when, why, and how to use preconditions:
So a precondition should only exist if it is decided that the client holds the responsibility.
Since the server should not test the precondition, the behaviour becomes undefined (as also stated on Wikipedia).
Answers
the first
@throwsdeclaration implies that the method has (other than an assertion)tested the precondition. This violates the second point.
As for the null pointer; this shows that the null pointer responsibility is assigned
to the server. That is, using a "tolerant attitude", as opposed to a "demanding attitude".
This is perfectly OK. If one chose to implement a demanding attitude, one would
remove the throws declaration (but more importantly; not test for it), and add
a precondition declaration (and perhaps an assertion).