At 03:24 PM 4/30/01 -0700, Jeffrey W. Baker wrote:


>On Mon, 30 Apr 2001, Matt Sergeant wrote:
>
> > On Mon, 30 Apr 2001, Jeffrey W. Baker wrote:
> >
> > > Yes precisely.  It used to be that you could only die() with a 
> string, but
> > > 5.<mumble> gave us die() with a reference to an object and at that moment
> > > the system was complete.  The creation of a rational exception object 
> type
> > > is left to the discretion of the system designer (thankfully).
> >
> > Well actually I personally would prefer proper exception semantics, but
> > unless someone re-writes Error.pm (or whatever) to be implemented using
> > Filter, then we're stuck with closures, which I'll avoid thank you.
> >
> > The things I don't like are:
> >
> > You currently have to do two blocks, one if ($@), and then
> > if($@->isa(...)) inside that. That's too much typing, when Perl is so
> > renouned for it's succinctness (is that a word?).
> >
> > The second thing is no finalize/always clause (you can sort of emulate it,
> > but it's not quite guaranteed like it is in languages that implement it
> > properly - we discussed this yonks ago on perl-friends, I'll try and dig
> > up the discussion if you want).
> >
> > The whole $@->isa() thing, it's just plain ugly, and doesn't really look
> > like exception handling - it looks like botched up OO code. It can/should
> > be more structured IMHO.
> >
> > It's also another case of far too many ways to do it, causing people's
> > perl code to look different everywhere, which is bad for maintainence.
>
>Well, the nice thing about the way Perl does it is that you can have your
>way, and boy am I glad I don't have to do it that way, too.
>
>I have learned that errors from down in the call stack are very rarely
>conditionally recoverable.  If I call obj->method(), and it throws an
>exception, there are few situations where the cause of the exception
>matters at all.  In most cases I will just not handle the exception, and
>it will bubble up.  In some cases I might want to log.  In others I might
>want to retry, or try plan B.  But, very rarely do I want to branch on the
>type of exception.  Right now I cannot in fact think of any program I have
>written that branches on the type of exception.  Java encourages this with
>multiple catch blocks, but I think it is stupid and anyway the catcher
>usually is not the primary source of knowledge about what the hell
>happened.  Think of it: the called program had to make a decision about
>what exception to throw, and now the caller is trying to decode that
>exception.  I believe that decisions should be made at the place in the
>program that has the most relevant information about the decision.  If you
>try to encode information into the exception object, you are encouraging
>some other part of the program to make a less-informed opinion.

This is why there is a difference between a runtime exception and a regular 
exception in Java. The regular exception encourages catching the exception 
and doing something with it as close to the original calling code as possible.

>My coding style dictates that a function or method will always do
>everything in its power to succeed.  If it returns an error code or throws
>an exception, that means permanent failure as far as that function is
>concerned.  In my C code, I usually find that I only need two values for
>my return value: FAILURE and SUCCESS.  I rarely need anything beyond that.
>
>The explicit exception declarations in Java piss me off, because they
>cause maintenance headaches.  Say you have a twenty level call stack.  At
>depth 0, you catch Exception, at depth 5, you catch FooException.  Let's
>say that a package API changes and depth 15 now need to throw
>BarException.  At some level, you now have to explicitly handle
>BarException.  You either have to do it at depth 14, or you have to change
>the declaration of every method up the call stack to the depth that *does*
>handle BarException.  This is more work than it needs to be.

If you really have something that convoluted, then the design of the error 
handling seems a bit odd. I've never had to deal with a depth of 14 
exception handling in my Java code yet. And as you say, the designer of the 
code should catch the exception close to the source -- the exception in my 
mind is an aggregate exception collector for logging errors at different 
levels of the app. But that's discussed below.

Generally if it's a caught exception, I try to do something with it right 
away. If it's something that I intend to log rather than catch so far up 
the tree, then I can convert it to a runtime exception which can bubble up 
the trace.

I would agree -- I don't know why you would do something with an exception 
in a place in code that knows less about why the exception occured. Except 
in a few cases:

1) Of course you catch certain exceptions at the caller level.

But if you take your analogy of wanting to catch the exception at the exact 
time of error, then this would argue that we need to provide callbacks into 
every object that actually get called when certain errors are encountered 
such that it gets caught inside the called library function itself and not 
outside of the called function stack.

But obviously this would be ludicrous to maintain and a royal headache and 
breaks the entire idea of encapsulating a method so that you aren't 
supposed to know exactly what the method does (or at least you arent 
supposed to care).

2) If you have a call depth of 14 with all different methods, then it seems 
ripe for reorganizing the structure so that there are less call stacks.

If you really need this functionality (eg maybe you are partitioning 
exceptions to provide different logging levels in your applications)...

then another thing you can do is convert it to a runtime exception. Just 
create a wrapper runtime exception that takes an exception in the 
constructor so that when you catch your wrapper runtime exception, you know 
that this is a special exception -- an exception that is not a normal 
runtime exception, but one that (A) You can catch yourself and detect it is 
an app level exception and (B) You can always get the original exception 
object out of it to find out what happened along with perhaps the stack 
trace of the original exception object.

---

I do agree that exception handling and why you do it is a bit of a black 
art. I think I have seen many programmers do it differently. And few really 
been able to explain to me why they do it that way (it makes a good 
interview question for Java though).

Even the books are very lukewarm on the subject... just touting some 
obvious aspects. The only place I ever saw a half-decent writeup on how to 
use exceptions in Java was by Bill Venners:

http://www.javaworld.com/javaworld/jw-07-1998/jw-07-techniques_p.html

Specifically I like the section on when to use Exceptions vs Errors. And 
when to use Checked versus Unchecked -- this is one that many Java 
programmers just don't have a clue about.

Why all this talk on Java? Well, although we do not precisely use 
exceptions (yet ... hopefully soonish -- Matt was probably right about 
CGI::Carp in the end -- I am getting sick of it's functionality always 
being patched) in our Perl app toolkit this article had a big influence in 
how I deal with errors and when I decide to truly die(), when to 
eval()/die() (for exception handling), and when to simply pass a silent error.

Later,
     Gunther



Reply via email to