Possible "throws" syntax

Dmitry Olshansky dmitry.olsh at gmail.com
Wed Aug 15 12:29:43 PDT 2012


On 12-Aug-12 07:28, Marco Leise wrote:
> Am Sun, 12 Aug 2012 05:02:25 +0200
> schrieb Marco Leise <Marco.Leise at gmx.de>:
>
>> ---D->>
>>
>> /**
>>   * Receives a response from the server.
>>   *
>>   * Some explanation of what
>>   * the function does in detail.
>>   *
>>   * Params:
>>   *    response = receives the whole response
>>   * Throws:
>>   *    UnexpectedResponseException if the server sent us garbage
>>   *
>>   *    UnauthenticatedException we need retry after we have logged in
>>   *
>>   *    SecurityException we have to switch to a secure connection for this
>>   *
>>   *    DisconnectException the connection was unexpectedly terminated
>>   * Returns: the associated response code
>>   */
>> int foo(out string response)
>> {...}
>>
>> <<-D---
>
> could become:
>
> ---D->>
>
> /**
>   * Receives a response from the server.
>   *
>   * Some explanation of what
>   * the function does in detail.
>   *
>   * Params:
>   *    response = receives the whole response
>   * Returns: the associated response code
>   */
> int foo(out string response) throws
>      UnexpectedResponseException, /// if the server sent us garbage
>      UnauthenticatedException, /// we need retry after we have logged in
>      SecurityException, /// we have to switch to a secure connection for this
>      DisconnectException /// the connection was unexpectedly terminated
> {...}
>
> <<-D--
>

When I see code like this I have one single thought - error codes!

Indeed that's what is used in this example, with Exceptions only being 
convenient (and separate) transport for error codes. So the net progress 
is creating 1:1 type for each error condition (start counting the lines 
of code) and then...

If I got it right somewhere later foo is supposed to be used like this:
try{
...some_code
foo();
...other code
}
catch(UnexpectedResponseException)
{
	print error and disconnect this server or retry?
}
catch(UnauthenticatedException)
{
	print error 2
}
catch(SecurityException)
{
	sslFoo(resp); // this one is just awesome ;)
}
catch(DisconnectException )
{
	print error 3 & (ask to) reconnect?
}

Or used a catch all and do type switch Java-style to see if Exception is 
one of interesting to you types.  Needless to say awful again.

First SecurityError is gross fiction as you either know to authenticate 
(need credentials in the interface) or do auto detection (like try 
HTTPS, then fallback to HTTP).

Moreover encoding _cause_ of error in type is useless, end user needs a 
hint on the proper way to handle error. It's like pointing out a guy who 
made the mistake and how stupid it is instead of proposing the ways to 
fix the situation.

what I'd expect the code to be is (been discussed before):
class NetworkException
{
	@property bool transient; // packet lost or whatever, can re-try with 
the same parameters
	@property bool lost; // need reconnect to restore, server down or 
disconnected or unexpected input
	@property string msg();
}

This reduces all the handling to:
catch(NetworkException ne)
{
	if(ne.lost)
		//ya kill me, but you got the idea ;)
		goto ReconnectAndRetry;
	if(ne.transient){
		warning("..."); //log failure
		goto RetryAndCheckTryCount;
	}
	error(ne.msg);
}

Including but not limited to the time when foo's author adds more types 
to his "throws list". Unlike checked exceptions it won't break build 
just for the fuck of it *and* it will still work correctly.

In fact if we manage to come up with proper reasonable standard 
exceptions like Network/IO/etc. that everybody derives from error 
handling would become damn easy with *any* library.

-- 
Olshansky Dmitry


More information about the Digitalmars-d mailing list