I agree, exceptions should always be used to indicate that a method cannot
meet its contract.  However, there are three completely different reasons
that may cause this to happen:

1) An environmental error.  E.g. failing to meet a postcondition because of
events beyond the programmer's control (I/O failure, network connection
failure, etc.).
2) A programming error. E.g. failing to meet a method's precondition or
postcondition, or a class invariant or loop invariant.
3) An implementation error.  E.g. the interpreter itself has failed and can
no longer be trusted to run the program correctly.

A program can try to recover from exceptions that report errors of type (1)
or at least gracefully fail.  A program cannot safely recover from errors of
type (2) and (3) because they have left the program in an unknown state.  If
components of a program can be safely isolated then it is possible to
recover from these types of errors with increasing amounts of reliability
depending on the complexity of the isolation -- transactions, byzantine
general algorithms, etc.

A well factored exception hierarchy should reflect these distinctions.
Java's, for example, does not!  Ruby's is much better by comparison, but I
would like to see this categorisation at the top level.  Something like:

Exception
    EnvironmentalError
        SecurityError
            file permissions, data tainting etc.
        ResourceExhausted
            disk full, etc.
        ResourceUnavaliable
            file not found, network failures, etc.
        etc.
    LogicError
        PreconditionError
            index out of bounds, range error, invalid parameters,
dereferencing null, etc.
        ClassInvariantError
        LoopInvariantError
        PostconditionError
    ImplementationError
        out of memory, heap corrupted, etc.

Cheers,
            Nat.

From: <jweirich / one.net>
> I have a different take on exceptions.  I believe exceptions should be
> thrown when the called method has failed, where failure is defined as
> unable to met its contract (either formally defined via Design by
> Contract or informally defined some other way).  Trying to communicate
> exactly how a method fails through exceptions unnecessarily couples
> the client code to the supplier code.
>
> For example, suppose we have method do_something() that can throw an
> OutOfRangeError or a InverseNotFoundError exceptions (just examples).
> We carefully handle both of these errors in our client code.  Then our
> code is given an object that implements do_something() via a network
> proxy object.  All of a sudden we could possibly get a NetworkError
> exception as well.  If our code doesn't expect a NetworkError, then we
> have problems.
>
> We should expect exceptions to happen and handle them, but trying to
> anticipating all the failure modes and responding differently in each
> case is a dangerous path.   I believe that treating all exceptions as
> failures (without distiguishing different failure modes) is a better
> way to go.
>
> Of course, this is just my take on exceptions.  I know others
> disagree.



________________________________
Dr. Nathaniel Pryce
B13media Ltd.
40-41 Whiskin St, London, EC1R 0BP, UK
http://www.b13media.com

XP Day, London, UK. 15th December 2001. http://xpday.xpdeveloper.com/