comp.lang.ada
 help / color / mirror / Atom feed
From: bobduff@world.std.com (Robert A Duff)
Subject: Re: Building blocks (Was: Design By Contract)
Date: 1997/09/19
Date: 1997-09-19T00:00:00+00:00	[thread overview]
Message-ID: <EGrz21.GoG@world.std.com> (raw)
In-Reply-To: 3421E190.49CC@chimu.com


In article <3421E190.49CC@chimu.com>,
Mark L. Fussell <mark.fussell@chimu.com> wrote:
>A close equivalent in Eiffel is the following example.  This is actually
>a variation from the discussion in Section 12.5 of OOSC-2.

I read about this in OOSC-1, and I didn't buy it.  It seems to me that
retry has nothing at all to do with whether an operation can "pretend it
succeeded".  The thing that prevents that pretense is having a spec for
what the routine in supposed to do.  In Eiffel, this is represented by
the postcondition and invariant (which may include executable boolean
expressions, plus comments).  In Ada, it's represented mainly by
comments, but perhaps also by constraints, and maybe even
raise_statements in the code.

If Eiffel had Ada-style exception handlers, I don't see how this would
do any damage.  The exception handler would still be required to obey
the postcondition.  Either way, there's always the danger that the
programmer forgot to handle some case correctly.  But that's true even
without exceptions:

    if <some condition> then
        <correct code>
    else
        <wrong code>
    end if;

If <some condition> is usually True, and your test cases fail to
exercise the else branch, then you have a bug that a customer might trip
over.  Likewise, if the main body of a procedure is right, but the
exception handler is wrong, you have a bug.  Either way, the post
condition will catch it at run time.  I don't see how "retry" enhances
the ability of postconditions to find bugs.

Furthermore, retry seems to have all the bad properties of goto.  And
the worst sort of goto -- the kind that jumps backwards in the code,
forming a loop, without actually writing "loop" at the front.

>is
>    -- The Eiffel version of the above
>local
>    attempts : INTEGER  -- FYI: initializes attempts to 0
>do
>    if attempts = 0 then
>        -- do main stuff
>    else
>        -- do nothing
>    end
>rescue
>    attempts := attempts + 1
>    retry
>end

The above code seems obfucatory to me.  If you really want to retry, I
would much rather have an explicit loop:

    loop
        begin
            ... -- do main stuff
            exit;
        exception
            when Some_Error =>
                null;
        end;
    end loop;

Often, you want to do something *different* when the exception occurs
(still, of course, obeying the postcondition).  That's what the above
Eiffel code does, but in a confusing way.  There's no warning at the top
of the code that we might be entering it from the exception handler.  In
that regard, retry is *worse* than a goto -- at least with a backward
goto there's a label there warning you that some other thing might jump
here.  It seems much clearer to say "do THIS in the normal case, but if
you get an exception, do THAT instead".  And of course, THIS and THAT
must obey postconditions.

>"This mechanism strictly adheres to the Disciplined Exception Handling
>principle: either a routine succeeds, that is to say its body executes
>to the end and satisfies the postcondition, or it fails.

This is a bogus definition of "succeed".  The only sensible definition
is "obeys the postcondition".  And that could be achieved just as well
without retry.

>...  When
>interrupted by an exception, you may either report failure or try your
>normal body again; in no way can you exit through the rescue clause and
>pretend to your caller that you succeeded."

But if exception handling were more Ada-like, it would *still* be the
case that "in no way can you ... pretend ...".  You would still be
required to obey the postcondition.

>Most of the difference between the Eiffel and Ada approach is really
>"what it feels like" in the exception handler.  Eiffel's exception
>handler give you a chance to retry the main body which can than do what
>ever it wants (within its contract), but in so doing returns you to
>thinking about how to satisfy the routine call.  The Ada (and many other
>languages) approach allows you to try to both recover from the exception
>and satisfy the routine call in one place.  This may lead you to forget
>to do one or both of these responsibilities.

Just the opposite, IMHO.  With retry, you might forget, when writing the
main body, that you might get there via retry.  With the Ada approach,
you know which situation you're in, and you can write code that
satisfies the postcondition on that basis -- no need for bogus state
variables like the above "attempts", which seem to obfuscate.

>Certainly Eiffel calls out the 'do nothing' behavior more strongly by
>having it be in the main body:
>    if attempts = 0 then
>        -- do main stuff
>    else
>        -- do nothing
>    end
>This looks much stranger and more suspicious than the equivalent:
>   begin
>      ... some code
>   exception
>   when others =>
>       null;

I disagree.  Unless the "when others => null;" is inside a loop (which I
prefer to indicate by saying "loop", rather than the goto-ish backwards
jump of "retry"), it looks mightily suspicious to me.  On the other
hand, in the Eiffel case, if the main body simply said "do main stuff"
(without the if statement), then it seems easier to forget that we might
get here with attempts > 0.

>In the quotes above, the following remark implies more than it means:
>"in no way can you exit through the rescue clause and pretend to your
>caller that you succeeded".  Since the caller only sees the routine
>return, it would not know whether you 'pretended to succeed' via the
>rescue/exception clause or through the main body of the routine. 
>Pretending to succeed is possible one way or the other.

Exactly.

>...In either case,
>your exiting normally implies you fulfilled your contract
>(post-condition) and if Ada had post-conditions then:
>   when others => null;
>should have to satisfy them or throw a new exception.  To be fair, the
>sentence before BM defined 'succeed' more restrictively as the execution
>of the body, but that definition is Eiffel specific and the word
>'success' has a more general connotation.

Agreed.

In summary, I think it's postconditions that help make routines work
properly in all cases (including exceptional cases).  I don't see any
way in which "retry" helps ensure that postconditions are obeyed, and I
think retry simply makes the code more confusing.

- Bob




  parent reply	other threads:[~1997-09-19  0:00 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1997-09-09  0:00 Building blocks (Was: Design By Contract) Marc Wachowitz
1997-09-15  0:00 ` Joachim Durchholz
1997-09-17  0:00 ` Paul Johnson
1997-09-18  0:00   ` Stephen Leake
1997-09-18  0:00     ` Mark L. Fussell
1997-09-19  0:00       ` Jon S Anthony
1997-09-23  0:00         ` Mark L. Fussell
1997-09-19  0:00       ` Robert A Duff [this message]
1997-09-20  0:00         ` Joachim Durchholz
1997-09-22  0:00           ` Matthew Heaney
1997-09-23  0:00             ` Joachim Durchholz
1997-09-23  0:00             ` Veli-Pekka Nousiainen
1997-10-03  0:00               ` Robert I. Eachus
1997-10-04  0:00                 ` Paul Johnson
1997-10-14  0:00                   ` Robert I. Eachus
1997-09-23  0:00           ` Jon S Anthony
1997-09-24  0:00           ` Richard A. O'Keefe
1997-09-24  0:00           ` Alan E & Carmel J Brain
1997-09-25  0:00             ` Anonymous
1997-09-30  0:00               ` Alan E & Carmel J Brain
1997-09-30  0:00                 ` Matthew Heaney
1997-09-30  0:00                   ` W. Wesley Groleau x4923
1997-09-30  0:00                     ` Matthew Heaney
1997-10-01  0:00                     ` Alan E & Carmel J Brain
1997-09-30  0:00                   ` Neil Wilson
1997-09-30  0:00                     ` Stephen Leake
1997-10-01  0:00                 ` Anonymous
1997-10-01  0:00                   ` Joachim Durchholz
1997-10-01  0:00                   ` Paul M Gover
1997-10-04  0:00                     ` Paul Johnson
1997-10-04  0:00                       ` Matthew Heaney
1997-10-15  0:00                         ` Paul Johnson
1997-10-15  0:00                           ` Matthew Heaney
1997-10-16  0:00                             ` Joachim Durchholz
1997-10-17  0:00                               ` Robert I. Eachus
1997-10-16  0:00                           ` Joachim Durchholz
1997-10-22  0:00                           ` Reimer Behrends
1997-10-02  0:00                   ` Robert A Duff
1997-10-02  0:00                     ` Tucker Taft
1997-10-02  0:00                       ` Matthew Heaney
1997-10-03  0:00                     ` Stephen Leake
1997-10-04  0:00                     ` Matthew Heaney
1997-10-07  0:00                       ` Robert A Duff
     [not found]       ` <11861963wnr@eiffel.demon.co.uk>
1997-09-19  0:00         ` Mark L. Fussell
1997-09-18  0:00     ` W. Wesley Groleau x4923
1997-09-21  0:00       ` Matthew Heaney
1997-09-18  0:00   ` Jon S Anthony
1997-09-18  0:00   ` Robert Dewar
  -- strict thread matches above, loose matches on Subject: below --
1997-09-11  0:00 Robert Dewar
1997-09-09  0:00 Marc Wachowitz
1997-09-02  0:00 Design By Contract Jon S Anthony
     [not found] ` <JSA.97Sep3201329@alexandria.organon.com>
1997-09-04  0:00   ` Paul Johnson
     [not found]     ` <5un58u$9ih$1@gonzo.sun3.iaf.nl>
1997-09-06  0:00       ` Building blocks (Was: Design By Contract) Joachim Durchholz
1997-09-08  0:00       ` Paul Johnson
1997-09-08  0:00         ` Brian Rogoff
1997-09-09  0:00           ` Veli-Pekka Nousiainen
1997-09-09  0:00             ` Jon S Anthony
1997-09-09  0:00           ` Veli-Pekka Nousiainen
1997-09-09  0:00           ` Matthew Heaney
1997-09-09  0:00             ` W. Wesley Groleau x4923
1997-09-10  0:00               ` Robert A Duff
1997-09-12  0:00                 ` Jon S Anthony
1997-09-09  0:00             ` Brian Rogoff
1997-09-10  0:00             ` Robert Dewar
1997-09-12  0:00               ` Jon S Anthony
1997-09-12  0:00                 ` Robert Dewar
1997-09-16  0:00                   ` Brian Rogoff
1997-09-12  0:00               ` Paul Johnson
1997-09-14  0:00                 ` Robert Dewar
1997-09-14  0:00                 ` Robert Dewar
1997-09-15  0:00                   ` John G. Volan
1997-09-14  0:00                 ` Robert Dewar
1997-09-10  0:00             ` Paul Johnson
1997-09-10  0:00               ` Darren New
1997-09-10  0:00               ` Matthew Heaney
1997-09-09  0:00           ` W. Wesley Groleau x4923
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox