Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!gatech!mcnc!ece-csc!ncrcae!hubcap!billwolf%hazel.cs.clemson.edu From: billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu (William Thomas Wolfe,2847,) Newsgroups: comp.sw.components Subject: Re: using components Message-ID: <5490@hubcap.clemson.edu> Date: 15 May 89 21:13:45 GMT References: <11401@bloom-beacon.MIT.EDU> Sender: news@hubcap.clemson.edu Reply-To: billwolf%hazel.cs.clemson.edu@hubcap.clemson.edu Lines: 108 From tada@athena.mit.edu (Michael Zehr): > There have been a couple of good comments about using software > components, but so far most of them have been along the lines of > "such-and-such a language does this." Could you describe > *how* the language provides both efficiency and quick building time? > > For example, one person mentioned Ada's "re-binding" of > executables. What does this do? Briefly, Ada provides a number of excellent facilities for partitioning a problem into modular subsystems, in order to facilitate the construction of the subunits in an independent manner. One such facility is known as "separate compilation", whereby first the interface to a procedure or function is described: procedure Handle_This_Task (With_Parameter : in out Parameter_Type) is separate; Now we can compile the code which contains this specification without ever actually implementing the Handle_This_Task procedure. Eventually, before we bind everything into an executable, a procedure must actually be coded to satisfy this specification, but we can defer it until the rest of the code has been written and debugged. Moreover, if we wish to change something in that procedure's code, we can change and recompile only that procedure, without having to recompile the entire system. Another mechanism is the "package". One use of packages is to describe specifications (*compilable* specifications) for subsystems which collectively interact to form a larger system. Once the high-level specifications have been compiled together, the information flows across the subsystem interfaces have been verified for completeness and consistency. The project can then be "farmed out" to individual programmers, who will implement each subsystem independently of what everyone else is doing. The package specification forms a contract between the implementor and the other project members; if everyone fulfulls their end of the deal, then the entire system is guaranteed to work as far as information flows are concerned. The implementor constructs a package body, which is said to be "compiled against" the package specification, or "spec". So everyone goes about their business, implementing and testing their individual subsystems, (testing of subsystems can be accomplished by first developing them in temporary isolation from the system, and later compiling them against the system specs) and finally when everyone is done, the compiled units are *bound* together into an executable for integrated testing. Now suppose that a problem is found in one subsystem. That problem is corrected, and only that subsystem (and possibly only a small portion of that subsystem, if the subsystem has been internally partitioned as well) will require recompilation. Once the affected area of the system is recompiled, then the system is bound once again into a new executable for further testing. The technical mechanism by which this is accomplished is known as the "library" system; each program is a member of some program library or sublibrary, and when a program (or "program unit", or "unit") is compiled into a library, the library stores some intermediate form(s) of the program. Upon recompilation, the library simply updates its intermediate form(s). If there is an optimization flag turned on, then the library stores special information which will be used by the optimizer during the binding phase. Now when binding occurs, the binder scans through the libraries for the desired program units, and binds them together into a piece of executable code, perhaps exploiting the knowledge accumulated during the compilation phase in order to optimize the executable code. Although packages present boundaries to the programmer, an optimizer can corrupt any and all boundaries in pursuit of a more efficient executable, if global optimization is desired. Normally the work of optimization is not done until very near the end, during or after execution profiling. The library system is also important in that it permits the reuse of code (a software component needs to be compiled into only one library, and many other users can then make use of it); it also facilitates the tracking of the impact of a modification, in that a change in the specification of a component which is used by other users will require the recompilation of the relevant areas of code which made use of the modified unit. This enables the rapid identification of the impact of the modification, and allows the tracking of change as it spreads throughout the system. There is an automatic recompilation facility which can be used to automatically recompile all dependent units if it is known that the change will not require changes to the dependent units; automatic recompilation will also identify (in the form of compilation errors) specific places in which the modified specification impacts the dependent units (e.g., a dependent unit's attempt to call a procedure which was just removed from the specification). > Someone also mentioned being able to reuse components in different > languages. I agree that this is crucial in combining efficiency with > productivity. So far, my experience with mixed-language coding is > that it is very easy on Vaxes (becuase of the forced procedure > interface of the CALLS instruction) but extremely difficult on IBM > mainframes (because there is no standard calling sequence). Does > anyone have any experience in mixed-language coding on newer RISC > machines? Do compiler witers stick to "standardized" calling > mechanisms? Ada makes direct provision for interfacing to other languages; the only implementation dependencies are whether or not the compiler you are using supports calls to that particular language. Typically, compilers support calls to at least several other languages, and the means of use is via the standardized interfacing mechanism defined by the Ada programming language. Special provision is also made for machine code insertions; as with interfacing to other languages, there is direct support for machine code insertion in the Ada language, and the only question is whether the particular compiler you are using provides the service. Although the compilers are not required to provide machine code insertion either, many if not most of them do so. Bill Wolfe, wtwolfe@hubcap.clemson.edu