comp.lang.ada
 help / color / mirror / Atom feed
From: gauthier@unilim.fr (Michel Gauthier)
Subject: Re: Exceptions: Are they GOTOs?
Date: 1996/07/17
Date: 1996-07-17T00:00:00+00:00	[thread overview]
Message-ID: <gauthier-1707961114030001@164.81.60.62> (raw)
In-Reply-To: brad.837052481@ss1


This is a reply to a private message following a c.l.a message in which
<brad.837052481@ss1>, brad@cs.uwa.oz.au (Bradley Edelman) wrote:

>>>  What do people think about exception handling?  I believe it to be a major
>>>  strength of Ada but there is a school of thought that exceptions are just
>>>  GOTO statements and should be avoided accordingly.

The following ideas are milestones, rather than a well-built paper.

"resuming requirement" : some projects require appropriate reactions
     after any situation, including bad ones. Other projects may 
     locally encounter the same requirement (basic case : syntax
     errors in typing input data).

"reuse principle 1" : a reusable component is not allowed to make
     assumptions about its uses.
       Consequently : it is not allowed to assume anything about
     'normality' or 'abnormality' of calls.
       The only things a reusable component may do are rendering 
     the service it has to, or reporting that it cannot.

Consequence : aborts and goto's are not suitable to report, since they
     assume too much things about the use.

Known vocabulary : programming is 'offensive' when the caller has to
     check some precondition that permits the callee to work correctly,
     and 'defensive' when the callee checks the preconditions and
     reports accordingly if it cannot work correctly.
       'Offensiveness' is a property of each caller. 'Defensiveness' is 
     a property of the callee. Some calls can be both.

Consequence : the 'defensive' behaviour is the only possible
     one for a reusable component, since the contrary assumes that all
     callers are 'offensive'.
       Of course, there is no harm in non-defensive behaviour when
     the programmer has a full control on a well-defined set of calls.

Known implementations of reports : exceptions and status codes.
       Balance : status codes imply verbosity caused by the requirement
     of explicit handling everywhere in the program, exceptions imply 
     implicit information, which has to be made explicit by re-building
     or by appropriate documentation.
       IMHO : exceptions are simpler in most cases, not necessarily
     in all cases (remind that we speak of reusable components only).
       To convince yourself, consider what you would have to write
     if Text_IO was specified with status codes, and the quality
     of the resulting programs.

Complexity of goto's : very long ago, I wrote a paper about measuring
     (in McCabe's style) the effect of transforming non-'structured'
     algorithms into 'structured' ones. More generally, it may be interesting
     to measure the effect of program-transforming algorithms. About
     goto's, the result was :
      - additional complexity of forward-goto's : the number of control
     structures that the jump exits from
      - additional complexity of one backward goto : the above, plus
     an enclosing loop
      - additional complexity of mixed forward and backward goto's :
     not computable, since the transformation involves copying pieces
     of source text.
       According to this idea, exception raise and handling is
     exactly like forward-goto's (with any language, except Eiffel's 
     'retry'). Be aware that this complexity _is_ in the program, whether
     you handle exceptionsor not.
       Note : this seems to illustrate that exceptions are less complex
     than status codes, which work as transformation of exceptions into
     'structured' code (status introduces flows that converge, goes
     together during a time, and then diverge again).

Ambiguity of 'contract' : the idea that a specification is a sort of
     contract (in the commercial sense) between a client and a
     provider is a very old idea. I remember that I, and other colleagues,
     was already using it in my courses (using Pascal and status) in 1975.
       However, it is ambiguous whether the word 'contract' denotes
     the expected service in a limited sense, or the behaviour in all
     cases. The renowned (but IMHO somewhat weak) Bertrand Meyer's book 
     is ambiguous too. There are two concepts, we need two words.

_Remind that_ : almost every statement and many declarations
     can raise at least one exception. Languages that do not provide 
     such control are not dependable.

Suggestion : call 'specification' the definition of the basic service,
     and 'contact' the full definition with report cases. Also call
     'success' the case of obtaining the specification, and 'failure'
     the contrary. Do not call of 'errors' here.
       Remember that preconditions can sometimes not be coded as
     predicate functions : opening a remote file (can be, but implies
     a non-atomic statement), inversing a matrix (same complexity as
     the basic computation), getting a number from the user
     (intrinsically impossible),... The issue of numeric compotations
     and overflowing is intrinsically impossible, too.
       Of course, the so-called 'contract model' of genericity is 
     compatible with this choice of words.

Very important : "success vs. failure" / "correct vs. erroneous" /
     "exception vs. status" are entirely independent distinctions :
     you can find examples of the eight possible cases (although one
     of the eight is somewhat exotic, but sometimes required).
       Particularly : yileding a result when a report is required by
     the specification is an error !!!

"raising is simple" : in most cases, you are inside one or more branches
     of conditional statements (or cases, or loops), which builds a rich
     knowledge of the program state, and permits you decide that it is 
     a situation where the contract requires a raise.
       The same holds with status codes, and goto'ing is similar.

"handling can be complex" : a handler is a location where many flows
     converge. There are many risks of errors here :
     - if your mind omits one corresponding raise,
     - if you have not enough information about the program state at the
     locations of the raises.
       Useful rules can be deduced from this :
     - compute the exact set of raises,
     - prove appropriately if some raises cannot be reached,
     - attach postconditions to exception raise locations as well as to
     any other subprogram exit.
       There is, of course, always the risk of bad proofs, but nothing
     will never decrease this risk to zero.

Caution for status codes : the equivalent (with exceptions) of
                         if REPORT /= SOME_REPORT then
                              SUCC ;
                         else
                              FAIL ;
                         end if ;
     will include something like :
                         when SOME_REPORT =>
                              FAIL ;
                         when others =>  -- ???
                              SUCC ;      -- ???
     Dangerous, isn't it ?

Yet more rules : in fact, a good use of reports requires the above 
     rules for _all_ reports, whether reporting is by exceptions or
     by status codes. Hence, for a piece of program (say, subprogram) :
     - consider _all_ raises, including implicit ones, or assignments of 
     the status,
     - remove all non-reachable raises of this set, after proving it,
     - consider all reports allowed in the contact,
     - check if internal effective raises and final reports fit,
     - every non-fit detects a programming error.

Sorry, but : without such style rules, how can you depend on a program ?

----------          ----------          ----------          ---------- 
Michel Gauthier / Laboratoire d'informatique
123 avenue Albert Thomas / F-87060 Limoges
telephone +33 () 55457335 [or ~ 7232]
fax +33 ()  55457315  [or ~7201]
----------          ----------          ----------          ----------
La grande equation de la fin du siecle : windows-X = Mac-Y
The main end-of-century equation : windows-X = Mac-Y
----------          ----------          ----------          ----------
Si l'an 2000 est pour vous un mysticisme stupide, utilisez la base 9
If you feel year 2000 a stupid mystic craze, use numeration base 9
----------          ----------          ----------          ----------




      parent reply	other threads:[~1996-07-17  0:00 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1996-07-11  0:00 Exceptions: Are they GOTOs? Bradley Edelman
1996-07-11  0:00 ` Michel Gauthier
1996-07-11  0:00 ` Robert A Duff
1996-07-12  0:00 ` steved
1996-07-13  0:00   ` Michael Feldman
1996-07-16  0:00   ` Robert I. Eachus
1996-07-19  0:00     ` Michel Gauthier
1996-07-18  0:00   ` Robert Dunn
1996-07-18  0:00     ` Robert Dewar
1996-07-19  0:00       ` Larry J. Elmore
1996-07-20  0:00         ` Andy Askey
1996-07-12  0:00 ` Spasmo
1996-07-12  0:00   ` David Morton
1996-07-14  0:00   ` Robert Dewar
1996-07-17  0:00     ` Spasmo
1996-07-18  0:00       ` Walter B. Hollman Sr.
1996-07-20  0:00         ` Robert Dewar
1996-07-13  0:00 ` Robert Dewar
1996-07-14  0:00 ` Andy Askey
1996-07-14  0:00   ` Laurent Guerby
1996-07-15  0:00     ` Andy Askey
1996-07-15  0:00       ` Robert Dewar
1996-07-14  0:00   ` Robert Dewar
1996-07-15  0:00 ` OS2 User
1996-07-16  0:00 ` Michel Gauthier
1996-07-17  0:00 ` Michel Gauthier [this message]
replies disabled

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