Checking the Preconditions

Bill Venners: One of the recommendations you make in your book Object-
Oriented Software Construction that has always surprised me is the notion that
under no circumstances shall the body of a routine check for the precondition of the
routine. I understand that you don't want to have the same condition being tested in
multiple places, both the client and the supplier, as you called it, but you also said, "If the
client's part of the contract is not fulfilled, that is to say if the class does not satisfy
precondition, then the class is not bound by the post condition." So the supplier class can
either throw an exception or return a wrong result. I tend to prefer defining exceptions
that will be thrown if preconditions are broken, because then the behavior of the routine is
specified even under broken preconditions. The behavior of the routine is fully specified.
That's my intuitive preference. Could you describe your reasoning for recommending the
other approach?

Bertrand Meyer: I don't think you're expressing a preference with respect to
language rules, but rather, a preference for a design style that puts more responsibility on
the supplier. That is to say, you prefer a design style in which the supplier in effect
extends the specification to account for more cases. In the end, it's really a matter of
design style. Personally, I have found it far more effective to define for each operation the
conditions under which it will work, and leave the behavior undefined in other cases. I
think in the end it's a more effective approach.

If you take the viewpoint of the client, what happens typically is this: You are writing
some software and you instantiate a class. Assuming you are programming in a context in
which the only way to use the class is through it's specification, which includes the
contract, you'll see the pre-condition. If you are a reasonable client programmer, if you
know what you are doing, you'll know to program against the precondition. Of course,
you may not like the precondition. You may find it's too demanding, but that's life. It's
part of the contract. I think that style works pretty well.

The other style is a bit more problematic. For example, I recently looked at some
collections classes from .NET. You can see the interface for a certain library class, but
you don't necessarily see the exceptions. If you're careful and serious, you will go deeper
into the documentation of the class and see that some exceptions can be raised in certain
cases. If you want to process such cases, you'll have to write a try catch structure in your
own client code. That structure is actually more complicated than dealing with the
negation of the precondition in the first place, because you're trying to do some task, and
after the fact you have to catch possible violations and try to recover. So
you will actually end up doing the same thing either way, but it's more complicated to
deal with it after the fact than if you just checked the precondition in the first place.
Likely, however, many programmers are simply not going to take the trouble to look at
these exception clauses, or they might miss some of them. If something wrong happens,
some exception will occur, and there's no guarantee at all whether and how the exception
is going to be processed. Is it going to be processed properly? Is it going to be passed
back up the call chain to a routine that has no clue about what actually happened? So it
seems to me that this approach is really a way to ignore the problem, to put your head
in the sand and pretend that nothing is going to happen, when in fact things can happen.
It is better to tackle the problem head on, to have a specification that explicitly says what
is expected of the caller to get correct treatment, and to make sure before the call that
these conditions are satisfied.