From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!magnus.acs.ohio-state.edu!tut.cis.ohio-state.edu!sei.cmu.edu!jbg From: jbg@sei.cmu.edu (John Goodenough) Newsgroups: comp.lang.ada Subject: Exception usage design issues (was: Pre-condition vs. Post-condition) Message-ID: <23018@as0c.sei.cmu.edu> Date: 21 Mar 91 16:34:54 GMT References: <344@platypus.uofs.edu> <2865@sparko.gwu.edu> <97779@tut.cis.ohio-state.edu> <311@nic.cerf.net> <2891@sparko.gwu.edu> Organization: Carnegie-Mellon University (Software Engineering Institute), Pgh, PA List-Id: Seeing all this discussion about the philosophy of exception usage reminded me of a short position paper I wrote a few years ago on this point. I'm posting it here because it presents some views that haven't been stated yet, and someone once told me that it had been helpful when they were designing a real system. USING EXCEPTIONS: SOME DESIGN ISSUES John B. Goodenough Software Engineering Institute Carnegie Mellon University, Pittsburgh, PA 15213 September 21, 1988 1 Summary This paper addresses Topic 9 of the Application Software Design working group: Discuss the best use of exceptions in the design of management information systems, their benefits and problems, including scope, propagation, control, and usage. Only Ada and PL/I provide explicit language support for handling exceptions. Since exceptions are not supported explicitly by the most commonly used programming languages,(FORTRAN, COBOL, and C) few programmers and system designers have experience in making effective use of this language feature. It's easy to think of exceptions as a kind of ``add-on'' feature of a software design, i.e., a facility whose use is left to the designers of individual modules and routines. In fact, exceptions are used most effectively only if the strategy guiding their use is developed in the earliest stages of a design. Moreover, effective use of exceptions requires attention throughout a design. In this paper, I will discuss some of the questions that should be considered by information system designers when deciding how to treat exceptions in designs. 2 Definitions First some definitions. An exception situation arises when an operation is invoked and cannot be completed in a ``normal'' fashion. From a design viewpoint, I think it is best to view an exception situation as a situation that occurs when an operation is invoked and certain input predicates fail to hold. The invoked operation detects this failure and allows the invoker to deal with the situation appropriately. The advantage of identifying and using exceptions is that it allows the effect of an operation to be extended to cover a wider range of situations, since the invoker is given the responsibility. What are some examples of input predicates whose failure gives rise to an exception situation? - For a POP operation of a stack or queue, an input predicate is ``the stack or queue has at least one element.'' An exception situation occurs when POP is invoked and this predicate does not hold. - For a READ operation on a file, an input predicate is ``there exists a record to be read.'' - For a TABLE_LOOKUP operation, an input predicate is ``the sought-for value exists.'' - For MATRIX_INVERSION, an input predicate is ``an inverse exists.'' An exception condition is signaled to the invoker of an operation when the corresponding exception situation is detected. A handler for the condition specifies the invoker's response to the exception situation. Exception situations are not always errors. They may be boundary conditions whose significance is known primarily to the operation's invoker. Exceptions serve to generalize operations (making them usable in a wider variety of situations) because: - The response to an exception situation is provided by the invoker instead of by the operation itself. - An arbitrary, operation-defined response to the situation can be replaced by an appropriate user-defined response. 3 Design Issues My definition of an exception situation leads to natural questions that should be addressed during the design phase. - First, identify the input assertions associated with an operation, i.e., the assumptions and preconditions that allow the operation to complete in a ``normal'' manner. - Then evaluate each assertion, using criteria such as: * How easy is it for the operation's invoker to check the assertion before calling the operation? * When the check fails, is a fixed response (provided by the operation) always acceptable? * An operation's behavior may be undefined if an operation is invoked when an input assertion is unsatisfied. Are the consequences of such behavior likely to be important? Depending on the answers to these questions, a designer can decide whether an exception situation should be handled by signalling an exception condition. Given a decision to handle an exception situation, there are some other design decisions that need to be considered: - Should an inquiry function be provided? - Should a boolean function be provided to check whether the exception situation will occur? An inquiry function is called after an exception is raised and provides additional information about the nature of the situation. Such functions are useful when the invoker's response to an exception situation might change depending on specific details involved in the situation. For example, if an operation detects ill-formed terminal input, the most helpful response may depend on the specific characters that were typed in. Since an exception handler does not, in general, have access to all the information available to the operation that signals the exception, the needed additional information must be provided to the invoker. There are at least two ways of doing this: - If the programming language permits exceptions to be raised with parameters, the designer needs to decide what parameters should be provided. - If no parameters can be associated with exceptions, an inquiry function must be provided. Providing an inquiry function extends the usability of an abstract data type, but it can easily violate information hiding principles, since the details of a particular exception situation might well reflect an implementation approach. Nonetheless, such functions are very useful when investigating mysterious program behavior. If they are not provided consistently throughout a design, it can be very difficult to extract the needed information by using a debugging tool. The MULTICS operating system, written in PL/I, was careful to provide such functions for all basic operations. In one case when I was using MULTICS, PL/I told me that I had encountered a device error. I would have been unable to diagnose the reason for the problem if I hadn't been able to call a function returning the full status word for the device. Of course, such a function is device dependent, and this is the disadvantage of such functions. Whenever it's not too costly, it's a good idea to provide a boolean function that checks for an exception situation. For example, if a READ operation will raise an exception when the end of a file is encountered, a function should also be provided that checks for the end of file. These functions sometimes allow more readable programs to be written. For example, if the programmer is primarily interested in whether a file is at its end, it is certainly more convenient to check this directly by calling the end-of-file function rather than by calling the READ operation just to see if it raises an exception! (And if it doesn't, you need to preserve the value that was read.) In addition, some language constructs depend on the use of predicates rather than exceptions. For example, a guard in an Ada select statement is a boolean expression. If the value of a guard depends on the state of a file and there is no end-of-file function, the programmer must go to considerable trouble to obtain the correct boolean value. Of course, it's not always appropriate to define an exception for every input predicate. For example, a precondition for the correct operation of a binary search function is that the table being searched is ordered. Checking that the table is ordered each time the search is called would completely defeat the purpose of the algorithm! Here is a case where no exception should be defined. Similarly, it is not always appropriate to provide a function to check for an exception situation independently of invoking the operation. For example, a matrix inversion operation should raise an exception when the matrix has no inverse, but since it is almost as costly to check for this situation as to attempt to find the inverse, it's probably not sensible to provide a function in this case. 4 Example As a simple example of these ideas, consider a simple function that is to calculate the sum of a set of numbers presented in some input stream. What preconditions could lead to exception situations, and what inquiry functions might be provided? For which exception situations should corresponding boolean functions be provided? The preconditions could be: - There exists a sum (i.e., the sum does not overflow; it is representable). - The input stream is not empty. - The input is syntactically valid. Possible inquiry functions and their results could be: - When overflow occurs, the inquiry function returns the sum just before the exception was raised, together with the number that was read. - When any exception occurs, an inquiry function returns how many numbers have been read, telling the programmer how much of the input stream has been processed. - When syntactically invalid input is read, an inquiry function can return the invalid string that was read. REFERENCES Issues concerning the use of exceptions, particularly in Ada, are discussed in some detail in pages 94-127 of Ada in Practice.(Ausnit, C. N., Cohen, N. H., Goodenough, J. B., and Eanes, R. S, Springer-Verlag, 1985.) -- John B. Goodenough Goodenough@sei.cmu.edu Software Engineering Institute 412-268-6391