Change the name of ArrayBoundsException in druntime
Steven Schveighoffer
schveiguy at yahoo.com
Thu Oct 23 12:32:15 PDT 2008
"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.
For the second example, you are assuming that ValidationException is a
subclass of AuthException.
I think in this case, ValidationException and AuthException might share a
common parent (SqlException) which you do NOT want to catch. It is
advantageous in this case to have both a hierarchy through inheritance and a
hierarchy through parameters.
Here's another idea, to avoid rethrows, what about some pre-handler code
that tests if an exception is what you want? Perhaps the same mechanism
that is used by template constraints:
catch(SqlException e) if (e.reason is Auth || e.reason is Validation)
{
r.tellFailed(e.toString());
}
That gives you the same mechanism used with typing and without the rethrows,
without creating N subclasses of SqlException, and without multiple
repetitive blocks that do the same thing. It looks more readable to me too.
Not sure how exception code works, so I don't know how plausible this is.
-Steve
More information about the Digitalmars-d
mailing list