The Right Approach to Exceptions

Jim Hewes 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 
error.


 > 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.

Jim



More information about the Digitalmars-d mailing list