T. Wolf: on Exceptions As First-Class Objects in Ada 95
Total Page:16
File Type:pdf, Size:1020Kb
On Exceptions as First-Class Objects in Ada 95 Thomas Wolf Paranor AG, Switzerland e–mail: [email protected] Abstract. This short position paper argues that it might gramming languages that show a much better integration be beneficial to try to bring the exception model of of object orientation and exceptions, most notably Java. Ada 95 more in–line with the object–oriented model of In the remainder of this paper, I’ll try to make a case programming. In particular, it is felt that exceptions — being such an important concept for the development of for better integrating exception into the object–oriented fault–tolerant software — have deserved a promotion to paradigm in Ada 95. Section 2 discusses some problems first–class objects of the language. It is proposed to with the current model of exceptions. Section 3 argues resolve the somewhat awkward dichotomy of exceptions for an improved exception model that would solve these and exception occurrences as it exists now in Ada 95 by problems, and section 4 presents a brief summary. treating exceptions as (tagged) types, and exception occurrences as their instances. 2 Exceptions in Ada 95 Keywords. Object–Oriented Exception Handling, Soft- ware Fault Tolerance Exceptions in Ada 95 are seen as some kind of “special objects”: even their declaration looks more like that of an object than a type declaration: 1 Introduction Some_Exception : exception; The exception model of Ada 95 [ARM95] is still basi- Such exceptions can be raised (or thrown, as other lan- cally the same as it was in the original Ada 83 program- guages call it) through a raise statement: ming language; although some improvements did occur: raise Some_Exception; the introduction of the concept of exception occurrences, and some other, minor improvements concerning excep- or through a procedure that passes a string message tion names and messages. along with the exception: Exceptions are a very general and powerful tool to Ada.Exceptions.Raise_Exception build reliable applications. They provide a way to sepa- (Some_Exception’Identity, “Text”); rate normal flow of control cleanly from exceptional error handling. This makes a proper separation of con- Any begin–end block can have exception handlers: cerns possible, and helps in properly structuring and begin designing software components. ... Ada 95 is an object–oriented programming language, exception and it has a long success history in the development of when E : Some_Exception => reliable software. The object–oriented features had been Ada.Text_IO.Put_Line integrated rather smoothly into the already strong typing (Ada.Exceptions.Exception_Message(E)); system of Ada 83. It is all the more surprising that when others => exceptions apparently did not get too much attention in -- Whatever... this integration process: they follow a somewhat awk- end; ward model and are completely set apart from the pow- The handler for others catches any exception not erful and clean semantics of other types in the caught by one of the other exception handlers in this programming language. In fact, the programming lan- block. The ‘E’ in the first handler declares an guage doesn’t handle exceptions as types at all. Exception_Occurrence that will hold the caught excep- This may once have been a sensible design decision tion instance and that is needed if the handler needs to under the aspect of not creating too big a gap for the get at the exception message associated with this transition from Ada 83 to the then new language Ada 95. instance. However, I believe the time has come to reconsider these The exception message (and also the exception choices made nearly 10 years ago, especially in view of name) are things added in Ada 95 to rectify deficiencies the experiences made since then in other successful pro- found in Ada 83. But still, limiting the additional infor- mation that may be passed along with an exception to a but it strangely departs from the usual high–level view simple character string is too restrictive. There are many taken in Ada. Working with Exception_Ids in this way cases where one would like to add even more (and typed is reminiscent of working directly with the tags of tagged and structured!) data to an exception, and for such uses, types. the single string, whose length may even be truncated to The usual way to add application–defined arbitrary 200 characters if the exception is re–raised [ARM95, data to an exception (occurrence) relies on a mis–use of §11.4.1(18)], is simply not sufficient. I’ll show one the standard exception message. This method is exem- example in section 2.1 below. plified by the CORBA IDL mapping to Ada 95. Also, Ada 95 has no means to instantiate generics In CORBA IDL, exceptions can carry arbitrary appli- with exceptions: there are no formal generic exceptions. cation–defined attributes. The mapping of IDL to (As there are no generic formal task types, which in Ada 95 must therefore somehow provide a way to add some rare cases also might be convenient.) Generic units additional information to exceptions in Ada 95. This is thus have to raise exceptions declared elsewhere, or to done by defining separate tagged types to hold the declare their own exceptions. In the latter case, excep- exception attributes. When a CORBA exception is raised tions resulting from two different instantiations also are in Ada, the application must not use the raise statement different [ARM95, §11.1(3)], and in the former case, the directly, but first create an object of the appropriate type generic unit (not the place where it is instantiated!) needs in IDL_Exception_Members’Class and then call a spe- to have visibility of the exception declaration. There is a cial primitive operation of this type. This operation first work–around (see section 2.1), but it is somewhat copies the data into some dynamically allocated (or oth- low–level. erwise global) object and then puts some kind of refer- Finally, exceptions in Ada 95 cannot be organized in ence to this object in stringified form into the standard hierarchies. This, too, can be quite useful in many cases. exception message. Then the normal Ada exception cor- Exception hierarchies go together with the ability to han- responding to the CORBA exception is raised with that dle either individual exceptions or a whole (sub–)tree of message. such a hierarchy. This helps insulate users of a software Where a CORBA exception is caught in an exception component against changes in the exception raising handler, the Ada application can retrieve the associated behavior of that component, which is all the more impor- data by calling a special operation that looks at the tant in Ada since exceptions are not part of the interface exception message, extracts the reference from it and of operations. Consider a component that is extended or then returns the object associated with this exception otherwise changed and then either raises a new excep- occurrence. tion it didn’t raise before, or some operations now raise While this works, it makes for a rather heavy inter- different (but already declared) exceptions. Without face that is not particularly convenient to use. Worse yet, exception hierarchies, it would then be necessary to this mechanism relies on the application following an make according changes in the exception handlers of all implicit protocol for treating exceptions, and this proto- other software components using the changed compo- col cannot be enforced. If an application directly raises nent. With hierarchies, this may not always be necessary. an Ada exception that corresponds to a CORBA excep- (It also may still be necessary in some cases, of course.) tion without adding the CORBA data, or if an applica- If a software component structures its exceptions, and in tion changes the exception message of such an particular related ones, in exception hierarchies, users of exception, all bets are off and it is rather unlikely that the the software component have the choice of handling the scheme will continue to work as intended. Such unsafety whole hierarchy instead of individual exceptions. Such is in stark contrast to the rest of the Ada 95 language! hierarchy–wide handlers would not necessarily have to There is no direct work–around known to me for the be adapted in this case. lack of exception hierarchies in Ada 95. (Except the catch–all “when others”, but that should really remain 2.1 Work–Arounds reserved for rare special cases. Generous use of “when others” is in general not a sign of a well For some of the above limitations, there exist thought–through error handling strategy. Also, it indis- work–arounds. Instead of working with generic formal criminately catches any exception and is thus not well exception parameters, which don’t exist in Ada 95, it is suited for dealing with exception hierarchies.) One possible to use a generic formal object of type might attempt to use the above work–around for adding Ada.Exceptions.Exception_Id, which can then be application–defined attributes to an exception occur- used inside the generic unit to raise the designated rence to also encode somehow an attribute that further exception not by a raise statement but through proce- distinguishes between occurrences of a particular excep- dure Ada.Exceptions.Raise_Exception. This works, tion, but any such attempts will be partial and unsafe CORBA IDL also has exceptions that can carry arbitrary solutions only, and rather heavy and inflexible to use. application–defined attributes, although there are no exception hierarchies in IDL. (There are just two broad 2.2 Some History classes of exceptions in IDL: “checked” and “unchecked” exceptions, like in Java — IDL also, like Interestingly enough, the above problems were all well Java, requires operations to declare the exceptions they known at the time the design of Ada 9X began.