|
Boost : |
From: Pavel Vozenilek (pavel_vozenilek_at_[hidden])
Date: 2006-08-08 20:16:28
"Emil Dotchevski" wrote:
>>>>> http://article.gmane.org/gmane.comp.lib.boost.devel/146322
>>>
>> } catch(boost::exception& e) {
>> e.dump_everything(); // what happened?
>> }
>
> Yes, but what does dump_everything() look like?
>
> The reason why this is important is that I can't imagine dump_everything
> being able to format a proper user message. The best it can do is dump
> stuff
> in a debug log, for example. Which begs the question, how do you format a
> proper message for the user? I think that the only way to do this is for
> the
> code that formats the message to *know*, for each class of exceptions,
> what
> info could be available. You can't parameterize this with a "visitor"
> interface. Or can you? That was my intention when I asked you for an
> example: what's in dump_everything?
>
Would it be possible to use typeid(..).name()
together with lexical_cast<> on the values?
The formatting is almost irrelevant at this
point, raw data are.
The end user woudn't see it, only the author.
>> typeswitch:
>> if (dynamic_cast<This>(e)) .... else
>> if (dynamic_cast<That>(e)) ....
>
> What's wrong with
>
> catch( This & )
> {
> }
> catch( That & )
> {
> }
>
This looses the valuable simplicity
of catch (boost::exception&).
And what if you want to add the same
10 data items for every exception.
[ snip visitor-like approach vs individual catch statements ]
>
> My personal opinion is that a list of ordered catch statements is the
> simplest way to get what you need. And it is directly supported by C++.
>
Problems:
* Coupling. The code containing catch is likely
already complex and now it needs to include
all handled exceptions, even if they are from
lower layer.
With the other approach you may create
visitor in lower layer and provide it as part
of its interface.
The visitor would not need to know about higher
layer but would work correctly, the upper layer
would not depend on lower layer details
(definitions of the exceptions).
* Isolation of error handling.
With sequence of catch you put error handling
code into vicinity of normal-path code.
The code is spread across many functions.
With visitor you can put error handling code
into one central location and can completely
isolate it from normal-path code.
Only visitor definition needs to be shared.
* Not dynamic. Behaviour of a hardcoded catch sequence
cannot be changed easily. A visitor fares better.
Not really earth shaking feature but may come handy.
Example: the visitor itself may be payload
of the thrown exception. On each catch level
it will be invoked and when it decided
the error has been solved it will stop propagating
the exception up.
Say std::bad_alloc that "auto-stops"
when enough of memory has been released.
Better example: regression test suite.
You created and use debug visitor that stops
propagating of exceptions up and you may safely
throw and test anything from lower layer w/o worry
what disaster will it cause somewhere up.
* It is shorter:
} catch (boost::exception& e) {
my_visitor v;
v.process(e);
}
vs.
} catch (exception1& e) {
handle(e);
} catch (exception2& e) {
handle(e);
} catch (exception3& e) {
handle(e);
} ....
* Safety: the correct ordering of the
checking is (should be) automated
with a visitor. Finding bug in
hand-written catch sequence
is very hard.
* If you add new exception or change
exception hierarchy you need to
update only the visitor class, not every
catch.
/Pavel
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk