comp.lang.ada
 help / color / mirror / Atom feed
* Pre-condition vs. Post-condition
@ 1991-03-15  3:57 Chris M. Little
  1991-03-15 19:07 ` Michael Feldman
  0 siblings, 1 reply; 31+ messages in thread
From: Chris M. Little @ 1991-03-15  3:57 UTC (permalink / raw)


Say we have a function CAPITAL which, given a country's name, returns its
capital city.  If the given country does not exist, an exception COUNTRY_ERROR
is raised.  Should the given country's presence be listed as a pre-condition
for this function, or should its absense (it doesn't exist) and the raising
of COUNTRY_ERROR be listed as a post-condition?

I brought this question up in class today and the outcome was a split decision.
I think exception raising and/or handling is as valid an outcome of a function
or procedure as any other outcome, so I'm tempted to cover the issue in the
post-condition comment.  My opponents believe that a function's pre-conditions
should be the conditions under which it would complete "normally", that is,
without any exceptions being raised.

I'd appreciate any insight on the issue.  E-mail please.  Thanks.

-- 
Chris Little, Graduate Asstistant	-     CML8@JAGUAR.UOFS.EDU	(VMS)
Department of Computing Sciences	-     CML8@SCRANTON.BITNET	(VMS)
University of Scranton, Pennsylvania.	-     CML8@ROBIN.CS.UOFS.EDU    (UNIX)

^ permalink raw reply	[flat|nested] 31+ messages in thread
* Pre-condition vs. Post-condition
@ 1991-03-18 15:47 "Norman H. Cohen"
  0 siblings, 0 replies; 31+ messages in thread
From: "Norman H. Cohen" @ 1991-03-18 15:47 UTC (permalink / raw)


For exceptions raised by predefined basic operations, it is generally
impossible to write a precondition guaranteeing that the exception WILL
be raised.*  In such cases it is clearly appropriate to incorporate in
the precondition sufficient conditions to guarantee that no predefined
exception** will be raised.

For programmer-defined exceptions raised under predictable circumstances,
it is reasonable to incorporate in formal specifications the conditions
under which a subprogram completes normally, the circumstances under
which such exceptions are raised, and the effect on the program state
in each case.  The approach I've adopted in developing proof rules for
Ada is to assume a separate precondition/postcondition pair for each such
case:

   function CAPITAL (COUNTRY: STRING) return STRING;

   -- Let Country_Map be the mapping { "USA" -> "Washington",
   -- "Mongolia" -> "Ulan Bator", ... }.

   -- Precondition for normal completion:
   --    COUNTRY in domain Country_Map
   -- Postcondition for normal completion:
   --    function_result = Country_Map(COUNTRY)
   --
   -- Precondition for completion with COUNTRY_ERROR raised:
   --    COUNTRY not in domain Country_Map
   -- Postcondition for completion with COUNTRY_ERROR raised:
   --    TRUE  [no change of state]

It is certainly possible to incorporate all this in a postcondition:

   -- Precondition: TRUE
   -- Postcondition:
   --      (    COUNTRY in domain Country_Map
   --       and exception_raised=none
   --       and function_result=Country_Map(COUNTRY))
   --   or (    COUNTRY not in domain Country_Map
   --       and exception_raised=COUNTRY_ERROR)

However, I find this presentation more obscure for the human reader.
The first approach more naturally decomposes the behavior of the function
into separate cases of interest.  For mechanical program analysis (e.g.
for the generation of verification conditions) the first approach is also
clearly preferable, because it allows proof rules to refer to the
exception status at the end of a statement.  For example, if Pre(S,P,E)
is the precondition for statement S to complete with postcondition P and
exception status E, then the proof rule for a sequence of two statements
is:

  (1) Pre(S1;S2, P, normal) = Pre(S1, Pre(S2, P, normal), normal)

  (2) If E is the raising of some exception,
         Pre(S1;S2, P, E) =
            Pre(S1, P, E) or Pre(S1, Pre(S2, P, E), normal)

(In the exception-raising case, case (2), the left operand of "or"
corresponds to the case where S1 raises the exception and the right
operand corresponds to the case where S1 completes normally and then
S2 raises the exception.)

----------

*-Among the reasons for this are the liberty provided by RM 4.5.7(7) to
  ignore real overflow, by RM 11.6(6) to use a wider type for computation
  of intermediate results, and by RM 11.6(7) to delete an operation whose
  "only possible effect is to propagate a predefined exception."  Also
  there are cases in which DIFFERENT exceptions may be raised for
  implementation-dependent reasons, such as the order in which
  subexpressions are evaluated or an implementation's adherence to
  nonbinding interpretation AI-00387, which recommends the raising of
  CONSTRAINT_ERROR wherever the  RM calls for NUMERIC_ERROR to be raised.

**-This really means "no predefined exception other than STORAGE_ERROR
   and IO_EXCEPTIONS.DEVICE_ERROR."  These two exceptions occur for
   reasons that cannot be expressed in terms of the abstract program
   state.  The raising of one of these exceptions is best viewed as an
   unpredictable event that causes the underlying abstract machine to
   break.  It is possible to factor the possibility of such unpredictable
   events into a formal proof of program behavior, but a simpler and
   equally useful approach is to reason about program behavior under the
   assumption that such events will not occur and to prominently
   document the fact that this assumption has been made.

^ permalink raw reply	[flat|nested] 31+ messages in thread
* Re: Pre-condition vs. Post-condition
@ 1991-03-24 21:23 stt
  1991-03-25 16:00 ` Arthur Evans
  0 siblings, 1 reply; 31+ messages in thread
From: stt @ 1991-03-24 21:23 UTC (permalink / raw)



Re: Should documentation on exception be preconditions or postconditions

This is pretty much of a style issue in my view, but
I much prefer Norm Cohen's approach for general readability.
That is, document the preconditions for normal action,
and then document the result of violating the preconditions.

I don't see why it really matters whether the exception is raised
explicitly or implicitly, or whether it is a predefined or user-defined
exception, for in Ada, the nearly universal result of violating preconditions 
is an exception, whether you state it or not.

Seeing exceptions as the result of violating preconditions emphasizes
their "exceptional" nature, and properly discourages using
exceptions as a kind of "status code."  A good rule (subject to the
usual exceptions that prove it!) is that any exception raised at 
run-time represents a program bug or an external failure, and the only 
reason to have user-defined exceptions is to provide better diagnostics
in post-mortem debugging of what are essentially unrecoverable errors.

Exceptions might trigger recovery, but probably only at a high level
(e.g., in an interactive program, they would flush the current
activity and reprompt the human operator; in a fault-tolerant system
they might cause the failing task to be decommissioned, or reset
and reelaborated.)

I realize this is a pretty extreme view of exceptions, namely that
they are primarily a debugging tool, not a programming tool, but
it is consistent with the "extreme prejudice" for efficient non-exceptional
execution speed over exception-handling speed.

Another implication of this view of exceptions is that surrounding
a single subprogram call with an exception handler is generally a bad
idea, since it implies that an exceptional condition is in fact
expected to happen!  Further, it implies that design rules stating that
undocumented exceptions should never be propagated are possibly misguided,
since handling "others" and raising some catch-all exception
is throwing away information which may be critical to post-mortem debugging.

Of course, once a subsystem gets to the point of being "fully" debugged,
and is being reused more and more, all exceptions which can be
propagated should be documented, though it may still be more appropriate
to document certain exceptions on a subsystem-wide basis, rather
than trying to identify each individual subprogram which could propagate them.
The exception handler attempting the recovery (if any), probably does
not "know" which particular subprogram call failed anyway, and it
may be more useful to know what is a reasonable recovery strategy
(e.g., how to "reset" the subsystem so as to allow clients to continue
to use it), than to know exactly which subprograms can cause the
subsystem to enter its exceptional state.

Therefore, if an exception is intended to be used for recovery
rather than simply debugging, the most important thing is that
the particular exception raised identifies which subsystem failed,
in what error state (if any) it is now, and what sort of reset
operation is appropriate.  If the exception
simply indicates that a bad parameter was passed in somewhere,
there is probably no obvious recovery strategy other than to
take two aspirin and fire up the source-level debugger in the morning...

S. Tucker Taft    stt@inmet.inmet.com
Intermetrics, Inc.
Cambridge, MA  02138

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~1991-03-29  3:28 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1991-03-15  3:57 Pre-condition vs. Post-condition Chris M. Little
1991-03-15 19:07 ` Michael Feldman
1991-03-17 12:26   ` George C. Harrison, Norfolk State University
1991-03-18 15:04   ` Joe Hollingsworth
1991-03-18 19:51     ` Marlene M. Eckert
1991-03-19 19:07       ` Michael Feldman
1991-03-21  3:01         ` Jim Showalter
1991-03-21 16:34           ` Exception usage design issues (was: Pre-condition vs. Post-condition) John Goodenough
1991-03-21 18:40           ` Pre-condition vs. Post-condition Michael Feldman
1991-03-19 20:38       ` Charles H. Sampson
1991-03-21  3:06         ` Jim Showalter
1991-03-19 21:07       ` Jim Showalter
1991-03-19  7:38     ` Jim Showalter
1991-03-19 14:46       ` Joe Hollingsworth
1991-03-21  2:46         ` Jim Showalter
1991-03-21  5:12         ` Explicit vs implicit checks (was Pre-condition vs. Post-condition) Scott Carter
1991-03-22 15:18       ` Pre-condition vs. Post-condition Brad Balfour
1991-03-19 18:17   ` Mike Gilbert
  -- strict thread matches above, loose matches on Subject: below --
1991-03-18 15:47 "Norman H. Cohen"
1991-03-24 21:23 stt
1991-03-25 16:00 ` Arthur Evans
1991-03-25 17:05   ` Michael Feldman
1991-03-26  4:31     ` Jim Showalter
1991-03-26 10:21       ` Richard A. O'Keefe
1991-03-26 16:44         ` Michael Feldman
1991-03-26 22:03           ` Richard A. O'Keefe
1991-03-26 23:36             ` Michael Feldman
1991-03-27 21:34             ` Jim Showalter
1991-03-28  2:54               ` Michael Feldman
1991-03-29  3:28                 ` Jim Showalter
1991-03-27  3:12         ` Jim Showalter

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