Exception/Error division in D

Steven Schveighoffer schveiguy at yahoo.com
Wed May 30 09:01:40 PDT 2012


On Wed, 30 May 2012 11:47:34 -0400, Jens Mueller <jens.k.mueller at gmx.de>  
wrote:

> Steven Schveighoffer wrote:

>> case 2:
>>
>> int main(string[] args)
>> {
>>    writeln(invert(to!double(args[1])); // clearly a catchable error
>> }
>
> This should be
> int main(string[] args)
> {
>    auto arg = to!double(args[1]);
>    enforce(arg != 0);
>    writeln(invert(arg));
> }
>
> The enforce is needed because args[1] is user input. If the programmer
> controlled the value of arg and believes arg != 0 always holds then no
> enforce would be needed.
>
> Doesn't this make sense?

Yes and no.  Yes, the ultimate result of what you wrote is the desired  
functionality.  But no, I don't think you have properly solved the problem.

Consider that user data, or environment data, can come from anywhere, and  
at any time.  Consider also that you have decoupled the function parameter  
validation from the function itself!  Ideally, invert should be the one  
deciding whether the original data is valid or not.  In order to write  
correct code, I must "know" what the contents of invert are as the writer  
of main.  I'd rather do something like:

int main(string[] args)
{
    auto argToInvert = to!double(args[1]);
    validateInvertArgs(argToInvert); // uses enforce
    invert(argToInvert);
}

Note that even *this* isn't ideal, because now the author of invert has to  
write and maintain a separate function for validating its arguments, even  
though invert is *already* validating its arguments.

It's almost as if, I want to re-use the same code inside invert that  
validates its arguments, but use a different mechanism to flag an error,  
depending on the source of the arguments.

It can get even more tricky, if say a function has two parameters, and one  
is hard-coded and the other comes from user input.

> PS
> For the record, I think (like most) that Errors should like Exceptions
> work with scope, etc. The only arguments against is the theoretical
> possibility of causing more damage while cleaning up. I say theoretical
> because there was no practical example given. It seems that it may cause
> more damage but it does not need to. Of course, if damage happens it's
> the programmers fault but it's also the programmer's fault if he does
> not try to do a graceful shutdown, i.e. closing sockets, sending a crash
> report, or similar.

Indeed, it's all up to the programmer to handle the situation properly.   
If an assert occurs, the program may be already in an invalid state, and  
*trying to save* files or close/flush databases may corrupt the data.

My point is, it's impossible for the runtime to know that your code is  
properly handling the error or not, and that running all the finally/scope  
blocks will not be worse than not doing it.

-Steve


More information about the Digitalmars-d mailing list