Change the name of ArrayBoundsException in druntime

Bill Baxter wbaxter at gmail.com
Thu Oct 23 12:39:36 PDT 2008


On Fri, Oct 24, 2008 at 4:08 AM, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> Andrei Alexandrescu wrote:
>>
>> Sean Kelly wrote:
>>>
>>> Andrei Alexandrescu wrote:
>>>>
>>>> Robert Fraser wrote:
>>>>>
>>>>> Option B:
>>>>> ---------
>>>>> try
>>>>> {
>>>>>    new Socket(30587);
>>>>> }
>>>>> catch(Exception e)
>>>>> {
>>>>>    if(e.type == ExceptionType.Socket)
>>>>>        printf("Could not open socket\n");
>>>>>    else
>>>>>        throw e;
>>>>> }
>>>>
>>>> I think you'd be hard-pressed to justify the "if" inside the second
>>>> example. You couldn't create a Socket, period. It doesn't matter where
>>>> exactly the exception was generated from.
>>>>
>>>> That's one thing about large exception hierarchies: everybody can come
>>>> with cute examples on how they could be useful. As soon as the rubber hits
>>>> the road, however, differentiating exceptions by type becomes useless.
>>>
>>> It may be different in a user application, but in services it's fairly
>>> common to have specialized code for handling different exception types.  And
>>> more importantly, it's common to want different exception types to propagate
>>> to different levels for handling.  Sure, one could use a generic exception
>>> handler at each level that rethrows if the detected type isn't one that
>>> handler cares about but why do this when filtering on type is a language
>>> feature?
>>>
>>> For example, let's say I have a network service that's backed by a SQL
>>> database.  My main program loop may look something like this:
>>>
>>>    bool connected = false;
>>>    while( true )
>>>    {
>>>        try
>>>        {
>>>            while( true )
>>>            {
>>>                auto r = acceptRequest();
>>>                scope(failure) r.tellFailed();
>>>                if( !connected )
>>>                    connectToDB();
>>>                handleRequest( r );
>>>            }
>>>        }
>>>        catch( SqlException e )
>>>        {
>>>            connected = false;
>>>            log( e );
>>>        }
>>>        catch( Exception e )
>>>        {
>>>            log( e );
>>>        }
>>>    }
>>>
>>>    ...
>>>
>>>    void handleRequest( Request r )
>>>    {
>>>        scope(failure) r.tellFailed( "General error" );
>>>
>>>        try
>>>        {
>>>            // process r
>>>        }
>>>        catch( AuthException e )
>>>        {
>>>            r.tellFailed( "Authentication failure" );
>>>        }
>>>        catch( ValidationException e )
>>>        {
>>>            r.tellFailed( "Invalid request format" );
>>>        }
>>>    }
>>>
>>> Being able to trap specific types of exceptions makes this code cleaner
>>> and more succinct than it would be otherwise.  If this weren't possible I'd
>>> have to trap, check, and rethrow certain exceptions at different levels to
>>> ensure that the proper handler saw them.
>>
>> Thanks for fueling my argument. There's duplication in code examples, as
>> in many other examples I've seen in favor of by-type handling.
>>
>> First example:
>>
>>        catch( Exception e )
>>        {
>>            if (e.origin = "sql") connected = false;
>>            log( e );
>>        }
>>
>> Less code and no duplication. Second example is even starker:
>>
>>        catch( AuthException e )
>>        {
>>            r.tellFailed( e.toString );
>>        }
>>
>> Clearly the need is to factor in the message to print in the exception, at
>> least in this case and many like it.
>>
>>
>> Andrei
>
> By the way, this each-exception-has-its-type crap is my #2 pet peeve after
> "Follow carefully my pocket watch... OO is good for everything... OO is good
> for everything... to use, inherit... to use, inherit..."

Interesting point.  The whole catch(A){} catch(B){} catch(C){} thing
is basically if-then-else on very similar types, which is exactly what
the OO crowd says you should try to avoid in any other situation.  You
should be using polymorphism!

But ok, types are good for one thing, and that's ensuring global
uniqueness.  That seems to be the real point of the billion exception
types, to give them unique identifiers that the compiler can check.
You can give your exceptions a typecode or a string identifier, like
your origin=="sql", but then the compiler won't tell you if your type
is unique.  And it won't tell you there's a problem if you mistakenly
type origin=="SQL" instead of "sql".

I think it boils down to a kind of static typing vs dynamic typing argument.

--bb



More information about the Digitalmars-d mailing list