The Right Approach to Exceptions
Juan Manuel Cabo
juanmanuel.cabo at gmail.com
Sun Feb 19 05:53:09 PST 2012
I uploaded my little 2003 article on exception categorization to
github,
where I detailed my whole point_of_view_of_the_catch and
whole_program_invariant phylosophy for organizing clasess, and
compared
C++, .NET and Java hierarchies. Its not a professional article,
and I never wrote a translation to english:
https://github.com/jmcabo/ExceptionArticle/blob/master/articuloExcepciones_v2.pdf
--jm
On Sunday, 19 February 2012 at 10:30:45 UTC, Juan Manuel Cabo
wrote:
> Hello D community! This is my first post!! I hope I can bring
> clarity to all this. If not, I apologize.
>
> Some time ago I researched the best way to classify exceptions
> and build a hierarchy. I came up with the following rules:
>
>
> 1) At the top level, there would be RecoverableExceptions and
> FatalExceptions (or you can call them something like
> CatcheableException and FatalExceptions, or Exception and
> Error).
>
> 2) Fatal exceptions shouldn't be catched. They imply that the
> program lost basic guarantees to go on (memory corruption,
> missing essential file, etc.). You could catch them if you
> wanted to, but it makes no sense other than at your top-level
> method (main(), etc.).
>
> 3) A RecoverableException can be converted to a FatalException
> by rethrowing it, once a catch decides so. You shouldn't do the
> reverse: a FatalException never should be converted to a
> RecoverableException.
>
> 4) It makes no sense to subclass FatalExceptions since there
> won't be a catch that groups them in a base type (since they
> are not catcheable).
>
> 5) Only create a new RecoverableException class type if it
> makes sense to write a catch for it alone. Otherwise, use an
> preexisting type.
>
> 6) Only group RecoverableExceptions in a category if it makes
> sense to write a catch for that category. Please don't group
> them because its fancy or "cleaner", that is a bad reason.
>
>
> Who decides when an Exception is Unrecoverable? Library code
> almost never decides it, since an exception is only
> unrecoverable if the whole_program_invariant got broken, and
> libraries are only a part of a program. So they will tend to
> throw RecoverableExceptions, which can be reconverted to
> Unrecoverable by the program.
>
> In some cases, it is clear that an exception is Unrecoverable.
> When you call a function without satisfying its arguments
> precondition (ie: null argument) the only way to fix that is by
> editing the program. You shouldn't have called it like that in
> the first place, why would you? So you let the
> UnrecoverableException bubble up to your main function, and log
> its stacktrace to fix it.
>
> Unrecoverable means the program got 'tainted', basic guarantees
> got broken (possible memory corruption, etc.). Most exceptions
> will be Recoverable.
>
> Now, expanding on the hierarchy: I said that it makes no sense
> to subclass UnrecoverableExceptions. Recoverable exceptions on
> the other hand, need to be subclassed
> _with_the_catch_on_your_mind_. You are passing info from the
> throw site to the catch site. The catch block is the
> interpreter of the info, the observer. You are communicating
> something to the catch block.
>
> So please, do not create a new types if there is no value in
> writing a catch that only cathes that exception and that can
> recover from that exception. Otherwise, use an existing type.
>
>
> I wrote these rules some time ago. Please excuse me if they
> come off a bit pedantic!!!!!!!!!!!! Its all only a clarifying
> convention.
>
>
> According to all this:
>
> * FileNotFoundException is useful. It tells you what happened.
> It is a RecoverableException (under my convention) because
> until it reaches the program, the library doesn't know if the
> program can recover from that (it could be a system missing
> file, or just a document the user asked for).
>
> * DiskFailureException is only useful if someone can write a
> catch for it. If so, then it is a RecoverableException. Only
> the program can decide if it broke basic guarantees.
>
> * Most argument exceptions are Unrecoverable. A function
> throwing shouldn't have been called like that in the first
> place. The only fix is to go back to editing the program.
> (precondition broken).
>
>
> Another thing: you cannot decide whether an exception is
> Unrecoverable based only on whether the thing that got broken
> is the postcondition of a function. It is the
> whole_program_invariant that decides that. For instance:
> findStuff(someStuff) might not know if someStuff is important
> enough for the stability of the program if not found. The
> postcondition is broken if it doesn't return the Stuff. That
> might be recoverable.
>
> And PLEASE: don't make classifications by the point of view of
> the cause of the problem. DO make classifications by the point
> of view of the fixing/recovery of the problem; the catch block
> is who you are talking to.
> FileNotFoundBecauseFilesystemUnmounted is worthless.
>
> So, to sum up: (1) it makes no sense to subclass fatal
> exceptions, and (2) never subclass a RecoverableException if
> you are not helping a catch block with that (but please do if
> it aids recovery).
>
> ..so verbose and pedantic for my first post... yikes.. i beg
> forgiveness!!!
>
>
>
>
> On Sunday, 19 February 2012 at 09:27:48 UTC, Jonathan M Davis
> wrote:
>> On Sunday, February 19, 2012 19:00:20 Daniel Murphy wrote:
>>> I wasn't really serious about implicit fallthrough.
>>
>> Lately, it seems like I can never tell whether anyone's being
>> serious or not online. :)
>>
>>> Out of the syntaxes I could come up with:
>>> catch(Ex1, Ex2 e)
>>> catch(e : Ex1, Ex2)
>>> catch(Ex1 | Ex2 e) // java 7 syntax, horrible
>>>
>>> I like (e : list) the best. Naturally it would also accept a
>>> type tuple of
>>> exceptions.
>>>
>>> http://d.puremagic.com/issues/show_bug.cgi?id=7540
>>
>> LOL. Personally, I actually think that the Java 7 syntax looks
>> great (I'd never seen it before), but catch(e : Ex1, Ex2) is
>> just as good and more consistent with the language as a whole,
>> since it doesn't try to give any operators a new meaning (as
>> Java's does).
>>
>> - Jonathan M Davis
More information about the Digitalmars-d
mailing list