Examples given here of good exception usage look like:
doSomethingSimplePossiblyExcepting handleExceptionRightHereThis is easy to understand and to deal with. What is more problematical is code that sets itself up to deal with exceptions in a huge process. For example, ChryslerComprehensiveCompensation has a handler that surrounds the payment of each Person. If anything goes wrong during payment, we issue a notification, put the Person into a suitable state, and carry on. The good news is that this ensures that everyone gets a chance to be paid, and no one Person can break the whole payroll.
However, when you're working with some nitty detail down in the guts of the system and this handler is active, it acts like a giant ComeFrom, as one of our colleagues refers to it: you wind up in the handler and have no idea where you came from.
I wish I'd said something more definitive and helpful than AvoidExceptionsWheneverPossible, but my practice is never to use them until I have to, rather than throwing them and handling them at every opportunity. -- RonJeffries
Does a Smalltalk exception have no information describing where it came from? -- KielHodges (not disagreeing, just curious)
Well, once an exception is handled, the call stack is ripped back all the way to the handler. You can find some stuff out, but nothing like you can in an ordinary debugger where you can see each line of code that's currently ?active? all the way back to the original call. You get to do old-fashioned ?print? debugging. Or remove the handler, which is what we actually do. -- rj
In a debugging situation, can you have Smalltalk halt before the exception is handled? I take it from your comments that you cannot.
BTW, VisualBasic lets one set an option to ?Break on All Errors?. Which is like having a car with a rusted body, blown engine and four flat tires, but with a really nice jack. :-) -- KielHodges (surprised to have finally found something to like about VB)
Doesn't ConvertExceptions address this one?
Why do you need to know where you came from? Is this another debugger problem? If so that would be a language/debugger/framework problem (see my comment on ExceptionsMaskRealProblems).
If you don't have the information you need to write the handler, then redesign until you do. This may mean handling the exception closer to the point of error, or it may mean putting more information into the exception object. It often means two handlers. The first will be close to the error, and so has enough knowledge about the error's context to restore the system to a sane state. It then rethrows the same exception (or possibly a different one (ConvertExceptions)). The second, higher level handler logs the error, abandons the transaction and goes on to the next transaction. -- DaveHarris
(I rewrote the above to make it clearer, and deleted dialogue which arose from the confusion. -- DaveHarris)
I'd just love to see some statistics on the percentage of errors in exception generation and handling in proportion to code volume, and some statistics on the complexity of such code. Not that I'm heavily into path analysis, but it seems clear that this kind of exception handling blows the pathing possibilities wide open. A much better strategy is CodeWithoutExceptions.
I can't speak for every project everywhere but I can say this: We haven't had any. None. Our project is a fairly large multi-tiered client/server application that runs 24 by 7. We can't afford to ever crash - which is why we chose to use exceptions heavily in the first place. The pathing possibilities are limited to what's on the call stack -- you can only get to places you've been before, and those places are prepared for your arrival. -- PG
My exception handling code is pretty simple. In practice, I don't think I ever retry an operation a different way. The mid-level handlers attempt to roll back partially completed operations, or at least restore the system to a stable state, and the high level handler reports the error and moves onto the next transaction. Both kinds are pretty simple.
In C++ we need more mid-level handlers because we have to manually destroy any objects that we've created on the heap, but we also have InitializationIsResourceAcquisition. In Java, we have finally for the same job; Smalltalk has something similar. We're doing things like closing and/or unlocking files, reshowing the mouse cursor or selection highlight if we hid it, generally cleaning up.
I gather my top-level handler usage corresponds to C3 usage, as described on AvoidExceptionsWheneverPossible. C3 seems not to use mid-level handlers. Maybe C3 is the sort of app that doesn't need them. -- DaveHarris