The Right Approach to Exceptions
sandford at jhu.edu
Sat Feb 18 22:21:38 PST 2012
On Sat, 18 Feb 2012 23:09:17 -0600, Jim Hewes <jimhewes at gmail.com> wrote:
> 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.
Not to jump on you in particular :) but bad user parameters should never be treated as exceptional. Even bad 'internal' parameters that are passed via the external API aren't exceptional. Programmers being lazy about input parameter checking is how hackers make their money.
>> 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
Yes, the USB stack has a high-level layer that can recover from a connection loss, but the rest of the protocol stack above and below it can't understand it and presumably ignore it. And you have just introduced a fairly long range dependency between the lowest level of your code and middle layer. (To say nothing of the implicit dependences implied with the intervening layers). This might be the best/only solution to the problem, but it also makes the code base larger and more fragile. I wasn't speaking in absolutes, but in relative difficulties.
> > 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.
Traditional error codes are enums and so what your describe as BadParameter is an exception wrapping an error code. I really hope no one has been proposing to map error code values to exceptions on a 1:1 basis. But your making many of my points; exceptions are (better, faster, stronger) error codes. My issue regarding the weak 'is a' relationship stems from the extra information in any given final typed exception being very specific to that particular exception. So its hard for me to see the rational between treating some of these as a group while not all of them: if MyGroupException is providing no more information then Exception, why can a function recover a MyGroupException and not a general Exception?
More information about the Digitalmars-d