The Right Approach to Exceptions

deadalnix deadalnix at gmail.com
Mon Feb 20 11:53:24 PST 2012


Le 20/02/2012 20:34, H. S. Teoh a écrit :
> On Mon, Feb 20, 2012 at 08:11:28PM +0100, deadalnix wrote:
> [...]
>> Considering the handler, This would be great to see it as scoped.
>> This imply using a scope delegate, and probably something as RAII to
>> create it and delete it when we go out of scope.
>
> Yeah, that definitely should be done, otherwise a handler installed by a
> function that's no longer in scope will still kick in when the same
> exception is triggered by unrelated code. That would be very bad.
>
>
>> I'm more doubtfull about what can be done on the throw side. This need
>> to be refined, and to be honnest, the idea is too new in my head to
>> come up with something significant. The concept needs some
>> decantation.
>>
>> I wonder however, how to do something clean. The delegate will need
>> some knowledge of the thrower onternal to do something really usefull,
>> but then, we make the codebase more fragile (because the caler will
>> depend on implementation of the calee, something that we want to
>> avoid).
>
> I've tried to do this by encapsulating the recovery options in the
> Condition object. So the delegate knows, here are the options I have of
> recovering, but it doesn't need to know how the low-level function
> implements those recovery strategies.
>
> For example, the FileNotFoundCond object has a restart() method, and an
> inherited abort() method. So these are the options available to the
> delegate. These methods just return an opaque object to the recovery
> system, which passes it to the low-level function. Then the low-level
> function tries to recover according to which object it receives. So the
> delegate doesn't actually know how each option is implemented, it just
> knows these are available options to recover.
>
> Also, the restart() method takes a new filename as parameter, so the
> delegate even knows what data is needed to provide to a particular
> recovery option in order to help the low-level function recover.
>
> Of course, the current implementation is very skeletal, and there are
> still many open issues:
>
> - How does the delegate know *which* low-level function throws a
>    particular Condition? For example, what if main() calls some function
>    that calls openDataFile() many times? What if openDataFile() is called
>    at different points in the function call hierarchy? How does the
>    delegate know which recovery choice is appropriate for every
>    FileNotFoundCond() that it catches?
>
> - Every Condition the program might encounter requires a lot of code:
>    you need to define a Condition subclass, populate it with recovery
>    strategies, and then have the throwing code check and handle each
>    option. Is there a way to reduce the amount of code you need to write
>    for every Condition?
>
> - Also, Conditions seem to specific to a particular situation. It's not
>    too bad for generic problems like FileNotFoundCond; we know what it
>    means when the OS says "file not found", and we generally know what
>    can be done to fix that. But what about ParseErrorCond? The delegate
>    would need to know what kind of parse error, or even which parser
>    issued that error, otherwise how would it know how to correct the
>    parse error?
>
>    But this means that every different parser in the program will require
>    its own ParseError subclass, along with the associated recovery
>    options. Seems like a lot of work for only occasional benefit.
>
> - Are there general recovery options that apply generally across the
>    majority of Conditions? If so, we can alleviate delegates from having
>    to know the intimate details of a particular operation, which
>    introduces too much coupling between high-level and low-level code.
>
> A more minor issue is that the current implementation is not very well
> written. :) I'll have to think about this more, to know how to better
> implement it. But I wanted to get the semantics of it out first, so that
> at least we can start discussing the conceptual aspects of the idea.
>
>
> T
>

So if I sum up things a bit (and refactor the design a bit according to 
what is best as I understand it) :

1/ lib don't throw exception, they raise a Condition.

2/ If an handler exists for that condition, then the handler is called, 
and the condition is passed as parameter. The condition provide an 
interface so the handler can specify how to handle that condition.

3/ The condition provide a way to throw in its interface. This part of 
the interface of Condition.

4/ If no handler is found, the throw method of the Condition is called.

5/ The handler is provided in a scoped manner.

6/ This mecanism is provided as a lib.

7/ The mecanism is provided as a richer way to use Exceptions.

Is it a solid base to start on ? I seems we need to start working on 
std.condition ;) BTW, do we need language support to implement that ? I 
don't think so, but I'm quite new to the issue.


More information about the Digitalmars-d mailing list