Writing Correct Software Assertion and exception techniques can aid in class correctness

Bertrand Meyer y aim in designing Eiffel was barring the occurrence of a major ca­ to produce a major program­ tastrophe resulting from faulty software, ming language for the 1990s, sooner or later someone will call the catering to the needs of those software engineers' bluff and ask them . software engineers willing to exactly why they think their systems Mdo what it takes to produce high-qual­ will perform as announced. It is diffi­ ity software. A key aspect of Eiffel, cult to answer that question convinc­ which makes it original in the world ingly given the current state of the art. of object-oriented languages, and in Eiffel won't provide the magical key the world of programming languages to the kingdom of software reliability. at large, is its strong emphasis on tech­ No existing method or tools wilL I do niques that help produce highly reli­ believe, however, that the EiffeI tech­ able software. niques are an impOItant step in the Although, there are many more as­ right direction. pects to Eiffel (including those described If you are expecting a sermon wliing in my book Object-Oriented Software you to improve your software's reli­ Construction, Prentice-Hall, 1988) the ability by adding a lot of consistency reliability features deserve a presenta­ checks, you are in for a few surprises. tion of their own. That is the focus of I suggest that one should llstl:.tlly check this article. I will show how it is possi­ less. According to conventional soft­ ble to write software that programmers ware engineering wisdom, "dett.>I1sive . (and users) can place a much higher programming" is considered to be a degree of confidence in than that writ­ programmer's best shot at reliability. I ten with traditional techniques. In par­ flexible software that is easy to build believe that defensive programming is ticular, I will discuss the all important and easy to maintain, but we also need a dangerow; practice that defeats the notion of assertion - the specification to be concerned that the software does velY purpose it tries to achieve. To element included within the software what it is supposed to do. program defen!'iively i!'i one of the worst itself. This will lead to a systematic From reading most of the object­ pieces of advice thm can be given to a view of exception handling, and a look oriented literature, one would think this programmer. at techniques (such as those offered is not a problem. Correctness concerns That more checking l'ttr1 make soft­ by Ada) that I find somewhat unsafe. are hardly ever mentioned. Actually, it ware less reliable may seem foolish. is unfair just to pick on object-oriented Remember, though, that in science cmu­ Why All the Fuss? programming. Take any standard text­ mon sense is not al\vays the best gUide. The issue is simple. It is great to have books you have on programming, al­ If YOli have ever hit a \\'(}otk~n table gorithms, data structures, and similar with your fist, you probably found it Bertrand is the preSident ofInteractive topics. See how many of them list "cor­ hard to believe rhe physics protf.:ssur Software Engineering and is the main rectness," "reliability," "," or who told you rhar mattl'r is a !'et Df tiny designer ofthe Eiffellanguage. His book, "assertion" in their indexes. I have quite atoms with mostly nothing in-IX'twt,'(.~n. Object-Oriented Software Construction, a few textbooks on my shelves, but waspublished by Prentice Hall in 1988. could not find many that passed this Expressing the Specification He can be reached at 805-685-1006, simple test. 111e ideas that hdp achieve corr(.·t'ml';~s.s or through e-mail as Bertrand at This apparent disregard for correct­ in EitTd are mtK~h ()kk~r than EithA it,· Eiffel.com. ness issues cannot last forever. Even (continued Wl!UIJ{{' 52} 48 < EIFFEL

(continued from page 48) ware element is correct or incorrect per may still publish the manuscript, but self. They come from work on program se; it is correct or incorrect only con­ does not have to. The situation is out­ proving and fonnal specification. Oddly cerning a particular specification, or side of the contract's bounds. enough, research on these topics has statement of its purpose. Correct ele­ remained estranged from most "real­ ments cannot be written unless the time Routine as Contract world" software development. Part of is taken to express all or part of this Specifying a routine is based on the the reason, at least in the United States, specification. transposition of these observations to is the widespread view that fonnal speci­ Writing the specification will not guar­ software. First, we need the equivalent fication and verification are specialized antee that it is met. But the presence of the contract document. It bewilders research topics whose application is of a specification, even one that is only me that no such concept exists in stan­ mostly relevant to "mission-critical" soft­ partially spelled out, goes a surpris­ dard approaches to software construc­ ware. Correctness, however, should be ingly long way toward helping pro­ tion. a universal concern. Eiffellooked at speci­ duce elements that satisfy their correct­ The specification consists of two fication and verification work to see ness requirements. parts: how much of it could be made part of This idea was captured by the title a standard programming methodology. of an article by Harlan Mills, then of • The of a routine states Eiffel is a production language and IBM, published in 1975: "How to Write the obligations of clients, which are environment. It is not a research vehi­ Correct Programs and Know Why." If also the benefits for the routine itself. cle. Eiffel relies on the technology of you are a serious software engineer, • The states the obliga­ the last part of the twentieth century. you don't just want to hope that your tions of the routine, which are also It has to work now. This means that no programs are correct because you have the benefits for the clients. miracles can be expected. In fact, the been careful, and done a lot of testing, techniques are modest and almost naive. and so on. You need precise argu­ The precondition is a set of initial con­ They are the result of an engineering ments that document the correctness ditions under which the routine oper­ trade-off between what is desirable in of your software. ates. Ensuring the precondition at the an ideal world and what can realisti­ In Eiffel, such arguments are ex­ time of any call to the routine is the cally be implemented today. But they pressed as assertions -:- elements of for­ clients' responsibility. make a big difference and I can't un­ mal specification that can be attached The postcondition is a set of final derstand why no widespread language, to software components, classes and conditions the routine is expected to other than Eiffel, has made any signifi­ their routines. ensure. Ensuring the postcondition at. cant attempt in a similar direction. return time (if the precondition was The basic idea is rather trivial. Cor­ The Contract met on entry) is the routine's responsi­ rectness is a relative notion. No soft- Let's look at routines first. A routine is bility. the description of some computation The concept of a contract is one of the on the instances of a class, made avail­ most useful aids to understanding Eif­ able by that class to its clients (to other fel programming. The role of contracts

Bring in manuscript Get published telC! classes relying on its services). How in Eiffel can be compared to what mes­ before March 1st before May 1st do we specify the purpose of a routine? sage passing represents in Smalltalk. The view I find most helpful is that Publish before No need to do Figure 3 illustrates this idea. The func­ May 1st anything if no a routine provides clients with a way tion intersect1 in a class CIRCIE (as­ manuscript is received before to contract out for a certain task that sumed to be part of some graphic pack­ March 1st the client's designer finds advantageous age) returns one of the two intersecting not to implement within the text of the points of two circles (see Figure 2). client. This is the same way that we We will look at how to associate the Figure 1: Contract between a humans at times contract out for part precondition and the postcondition to publisher and an author or all of a task that we need to perfonn. the text of the function in the actual Human contracts have two impor­ Eiffel class. In this example: tant properties: • The precondition is that the two rec­ • Each party expects some benefits and tangles should intersect. is prepared to incur some obligations • The postcondition is that the function in return. What is an obligation for result is a point that is on both circles. one party is a benefit for the other. • The obligations and benefits are Contract Variants spelled out in a contract document. This is not the only possible specifica­ Figure 2: Circle intersection tion. Programmers may feel uneasy Figure 1 illustrates an example of a about the just mentioned "demanding" contract between a publisher and an fonn of the routine, which only works Obligations Benefits author. The author's obligation is to in some cases. Instead, a tolerant ver­ Client Call the routine on ObtaIn as result of bring in a manuscript before March 1st. sion implementing a different contract two circles that the function a Intersect point that is on The benefit to the author is that the may be designed. For example: both circles manuscript will be published before Routine Find a point that is No need to retum May 1st. The publisher's obligation is • There is no precondition. More pre­ on both circles anything meaningtul if the circles do not to publish the manuscript before the cisely) the precondition is true, and intersact second date. automatically satisfied by any client. The publisher is not bound by any Here, the routines will be applicable obligation if the author violates his part in all cases. Figure 3: A routine contract of the deal. In such a case the publisher • The postcondition is more difficult Dr. Dobb'sjournal, December 1989- EIFFEL

(continued/rom page 52) correct. When a routine is written, its though, that short is meaningless With­ to express in this case. Either the two goal (contract) is expressed. If this goal out the presence of assertions in the circles intersect and the function result cannot be expressed in a formal way, language. is a point on both circles; or the two it should still be expressed as formally circles do not intersect, the function as possible. Invariants result is an arbitrary pOint, and an error Documentation is another key appli­ and can message has been displayed some­ cation of assertions. One of the most be used in a non-object-oriented con­ where. The awkwardness of stating the pervasive myths of software engineer­ text. Another use of assertions that is postcondition in such a way is the first ing literature is the idea that document­ inseparable from the object-oriented sign of why "demanding" versions are ing software is a worthy goal. Instead, approach is the . This is often better. documentation should be viewed as an optional clause of Eiffel classes. An an evil, made necessary by the insuffi­ invariant is a consistency constraint that Expressing the Contract cient abstraction level of current tools, applies to all instances of the class. Let's see how the preconditions and techniques, and languages. It is an evil In the CIRCLE example, the invariant postconditions will be integrated. List­ not just because documentation is tedi­ clause might state the following asser­ ing One, page 125, shows what a class ous to produce, but also because it is tion: CIRCLE might look like. Assume the almost impossible to maintain the con­ availability of a class POINT describing sistency of a software system with its radius >= 0; points, and a function distance, such documentation throughout the system's inside (center) that p I.distance (P2) is the distance evolution. Incorrect or out-of-date docu­ between any two points (PI and p2). mentation is often worse than no docu­ In larger examples the invariants can Result is a predefined variable which, mentation at all. . be much more extensive. in a function, denotes the result of that In an ideal world, software should Invariants can be viewed as general function. Create is the initialization pro­ be self-documenting, with no need for clauses that are implicitly added to all cedure. It is automatically exported. outside documentation. Failing this pro­ contracts of a certain class, without be­ The precondition of a routine, if any, grammer's Eden, we should strive to ing expressly repeated for each of these is given by the require clause. The post­ have as little need for external docu­ contracts. The precise definition of the condition is given by the ensure clause. mentation as possible. Documentation class invariant is that it is an assertion Preconditions and postconditions are should be deduced from the software that: assertions -logical constraints ex­ itself. "Self-documenting software" does pressed as one or more Boolean ex­ not mean that the software is its own • Must be ensured by the Create of the pressions, separated by semicolons. documentation. Instead, self-document­ class They are essentially equivalent to ing software should contain part, or • Must be preserved by every exported Boolean ANDs, but allow assertion com­ (ideally) all, of its documentation, cor­ routine of the class ponents to be identified individually. responding to various levels of abstrac­ These components can be tagged for tion, which can be extracted by auto­ In principle, we could do away with even better identification. For exam-· matic tools. the invariant by adding its clauses to pIe, consider Listing Two, page 125. Preconditions and postconditions the precondition and postcondition of Note that the first clause in this pre­ playa key role because they document every exported routine, and to the post­ condition (as well as clauses in the the essential properties of routines: What condition of the Create. But, besides preconditions of inside and outside) each routine expects and what each making these assertions unduly repeti­ express that the argument must be non­ ensures in return. The Eiffel environ­ tive, this would be losing sight of the void. Void is a predefined language ment provides an automatic tool that role of the invariant as a glqbal integ­ feature expressing whether there is an yields the documentation of a class rity constraint on the class, independent object associated with a certain refer­ based on its assertion. This tool, the of a particular routine. ence. class abstracter, is implemented by a The two properties used earlier to command called "short." Applying short define the invariant imply that the in­ Uses of Assertions to a class yields the description neces­ variant is satisfied in all observable states Along with invariants (discussed later), sary to determine whether the class can in the life of every instance of the class. preconditions and postconditions play be used in a certain situation, and, if Observable states are those immedi­ a fundamental role in the design of so, how to use it effectively. ately following the Create, and before Eiffel classes. They show the purpose The result of short applied to class and after application of exported rou­ of routines and the constraints on their CIRCLE would be of the form shown tines. The life of a typical object is uses. A brief look at any well-designed in Listing Three, page 125. pictured in Figure 4, with observable set of Eiffel classes shows how wide As shown in this example, short states marked as square blocks. The their application is. The Basic Eiffel keeps, as a complement to formal as­ idea of an observable state is important Library, which covers fundamental data sertions, the natural language header in the context of parallel programming. structures and algorithms, is an exam­ comments of routines, if present, at a In spite of its name, an invariant is ple of a set of carefully designed classes well-defined place. Only exported fea­ not necessarily satisfied at all times. It that come fully loaded with expressive tures are kept by short. may be temporarily violated during exe­ assertions. short provides documentation "for cution of exported routines, so long as The first application of assertions, free" - it is extracted from the soft­ it is restored for the next observable perhaps the most powerful, is as a con­ ware. short is the major tool for docu­ state. ceptual design aid for producing reli­ menting Eiffel classes. A companion An invariant captures the semantic able software. In this role, precondi­ tool, good, produces high-level system properties of a class, independently of tions and postconditions directly sup­ documentation in graphiC form, show­ its current implementation, by a set of pOlt the goal stated earlier: Writing cor­ ing the class stmcture with client and attributes and routines. These proper­ rect software and knowing why it is inheritance relationships. Remember, ties mLlst be understood in a software 'i4 Dr: Dobb :')lournal. December 1989--- EIFFEL

(continued/rom page 54) Assertions and Inheritance explicit the otherwise implicit mental engineering context in which software Assertions also play an important role assumptions that lie behind our soft­ is always subject to change. Invariants in the context of inheritance. Invariants ware. It is typical for a bug to cause can help bring some order to a con­ are always inherited. When a routine one of these assumptions to be vio­ stantly changing environment by ex­ is redefined, its precondition may be lated. When this occurs, run-time moni­ preSSing what does not change in a weakened, but not strengthened. Its toring will catch the violation. This de­ class - the basic semantics of the class. postcondition may be strengthened but bugging technique takes on its full mean­ Invariants can play a major part in not weakened. To understand these ing in the object-oriented context. I establishing a scientific basis for soft­ rules, the contracting metaphor must used it when using the Algol W com­ ware activities that currently rest on a be viewed in the context of inheri­ piler in the seventies. Its superiority rather shaky basis: Quality assurance, tance, redefinition (subcontracting), and over usual de pugging methods is hard regression testing, and maintenance. dynamic binding. to imagine until you have actually ap­ Because an invariant expresses the es­ plied it. sential semantics of a class that should Monitoring Assertions be preserved through successive modi­ The question of what happens when an Defensive is Offensive fication and extension, it provides a assertion is violated (such as if intersect1 If a routine has a precondition p, de­ framework for making QA and associ­ is called on two circles that do not fensive programming would mean that ated activities more systematic. intersect) is secondary. The main ques­ the text of the routine should test again tion is: How can we, as responsible for p, in case the client forgot. For in­ Limitations of Assertions software profeSSionals, make sure that stance, consider Listing Four, page 125. The Eiffel assertion techniques are only we produce software that is correct? The form as shown in Listing Four partial. The assertion sublanguage is The tendency to reverse the priori­ is never acceptable. It is a sloppy style based on Boolean expressions with ties and ask the secondary question of programming in which responsibil­ some extensions. Sometimes more is first is a sign of how insecure most of ity for ensuring various consistency con­ needed, such as first-order predicates. us in the software engineering profes­ ditions (contract clauses) have not been In the CIRCLE class it would be nice to sion feel about our techniques and tools. clearly assigned. Because the contract have the invariant express that no point This article won't reverse this situation. is unclear, the scared programmer in­ can be both inside and outside the Still, we must get our priorities straight. cludes redundant checks "just in case." circle, or that any such point must also The answer to what happens when This is a self-defeating policy. Com- . be "on" the circle. The notation for this an assertion is violated depends on plexity is the single, worst enemy of could be: how you have compiled your class. If software reliability. The more redun­ you have made the effort of spelling dant checks, the more complex the for p: POINT then out the mental hypotheses that under­ software becomes, and the greater the inside (p) and outside (p) lie the correctness of your software, risk of introducing new errors. implies on (p) you could expect a theorem prover to Reliability is not obtained by cow­ end check the software against these hy­ ardly adding even more checks, but potheses. Unfortunately, this is beyond by precisely delineating whose responsi­ This is not possible in current Eiffel, today's technology. The next best thing bility it is to ensure each consistency although properties involving quantifi­ to static proof is run-time monitoring. requirement. A party in a contract may ers ("for all," "there exists") can some­ If you compile a class under the AU_ fail to meet the requirement imposed times be expressed through Boolean ASSERTIONS mode, all assertions (pre­ on it. This is precisely what a bug is. expressions involving function calls. conditions, postconditions, invariants) The solution, however, is not to make These function calls require some care. are checked at the appropriate times the software structure more complex Other limitations of assertions are due during execution. If one is found to by introducing redundant checking, to the reference-based dynamic model be violated, an exception is triggered. which only makes matters worse. For used for objects. Unless you have made explicit provi­ fault-tolerant design, you should be able The mechanism is the result of an sions to handle it, the exception will to rely on a general-purpose run-time engineering trade-off. Though limited, result in program termination with a checking mechanism. In Eiffel, this assertions are a tremendous asset in clear message identifying the context mechanism is the monitoring of asser­ Eiffel programming. of the failure. tions as described above. There is never a good reason to com­ With redundant checking being un­ pile a class under any option other acceptable, we still face a choice be­ c. Create (... J than AU_ASSERTIONS, except perfor­ tween the "demanding" (strong pre­ mance. If you are sure your software condition) style and the "tolerant" (no c.f is correct and do not want to incur the precondition) style, with the intermedi­ overhead of checking, use the NO_AS­ ate spectrum. Mathematically, tolerant SERTION_CHECKmode. If a bug does routines represent total functions and c.g remain, though, you are on your own. demanding routines represent partial The default is an intermediate mode, functions. Which one to use depends which generates code that checks pre­ on the circumstances. The closer a rou­ conditions only. Switching modes may tine is to uncontrolled "end users," the c.f be needed a number of times during more tolerant it should be. But even development. This switch is easy. Only with general-purpose library routines, the last stage of compilation is repeated there is a strong case for demanding for the corresponding class. routines. Run-time monitoring of assertions pro­ With a strong precondition, a rou­ vides a powerful debugging mecha­ tine can concentrate on doing a well­ Figure 4: The life q( a ~ypical object nism. Asseltions are a way to make defined job and doing it well, rather Dr: Dobb :\' Tournai. December 1989--'---- EIFFEL

(continued from page 56) ception violation is not an expected exorcism has been dispelled, there is being concerned with other things. The situation that you want to handle sepa­ still room for an exception mechanism intersectl routine becomes a mess if it rately from the others - it is the mani­ Exceptions should not be used as con~ isn't assumed that the circles do inter­ festation of a bug. To handle special trol structures. They have no advantage sect. Tolerant routines must address cases, there is not much substitute for over standard control structures, and have user interface concerns for which the what you learned on day two of Intro­ many drawbacks. Some mechanism is routines do not have the proper con­ duction To Programming 100 - the needed however, to deal with an op­ text. The intersectl routine must ad­ if ... then ... else construct. erati?~ t~a~ might. fail in such a way dress problems of geometrical algorith­ There seems to be another pervasive that It IS dlfflcult or lmpossible to check mics (computing the intersection of two myth in the industry that one can forget for with a standard control structure. intersecting circles in the best possible about special cases through a form of Following are three main examples: way). It is difficult to reconcile these faith healing. This can be called "pro­ two aspects in a single routine. The gramming by prayer." In Ada, the sa­ 1. Bugs. By definition, a bug is unex­ solution that will ensure reliability more cred word is raise. Whenever you en­ pected. If you were able to test for its certainly than blindly checking all con­ counter a situation that threatens to occurrence, you would correct the bug straints all the time, is to separate the disrupt the spiritual harmony of your in your software, not handle it at run checking and the computation. program, kneel down and say, raise time. If, in spite of your best efforts, a Conventional wisdom, which says some_exception and a saint or angel bug does occur, you still want the abil­ "never assume anything, anywhere," will come and take your worries away. ity to recover from it somehow at run 'is wrong and dangerous. Its perva­ It doesn't work this way. The "an­ time, even if only to terminate the exe­ siveness can only be explained by the gel" has to be programmed, and ust+­ cution gracefully. absence of any notion of contract in ally by you. Postponing a problem does 2. Uncheckable consistency conditions. standard approaches to programming. not solve it. Some preconditions may be impossi­ If clients have no precise specification In Ada, after a raise, a chain of calls ble to check as part of an if ... then ... of the conditions they are supposed to that led to the exception is explored, else, either because they are too com­ observe, they can't be trusted to ob­ in reverse order, until a block is found plex to express formally, or because serve these conditions and there is no that includes an exception clause of the applicability of an operation can choice but to include as many consis­ the form: only be ascertained by attempting the tency checks as possible. In a system­ exception operation and seeing if it fails. For ex­ atic approach to software construction, when ample, a write to disk operation may however, the contract is clearly and some_exception=>some_action; fail, but it is not useful to ask first and adequately expressed, independently when then write. The only way to know if of its implementation, through asser­ othecexception=>othecaction; you can write is to attempt to write. tions. By using the short command to Then, if something goes wrong, you let client designers see this contract, One of the when branches names the must be able to recover. Another ex­ you can concentrate on doing your job current exception. Then the code ample, in an interactive system, is the rather than checking theirs. some_action is executed and control implicit precondition that the user will Considered in the perspective of other returns to the handling block's caller. not hit the BREAK key. Obviously, you engineering disciplines, the often rec­ If your aim was to make your soft­ cannot test for the occurrence of such ommended ban on "partial" routines ware simpler by separating the pro­ events. seems absurd. If you ask an electrical cessing of "normal" and "special" cases, 3. Impractical to check before each call. engineer to design an amplifier that you will be disappointed. Special cases These are operations for which express­ will work for any input voltage, or a will not go away through the raise at­ ible preconditions exist in principle, mechanical engineer to build a bridge tempt at absolution. Such as old sins, but for which it is impractical to check that will hold any load, they will laugh they will come back to haunt you in before each call. For example, few pro­ at you. Any engineering device has your exception clauses. In the program grammers want to protect every addi­ preconditions. There really is no good text, such clauses are far away from the tion by a test for non-overflow, or ev­ reason why software routines should source of the exception. They usually ery object allocation (Create) by a check be required to be total. lack the proper context to deal with the that enough memory remains. As in the The reference to electronic compo­ exception. previous case, but for practical, rather nents is not coincidental. One of the There are two cases of exception than theoretical reasons, you want to most exciting advantages of object­ handling. One is when the exception be able to attempt the operation, pro­ oriented techniques is the ability to must be handled identically for all calls ceed as if everything went all right, but work from libraries of standardized, of the routine. This type of exception recover if something goes wrong. off-the-shelf, reusable components. is much better handled by an if ... These components are similar to hard­ then ... else ... clause in the routine These three cases are ones for which ware components used in electrical en­ itself. In other words, the routine should exceptions are needed. They are not gineering. These libraries cannot be be made more tolerant. "special" or expected algorithmic cases, . successful unless the components are The second is when the handling of but abnormal situations that cannot be specified in a precise and standardized the special case is different for each properly handled by standard algo­ . way. Trying to sell a class without its client. This can be achieved by protect­ rithmic techniques. invariant, preconditions and postcon­ ing each call with an if . . . then ... In Eiffel, an exception occurs in the ditions is like trying to sell an amplifier else. The routine itself remains demand­ following situations: without its engineering specs. ing. In either case no special control structure is needed. • Assertion violations (if monitored). Programming by Prayer The violation of an assertion is al­ Assertions are not a way to program Exceptions ways a bug. A violated precondition the handling of special cases. An ex- Once the naive faith in exceptions as reflects a bug in the client; a violated

58 Dr. Dobb'sjournal, December 1989 EIFFEL

(continued from page 58) In the exception history table shown tags, when present, in the messages postcondition reflects a bug in the in Figure 5, some exceptions are dealt shown in Figure 5. routine. with in each of these two modes. The Not all exceptions cause failure. A • Hardware or operating system sig­ table, shown as it is printed at run time, rescue clause may execute a retry in­ nals, such as arithmetic overflow, mem­ is divided into periods, separated by struction, in which case the body (do ory exhaustion, and so forth. double lines. Each period, except the clause) of the routine must be tried • An attempt to apply an operation to last, ended with a retry. again, presumably because a substitute a non-existent object (Void reference). The absence of a clear-cut choice s~rategy is available. This is the resump­ • Failure of a called routine. between resumption and retry is what twncase. makes the Ada mechanism too gen­ For example, consider the routine The range of such exceptions is much eral, and hence dangerous. Some Ada in Listing Five, page 125, for attempting less extensive in Eiffel because of the examples show cases in which a rou­ to write to disk, from a generic class C. disciplined nature of the language. In tine reacts to an exception, fails to cor­ Here it is assumed that the actual particular, the static typing mecJ:lanism rect the cause of the exception, and write is performed by a lower-level ex­ of Eiffel implies that for a correctly returns to its caller without signalling ternal routine attempt-to-write, written compiled system there is no exception the exception. This is extremely dan­ in another language, over which we for a "feature applied to an object that gerous. have no control. If this routine fails, it cannot handle it (a message sent to an Eiffel enforces the choice between triggers an exception, which is caught object that cannot process it)." resumption and retry. The key idea is by the rescue clause. This results in a that of routine failure - a routine may retry. Local routine variables are initial­ Dealing with Exceptions succeed or fail. If it fails to achieve its ized on routine entry. An integer vari­ What happens when an exception oc­ contract, it may either try again or give able such as attempts, is initialized to O. curs? The Ada answer is dangerous. up. It should not conceal the failure The routine write never fails. Its con­ Because you can do essentially any­ from its caller. tract says, "write if you can, otherwise thing you like in a when clause, there This explains the fourth case in the record your inability to do so by setting is no guarantee that you will achieve earlier list of Eiffel exceptions. The fail­ the value of attribute write_successful anything remotely resembling the origi­ ure of a routine automatically triggers to false, so that the client can deter­ nal purpose of the routine that failed. an exception in its caller. This is imple­ mine what happened." It is always pos­ To obtain a satisfactory solution, it mented by the optional routine clause sible to satisfy such a contract. is necessary to think in terms of the rescue. If present, the rescue clause is The version of write shown in Listing contract that a routine is meant to en­ executed whenever an exception oc­ Six, page 125 is a variant of the class sure. The routine initially tries to satisfy curs during the routine's execution. that does not include attribute write its contract by following a certain strat­ If a rescue clause is executed to the successful. It may succeed or fail. - egy, implemented by the routine's body end, the routine terminates by failing. In this version, after five attempts, (the do clause). An exception occurs As noted, this automatically raises an the routine terminates through the bot­ when this strategy fails. In the disci­ exception in the caller, whose own tom of its rescue clause. This means plined approach, only two courses of rescue clause should handle it. If a the routine fails, triggering an excep­ action make sense: routine has no rescue clause, as will tion in the caller. This contract is more typically be the case with most rou:­ restrictive than the one shown in List­ • The routine (contractor) may have a tines, then it is considered to have an ing Three. It requires that the routine substitute strategy. If so, it should bring empty rescue clause - any exception be able to write. If this contract cannot the target object back to a stable state occurring during the execution of the be fulfilled, the only exit is through and use this strategy. This is the re­ routine leads to immediate failure and failure. sumption case. an exception in the caller. If no routine • If no substitute strategy is available, in the call chain has a rescue clause, Formal Requirements the routine should bring the target ob­ the entire execution fails and an appro­ The deeper meaning of the rescue ject back to a stable state, concede priate message, recording the history clause can be understood in the object­ failure, and pass the exception to its of recent exceptions in reverse order, oriented context, and with reference client. This is the failure case. is printed. Note the use of assertion to the contract of a routine, as expressed by assertions. The following expresses the require­ Object Class Routine Name of exception Effect ments on a contractor that implements 2FB44 INTERFACE m_creation Feature "quasUnverse"; Retry software element e: Applied to void reference MATH 2F188 quasUnverse "positive_oenul/"; Fail {P}e{QI (from BASIC_MATH) Precondition violated

2F188 MATH raise "Negative_ value"; Fail This means the contractor must write e (from EXCEPTIONS) Programmer exception in such a way that, whenever P is satis­ fied on entry, Q will be satisfied on 2F188 MATH filter "Negative_ value "; Fail exit. The stronger P is, the easier the Programmer exception contractor's job (more can be assumed); the stronger Q is, the harder the con­ new_matrix 2F321 MATH "square_matrix"; Fail tractor'S job is (more must be produced). (from BASIC MATH) Invariant violated Consider routine r with body do, 2FB44 INTERFACE create Routine failure Fail precondition pre, and postcondition post, in a class with invariant INV. The Figure 5: An exception history table (continued on page 63) p

EIFFEL Learn in 3 Intensive Days (continued from page 60) if exception=No_more_ memory requirement on the author of the do then ... elsif and so on. How Object-Oriented clause is: Generally, it is wise to resist the temp­ Approaches Will Change Ipre and INV} do Ipost and INV} tation to attach too much meaning to the World of Software the precise nature of an exception. An exception usually points to a symp­ Development in the 1990s. In other words, the invariant and the tom, rather than a cause. precondition can be assumed, the in­ For programmers who want to define variant must be preserved, and the post­ and raise their own exceptions, the rou­ condition must be ensured. Now, con­ tine raise is available in class EXCEP­ Larry L Constantine sider a branch rescue, of the rescue TIONS. The default handling of certain Chairperson clause, not ending with a retry. The exceptions, especially operating sys­ requirement here is: tem Signals, can be changed by rede­ fining certain routines from class EX­ Itrue} do IINV} CEPTIONS. By using class EXCEPTIONS, application software can access infor­ The' input condition is the weakest mation about the last exception. This Speakers Include: possible (hardest from the contractor's information includes the exception type, viewpoint), because an exception may its meaning expressed as a plain Eng­ • occur in any state. The rescue clause lish string, and so on. This is particu­ • David W Embley must be prepared to work under any larly useful for printing informative er­ • Robert Howard &: condition, but the output condition only ror messages. Marie Lenzi includes the invariant. Ensuring the in­ variant brings the object back to a sta­ Why Not Make It Right? • Burt Rubenstein ble state. Integrity constraints play a Reliability is a primary concern in any • Stephen Schur similar role in data base systems. The serious view of software construction. • Paul Ward rescue clause is not, however, con­ In the object-oriented' approach, it is • Rebecca Wirfs-Brock strained to ensure the entire postcondi­ even more essential. Reusability of soft­ tion. This is the sole responsibility of ware is meaningless unless the reusable the do clause. If the contractor satisfies components are correct and robust. Product Education the routine's contract, there is no need Static typing is an important aspect of for the rescue clause. Eiffel's contribution to this goal (see Sessions By: This shows the clear separation of the article "You Can Write, but Can • AICorp, Inc. concerns between the do clause and You Type?" in the March 1989 issue of • Aion Corporation the rescue clause. The former is re­ the journal ofObject-Oriented Program­ • Complete Computer ming for more on this subject). sponsible for achieving the contract Corporation when possible. The latter takes over in The assertion and exception tech­ case the do clause falters. The rescue niques described in this article provide • Interactive Development clause restarts the do clause under im­ the complement to static typing. They Environments, Inc. proved conditions, or closes the store don't absolutely guarantee that your • Object Design, Inc. after putting things in order. The re­ classes will be correct and robust, but • Softlab, Inc. quirements on the rescue clause are they sure can help. both harder (a weaker precondition) • The Stepstone Corp. and easier (a weaker postcondition). Availability • Symbolics, Inc. All source code is available on a single • The Whitewater Group Fine-Tuning the Mechanism disk and online. To order the disk, Those are the basics of Eiffel exception send $14.95 (Calif. residents add sales handling. In practice, some fine-tuning tax) to Dr. Dobb'sjournal, 501 Galves­ Chicago may be needed for particular applica­ ton Dr., Redwood City, CA 94063, or December 5-7, 1989 tions. This is done not through the call 800-356-2002 (from inside Calif.) language itself, but through the library or 800-533-4372 (from outside Calif.). Tutorial Session: class EXCEPTIONS. Classes needing the Please specify the issue number and December 4, 1989 corresponding facilities should inherit format (MS-DOS, Macintosh, Kaypro). this class. Source code is also available online It is sometimes necessary to treat through the DDj Forum on Compu­ Digital Consulting, various exceptions differently. Attrib­ Serve (type GO DDJ). The DDjListing ute exception in class EXCEPTIONS has Service (603-882-1599) supports 300/ Inc. the value of the code of the last excep­ 1200/2400 baud, 8-data bits, no parity, tion that occurred. Exception codes are I-stop bit. Press SPACEBAR when the ~ integer symbolic constants (attributes) system answers, type: listings (lower­ defined in that class. Examples include case) at the log-in prompt. (~i Precondition (precondition violated) and other assertion-related exceptions, DDJ For detailed 8-page brochure: No_object, No_more_memory, operat­ (listings begin on page 125.) Call (508) 470-3880 ing system signals (Sighup and so on.) Vote for your favorite feature/article. lA29DW and others. A rescue clause may con­ Circle Reader Service No.4. tain a test of the form: CIRCLE NO. 70 ON READER SERVICE 63