The Right Approach to Exceptions
jimhewes at gmail.com
Sat Feb 18 21:09:17 PST 2012
On 2/18/2012 5:59 PM, Robert Jacques wrote:
> But you _always_ know what went wrong: An unexpected error occurred
> while trying to do X, where X is whatever is inside the try-catch block.
> Exceptions are for exceptional situations...
Not to jump on you in particular for using the phrase "exceptions are
for exceptional situations”, but I've always heard people say this in
arguments about exceptions vs. returning error codes. Unfortunately
those people usually never go on to define what exceptional situations
are, so those trying to learn about using exceptions are left no better
off. If exceptional cases are like divide-by-zero or hardware failures,
then surely a bad parameter to a function is not “exceptional”. Then
what? Is out-of-memory exceptional or something you should expect might
happen given that memory is finite?
I think of exception handling as tied to contract programming. A
function has a specific job that it's supposed to do. If for any reason
it cannot do that job successfully, an exception should be thrown. That
can include even bad parameters (although if you have bad parameters to
internal functions I'd think that is a design bug and could be handled
by asserts). Look at the .NET library; it seems to work this way. So I
think the term 'exceptional situations' has been kind of useless.
> and not supposed to be used as
> a form of out of band information return (or at least that's what every
> programming book tells me).
If what you mean is that exceptions should not be used to return
information when the function is successful, I agree. But it can be used
to return extra details about errors when a function fails.
> I see typed exceptions as having a strong
> coupling problem; exception handling that is aware enough to handle a
> typed exception, is so close to the exception generation code that most
> of the information conveyed by the 'type' is also conveyed by the
> context. Now, the further away exception handling gets from exception
> generation, the less information context coveys, but the ability of the
> handler to do anything smarter than log the exception and retry / cancel
> becomes less and less.
I can't say agree there, if I'm understand you right. Not every
exception coming out of a function was generated by that function. It
may have come from several levels below that. Maybe you can handle the
former because it is more immediate but not the latter. So without
exception types how would you know the difference between them? You
could use error codes and switch on them but it defeats one of the main
purposes of exception handling. So I think if there are exceptions
generated from further away, it's an argument _for_ exception types
rather than against it.
I can think of a example. At work I wrote a driver that communicates to
a device over USB. If the device is suddenly unplugged, the lowest level
of code throws a “connection” exception. And this can happen in several
places. Most levels can't do anything about this (other than just be
exception safe) and the exception just percolates up where things get
closed and cleaned up. However, it would be possible, though not
currently implemented, to recover from this such that the driver waits
for the device to get reconnected and refreshes handles and all that,
and the application and user above never need to know. Where that
recovery happens isn't necessarily at the lowest level but somewhere in
a middle layer. So I think having a particular exception type is useful
here. But I don't want to have to check error codes because under normal
circumstances there are just too many places to check for this type of
> The other issue I see with typed exceptions is
> that the classic 'is a' relationship seems weak; to be informative and
> useful and exception must map to a specific or small set of
> error/unexpected conditions. However, this specificity naturally leads
> to large number of final classes, which isn't really leveraging OO
> principals. It's hard to see what, if any, benefit the intermediate base
> classes give over a generic exception.
Well, I think what H.S Tech has been saying in this thread makes sense
to me. You can have an exception hierarchy where base classes represent
groups or classes of errors that you can check for without having to
catch all exception. But you don't have thousands of classes where you
map each possible error code to a unique class. You can just have more
general types and then put the specific information in the exception.
For example, just have one BadParameter exception and then store
information about which parameter is bad and why in the exception.
More information about the Digitalmars-d