The Right Approach to Exceptions

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Feb 20 18:32:08 PST 2012


On 2/20/12 7:08 PM, H. S. Teoh wrote:
> On Mon, Feb 20, 2012 at 06:38:08PM -0600, Andrei Alexandrescu wrote:
> [...]
>>> We shouldn't be using Variant[string] for this, because there's
>>> another problem associated with it: suppose MyException sometimes
>>> gets "extra_info1" and "extra_info2" tacked onto it, on its way up
>>> the call stack, and sometimes not. Now what should the catcher do?
>>
>> Use a central loop to render the information.
>
> Then it's useless for i18n, unless you can magically translate a
> sequence of unknown values into a different language in a consistent
> way.
>
> It sounds like all this is good for is to print a list of "name=value"
> pairs. Which is useful, I'll admit, for development/debugging purposes.
> I don't see how such a thing is useful in i18n.

As I said, string templates in conjunction with name/value bindings is 
all that's needed for i18n.

> [...]
>>> This is what I mean by not being able to depend on whether some data
>>> is there. Ultimately, to do anything useful with the info in the
>>> object, you need to know what's there.
>>
>> No. You do realize you are positioning yourself straight against every
>> OO principle there is? The entire OO world is predicated on the
>> assumption you _can_ do useful stuff with an object WITHOUT knowing
>> what's there.
>
> And the way OO does this is by having the *derived classes* do useful
> stuff behind a polymorphic interface.

Exactly, and with this you just destroyed your own design. For it does 
not build any polymorphic interface, no abstraction. It forever forces 
code to toil in the concrete (_fileName, _ipAddress, _userName) and 
fails to elevate any common interface that would foster reusable code.

> What the Variant[string] does is,
> as you have said previously, to replace the need for many derived
> classes save a few, thereby throwing away the polymorphism and
> presenting what amounts to an array of void* to the catch block.

On the contrary. This builds abstraction:

class Exception
{
     bool transient();
     Variant[string] info();
     ...
}

because it allows client code to treat different types, even types that 
haven't even been defined yet, uniformly.

This does not build anything:

class Exception {}
class UserNameException : Exception { string _userName; }
class NetException : Exception { string _ipAddress; }
...

> For you to now accuse me of going against OO principles is a really
> strange argument, I must say. I was in fact *advocating* the use of OO
> by putting the useful information in the derived classes, where they
> belong.

I'm not accusing of anything, merely noting that your design does not 
stand the scrutiny of your own principles (which are correct). Both 
can't be sustained simultaneously. Try a fresh run of your principles 
over your design. It'll get totaled.

>> I think you are misunderstanding the mechanisms involved. There is no
>> combinatorial code, just simple iteration and such. Dealing with
>> distinct exceptions with distinct code IS combinatorial, repetitive,
>> and non-scalable.
>
> Then pray tell how "simple iteration" will achieve the translation of
> the data in Variant[string] into a localized string, when there is no
> guarantee any field will be in the hash at all. Format strings obviously
> won't work, since you can't have a format string unless you already know
> what arguments are present.

There's no guarantee. That'll be a runtime check in the formatting engine.


Andrei



More information about the Digitalmars-d mailing list