13 Supporting mechanisms xcept for onecrucial set of mechanisms,we havewsnthe basic ecof object-oriented software construction.The major missing piece is inheritance and all that goes with it.Before moving to that last component of the approach,we should review a few mechanisms that will be important to the writing of actual systems:external routines and the encapsulation of non-O-O software;argument passing;control structures; expressions;string manipulation;input and output. These are technical aspects,not essential to the understanding of the method;but we will need them for some later examples,and they blend well with the fundamental concepts.So even on your first reading you should spend some time getting at least generally familiar with them. 13.1 INTERFACING WITH NON-O-O SOFTWARE So far,we have expressed software elements entirely in the object-oriented notation.But the software field grew up long before object technology became popular,and you will often need to interface your software with non-O-O elements,written in such languages as C,Fortran or Pascal.The notation should support this process. We will first look at the language mechanism,then reflect on its broader significance as a part of the object-oriented software development process. External routines Our object-oriented systems are made of classes,consisting of features,particularly routines,that contain instructions.What is,among these three,the right level of granularity for integrating external software? The construct must be common to both sides;this excludes classes,which exist only in object-oriented languages.(They may,however,be the right level of integration between two different O-O languages.)Instructions are too low-level;a sequence in which two object-oriented instructions bracket a C instruction: Warning:this style !!x.make (clone (a)) is neither supported (struct A)*x =&y;/A piece of C * nor recommended. For purposes of dis- x.display cussion only. would be very hard to understand,validate and maintain
13 Supporting mechanisms Except for one crucial set of mechanisms, we have now seen the basic techniques of object-oriented software construction. The major missing piece is inheritance and all that goes with it. Before moving to that last component of the approach, we should review a few mechanisms that will be important to the writing of actual systems: external routines and the encapsulation of non-O-O software; argument passing; control structures; expressions; string manipulation; input and output. These are technical aspects, not essential to the understanding of the method; but we will need them for some later examples, and they blend well with the fundamental concepts. So even on your first reading you should spend some time getting at least generally familiar with them. 13.1 INTERFACING WITH NON-O-O SOFTWARE So far, we have expressed software elements entirely in the object-oriented notation. But the software field grew up long before object technology became popular, and you will often need to interface your software with non-O-O elements, written in such languages as C, Fortran or Pascal. The notation should support this process. We will first look at the language mechanism, then reflect on its broader significance as a part of the object-oriented software development process. External routines Our object-oriented systems are made of classes, consisting of features, particularly routines, that contain instructions. What is, among these three, the right level of granularity for integrating external software? The construct must be common to both sides; this excludes classes, which exist only in object-oriented languages. (They may, however, be the right level of integration between two different O-O languages.) Instructions are too low-level; a sequence in which two object-oriented instructions bracket a C instruction: !! x ● make (clone (a)) (struct A) *x = &y; /* A piece of C */ x ● display would be very hard to understand, validate and maintain. Warning: this style is neither supported nor recommended. For purposes of discussion only
440 MORE O-O MECHANISMS $13.1 This leaves the feature level,the right one since encapsulating features is compatible with O-O principles:a class is an implementation of a data type protected by information hiding;features are the unit of interaction of the class with the rest of the software;since clients rely on the features'official specification (the short form)independently of their implementation,it does not matter to the outside world whether a feature is internally written in the object-oriented notation or in another language. Hence the notion of external routine.An external routine will have most of the trappings of a normal routine:name,argument list,result type if it is a function, precondition and postcondition if appropriate.Instead of a do clause it will have an ex ternal clause stating the language used for the implementation.Here is an example, extracted from a class describing character files: put (c:CHARACTER)is --Add c to end of file. require write open:open for write external "Cm alias"char write"; ensure one more:count old count +1 end The alias clause is optional,useful only if the name of the external routine,in its language of origin,is different from the name given in the class.This happens for example when the extemal name would not be legal in the object-oriented notation,as here with a name beginning with an underscore (legal in C). Advanced variants The mechanism just described covers most cases and will suffice for the purposes of this book.In practice some refinements are useful: Some external software elements may be macros rather than routines.They will appear to the O-O world as routines,but any call will be expanded in-line.This may be achieved by varying the language name (as in "C:[macro]..."). It is also necessary to permit calls to routines of"Dynamic Link Libraries"(DLL) available on Windows and other platforms.Instead ofbeing a static part ofthe system, a DLL routine is loaded at run time,on the first call.It is even possible to define the routine and library names at run time.DLL support should include both a way to specify the names statically (as in external "C:[dll]...")and a completely dynamic approach using library classes DYNAMIC LIBRARY and DYNAMIC ROUTINE which you can instantiate at run time,to create objects representing dynamically determined libraries and routines. You may also need communication in the reverse direction,letting non-O-O software create objects and call features on them.For example you may want the callback mechanism of a non-O-O graphical toolkit to call certain class features. All these facilities are present in the O-O environment described in the last chapter. Their detailed presentation,however,falls beyond the scope of this discussion
440 MORE O-O MECHANISMS §13.1 This leaves the feature level, the right one since encapsulating features is compatible with O-O principles: a class is an implementation of a data type protected by information hiding; features are the unit of interaction of the class with the rest of the software; since clients rely on the features’ official specification (the short form) independently of their implementation, it does not matter to the outside world whether a feature is internally written in the object-oriented notation or in another language. Hence the notion of external routine. An external routine will have most of the trappings of a normal routine: name, argument list, result type if it is a function, precondition and postcondition if appropriate. Instead of a do clause it will have an external clause stating the language used for the implementation. Here is an example, extracted from a class describing character files: put (c: CHARACTER) is -- Add c to end of file. require write_open: open_for_write external "C" alias "_char_write"; ensure one_more: count = old count + 1 end The alias clause is optional, useful only if the name of the external routine, in its language of origin, is different from the name given in the class. This happens for example when the external name would not be legal in the object-oriented notation, as here with a name beginning with an underscore (legal in C). Advanced variants The mechanism just described covers most cases and will suffice for the purposes of this book. In practice some refinements are useful: • Some external software elements may be macros rather than routines. They will appear to the O-O world as routines, but any call will be expanded in-line. This may be achieved by varying the language name (as in "C:[macro]… "). • It is also necessary to permit calls to routines of “Dynamic Link Libraries” (DLL) available on Windows and other platforms. Instead of being a static part of the system, a DLL routine is loaded at run time, on the first call. It is even possible to define the routine and library names at run time. DLL support should include both a way to specify the names statically (as in external "C:[dll]…") and a completely dynamic approach using library classes DYNAMIC_LIBRARY and DYNAMIC_ROUTINE which you can instantiate at run time, to create objects representing dynamically determined libraries and routines. • You may also need communication in the reverse direction, letting non-O-O software create objects and call features on them. For example you may want the callback mechanism of a non-O-O graphical toolkit to call certain class features. All these facilities are present in the O-O environment described in the last chapter. Their detailed presentation, however, falls beyond the scope of this discussion
$13.1 INTERFACING WITH NON-O-O SOFTWARE 441 Uses of external routines External routines are an integral part of the method,fulfilling the need to combine old software with new.Any software design method emphasizing reusability must allow accessing code written in other languages.It would be hard to convince potential users that reusability begins this minute and that all existing software must be discarded. Openness to the rest of the world is a requirement for most software.This might be termed the Principle of Modesty:authors of new tools should make sure that users can still access previously available facilities. External routines are also necessary to provide access to machine-dependent or operating system capabilities.The file class is a typical example.Another is class ARRAY, whose interface was presented in earlier chapters but whose implementation will rely on external routines:the creation procedure make use a memory allocation routine,the access function item will use an external mechanism for fast access to array elements,and so on “Polite society”is This technique ensures a clean interface between the object-oriented world and other not classless. approaches.To clients,an external routine is just a routine.In the example,the C routine char write has been elevated to the status of a feature of a class,complete with precondition and postcondition,and the standard name put.So even facilities which internally rely on non-O-O mechanisms get repackaged in data abstractions;the rest ofthe object-oriented software will see them as legitimate members of the group,their lowly origins never to be mentioned in polite society. Object-oriented re-architecturing The notion of external routine fits well with the rest of the approach.The method's core contribution is architectural:object technology tells us how to devise the structure of our systems to ensure extendibility,reliability and reusability.It also tells us how to fill that structure,but what fundamentally determines whether a system is object-oriented is its modular organization.It is often appropriate,then,to use an O-O architecture-what is sometimes called a wrapper-around interal elements that are not all O-O. One extreme but not altogether absurd way to use the notation would rely solely on external routines,written in some other language,for all actual computation.Object technology would then serve as a pure packaging tool,using its powerful encapsulation mechanisms:classes,assertions,information hiding,client,inheritance In general there is no reason to go that far,since the notation is perfectly adequate to express computations of all kinds and execute them as efficiently as older languages such as Fortran or C.But object-oriented encapsulation ofexternal software is useful in several cases.We have seen one of them:providing access to platform-specific operations. Another is to address a problem that faces many organizations:managing so-called legacy sofnware.During the sixties,seventies and eighties,companies have accumulated a legacy
§13.1 INTERFACING WITH NON-O-O SOFTWARE 441 Uses of external routines External routines are an integral part of the method, fulfilling the need to combine old software with new. Any software design method emphasizing reusability must allow accessing code written in other languages. It would be hard to convince potential users that reusability begins this minute and that all existing software must be discarded. Openness to the rest of the world is a requirement for most software. This might be termed the Principle of Modesty: authors of new tools should make sure that users can still access previously available facilities. External routines are also necessary to provide access to machine-dependent or operating system capabilities. The file class is a typical example. Another is class ARRAY, whose interface was presented in earlier chapters but whose implementation will rely on external routines: the creation procedure make use a memory allocation routine, the access function item will use an external mechanism for fast access to array elements, and so on. This technique ensures a clean interface between the object-oriented world and other approaches. To clients, an external routine is just a routine. In the example, the C routine _char_write has been elevated to the status of a feature of a class, complete with precondition and postcondition, and the standard name put. So even facilities which internally rely on non-O-O mechanisms get repackaged in data abstractions; the rest of the object-oriented software will see them as legitimate members of the group, their lowly origins never to be mentioned in polite society. Object-oriented re-architecturing The notion of external routine fits well with the rest of the approach. The method’s core contribution is architectural: object technology tells us how to devise the structure of our systems to ensure extendibility, reliability and reusability. It also tells us how to fill that structure, but what fundamentally determines whether a system is object-oriented is its modular organization. It is often appropriate, then, to use an O-O architecture — what is sometimes called a wrapper — around internal elements that are not all O-O. One extreme but not altogether absurd way to use the notation would rely solely on external routines, written in some other language, for all actual computation. Object technology would then serve as a pure packaging tool, using its powerful encapsulation mechanisms: classes, assertions, information hiding, client, inheritance. In general there is no reason to go that far, since the notation is perfectly adequate to express computations of all kinds and execute them as efficiently as older languages such as Fortran or C. But object-oriented encapsulation of external software is useful in several cases. We have seen one of them: providing access to platform-specific operations. Another is to address a problem that faces many organizations: managing so-called legacy software. During the sixties, seventies and eighties, companies have accumulated a legacy “Polite society” is not classless
442 MORE O-O MECHANISMS $13.1 of Cobol,Fortran,PL/I and C code,which is becoming harder and harder to maintain,and not just because the original developers are gone or going.Object technology offers an opportunity to re-engineer such systems by re-architecturing them,without having to rewrite them completely Think of this process as the reverse of turkey stuffing:instead of keeping the structure and changing the internals,you keep the entrails and replace the skeleton,as if repackaging the content ofa turkey into the bones of a zebra or a mouse.It must be noted, however,that such non-software applications of the idea appear neither useful nor appetizing. This technique,which we may call object-oriented re-architecturing,offers an interesting solution for preserving the value of existing software assets while readying them for future extension and evolution. It will only work,however,under specific conditions: You must be able to identify good abstractions in the existing software.Since you are not dealing with object-oriented software,they will typically be function abstractions,not data abstractions;but that is normal:it is your task to find the underlying data abstractions and repackage the old software's routines into the new software's classes.If you cannot identify proper abstractions already packaged in routines,you are out of luck,and no amount of object-oriented re-architecturing attempts will help. The legacy software must be of good quality.Re-architectured junk is still junk- possibly worse than the original,in fact,as the junkiness will be hidden under more layers of abstraction. These two requirements are partly the same,since quality in software,O-O or not,is largely determined by quality of structure. When they are satisfied,it is possible to use the external mechanism to build some very interesting object-oriented software based on earlier efforts.Here are two examples, both part of the environment described in the last chapter. The Vision library provides portable graphics and user interface mechanisms,On these libraries enabling developers to write graphical applications that will run on many different see“PORTABIL- platforms,with the native look-and-feel,for the price of a recompilation.Internally, ITY AND PLAT- FORM it relies on the native mechanisms,used through external routines.More precisely, ADAPTATION”, its lower level-WEL for Windows,MEL for Motif,PEL for OS/2 Presentation Manager-encapsulates the mechanisms of the corresponding platforms.WEL, MEL,PEL and consorts are also usable directly,providing developers who do not care about portability with object-oriented encapsulations of the Windows,Motif and Presentation Manager Application Programming Interfaces. Another library,Math,provides an extensive set of facilities for numerical computation in such areas as probability,statistics,numerical integration,linear and non-linear equations,ordinary differential equations,eigenproblems,fitting and interpolation,orthogonal factorizations,linear least squares,optimization
442 MORE O-O MECHANISMS §13.1 of Cobol, Fortran, PL/I and C code, which is becoming harder and harder to maintain, and not just because the original developers are gone or going. Object technology offers an opportunity to re-engineer such systems by re-architecturing them, without having to rewrite them completely. Think of this process as the reverse of turkey stuffing: instead of keeping the structure and changing the internals, you keep the entrails and replace the skeleton, as if repackaging the content of a turkey into the bones of a zebra or a mouse. It must be noted, however, that such non-software applications of the idea appear neither useful nor appetizing. This technique, which we may call object-oriented re-architecturing, offers an interesting solution for preserving the value of existing software assets while readying them for future extension and evolution. It will only work, however, under specific conditions: • You must be able to identify good abstractions in the existing software. Since you are not dealing with object-oriented software, they will typically be function abstractions, not data abstractions; but that is normal: it is your task to find the underlying data abstractions and repackage the old software’s routines into the new software’s classes. If you cannot identify proper abstractions already packaged in routines, you are out of luck, and no amount of object-oriented re-architecturing attempts will help. • The legacy software must be of good quality. Re-architectured junk is still junk — possibly worse than the original, in fact, as the junkiness will be hidden under more layers of abstraction. These two requirements are partly the same, since quality in software, O-O or not, is largely determined by quality of structure. When they are satisfied, it is possible to use the external mechanism to build some very interesting object-oriented software based on earlier efforts. Here are two examples, both part of the environment described in the last chapter. • The Vision library provides portable graphics and user interface mechanisms, enabling developers to write graphical applications that will run on many different platforms, with the native look-and-feel, for the price of a recompilation. Internally, it relies on the native mechanisms, used through external routines. More precisely, its lower level — WEL for Windows, MEL for Motif, PEL for OS/2 Presentation Manager — encapsulates the mechanisms of the corresponding platforms. WEL, MEL, PEL and consorts are also usable directly, providing developers who do not care about portability with object-oriented encapsulations of the Windows, Motif and Presentation Manager Application Programming Interfaces. • Another library, Math, provides an extensive set of facilities for numerical computation in such areas as probability, statistics, numerical integration, linear and non-linear equations, ordinary differential equations, eigenproblems, fitting and interpolation, orthogonal factorizations, linear least squares, optimization, On these libraries see “PORTABILITY AND PLATFORM ADAPTATION
$13.1 INTERFACING WITH NON-O-O SOFTWARE 443 special functions,Fast Fourier Transforms and time series analysis.Internally,it is based on a commercial subroutine library,the NAG library from Nag Ltd.of Oxford,but it provides a completely object-oriented interface to its users.The library hides the underlying routines and instead is organized around such abstract concepts as integrator,matrix,discrete function,exponential distribution and many others;each describes "objects"readily understandable to a mathematician. physicist or economist,and is represented in the library by a class:INTEGRATOR, BASIC MATRIX,DISCRETE FUNCTION,EXPONENTIAL DISTRIBUTION.The result builds on the quality of the external routines-NAG is the product of hundreds of person-years of devising and implementing numerical algorithms- and adds the benefits of O-0 ideas:classes,information hiding,multiple inheritance,assertions,systematic error handling through exceptions,simple routines with short argument lists,consistent naming conventions. These examples are typical of how one can combine the best of traditional software and object technology. The compatibility issue:hybrid software or hybrid languages? Few people would theoretically disagree with the principle of modesty and deny the need for some integration mechanism between O-O developments and older software.The matter becomes more controversial when it comes to deciding on the level of integration. See chapter 35. A whole set of languages-the best known are Objective-C,C++,Java,Object Pascal and Ada 95-have taken the approach of adding O-O constructs to an existing non-O-O language(respectively C in the first three cases,Pascal and Ada).Known as hybrid languages,they are discussed in varying degree of detail in a later chapter. The integration technique described above,rely ing on external routines and object- oriented re-architecturing,follows from a different principle:that the need for sofiware compatibility does not mean that we should burden the language with mechanisms that may be at odds with the principles of object technology.In particular: A hybrid adds a new language level to the weight of an existing language such as C. The result can be quite complex,limiting one of the principal attractions of object technology-the essential simplicity of the ideas. Beginners as a result often have trouble mastering a hybrid language,since they do not clearly see what is truly O-O and what comes from the legacy. Some of the older mechanisms may be incompatible with at least some aspects of object-oriented ideas.We have seen how the type concepts inherited from C make it hard to equip C++environments with garbage collection,even though automatic memory management is part of the appeal of object technology.There are many other examples of clashes between the C or Pascal type system and the O-O view
§13.1 INTERFACING WITH NON-O-O SOFTWARE 443 special functions, Fast Fourier Transforms and time series analysis. Internally, it is based on a commercial subroutine library, the NAG library from Nag Ltd. of Oxford, but it provides a completely object-oriented interface to its users. The library hides the underlying routines and instead is organized around such abstract concepts as integrator, matrix, discrete function, exponential distribution and many others; each describes “objects” readily understandable to a mathematician, physicist or economist, and is represented in the library by a class: INTEGRATOR, BASIC_MATRIX, DISCRETE_FUNCTION, EXPONENTIAL_DISTRIBUTION. The result builds on the quality of the external routines — NAG is the product of hundreds of person-years of devising and implementing numerical algorithms — and adds the benefits of O-O ideas: classes, information hiding, multiple inheritance, assertions, systematic error handling through exceptions, simple routines with short argument lists, consistent naming conventions. These examples are typical of how one can combine the best of traditional software and object technology. The compatibility issue: hybrid software or hybrid languages? Few people would theoretically disagree with the principle of modesty and deny the need for some integration mechanism between O-O developments and older software. The matter becomes more controversial when it comes to deciding on the level of integration. A whole set of languages — the best known are Objective-C, C++, Java, Object Pascal and Ada 95 — have taken the approach of adding O-O constructs to an existing non-O-O language (respectively C in the first three cases, Pascal and Ada). Known as hybrid languages, they are discussed in varying degree of detail in a later chapter. The integration technique described above, relying on external routines and objectoriented re-architecturing, follows from a different principle: that the need for software compatibility does not mean that we should burden the language with mechanisms that may be at odds with the principles of object technology. In particular: • A hybrid adds a new language level to the weight of an existing language such as C. The result can be quite complex, limiting one of the principal attractions of object technology — the essential simplicity of the ideas. • Beginners as a result often have trouble mastering a hybrid language, since they do not clearly see what is truly O-O and what comes from the legacy. • Some of the older mechanisms may be incompatible with at least some aspects of object-oriented ideas. We have seen how the type concepts inherited from C make it hard to equip C++ environments with garbage collection, even though automatic memory management is part of the appeal of object technology. There are many other examples of clashes between the C or Pascal type system and the O-O view. See chapter 35