Welcome to Academia

Sign up to get access to over 50 million papers

By continuing, you agree to our Terms of Use

Continue with Email

Sign up or log in to continue.

Welcome to Academia

Sign up to continue.

Hi,

Log in to continue.

Reset password

Password reset

Check your email for your reset link.

Your link was sent to

Please hold while we log you in

Academia.eduAcademia.edu

Three Concepts of System Architecture

1995

descriptionSee full PDF

Abstract

An architecture is a speci cation of the components of a system and the communication between them. Systems are constrained to conform to an architecture. An architecture should guarantee certain behavioral properties of a conforming system, i.e., one whose components are con gured according to the architecture. An architecture should also be useful in various ways during the process of building a system. This paper presents three alternative concepts of architecture: object connection architecture, interface c onnection architecture, and plug and socket architecture. W e describe di erent concepts of interface and connection that are needed for each of the three kinds of architecture, and di erent conformance requirements of each kind. Simple examples are used to compare the usefulness of each kind of architecture in guaranteeing properties of conforming systems, and in correctly modifying a conforming system. In comparing the three architecture concepts the principle of communication integrity becomes central, and two new architecture concepts, duality of sub-interfaces services and connections of dual services service c onnection, are introduced to de ne plug and socket architecture. We describe how these concepts reduce the complexity o f a r c hitecture de nitions, and can in many cases help guarantee that the components of a conforming system communicate correctly. The paper is presented independently of any particular formalism, since the concepts can be represented in widely di ering architecture de nition formalisms, varying from graphical languages to event-based simulation languages.

Three Concepts of System Architecture David C. Luckham Abstract James Vera July 19, 1995 Sigurd Meldal  Abstract An architecture is a speci cation of the components of a system and the communication between them. Systems are constrained to conform to an architecture. An architecture should guarantee certain behavioral properties of a conforming system, i.e., one whose components are con gured according to the architecture. An architecture should also be useful in various ways during the process of building a system. This paper presents three alternative concepts of architecture: object connection architecture, interface connection architecture, and plug and socket architecture. We describe di erent concepts of interface and connection that are needed for each of the three kinds of architecture, and di erent conformance requirements of each kind. Simple examples are used to compare the usefulness of each kind of architecture in guaranteeing properties of conforming systems, and in correctly modifying a conforming system. In comparing the three architecture concepts the principle of communication integrity becomes central, and two new architecture concepts, duality of sub-interfaces (services ) and connections of dual services (service connection), are introduced to de ne plug and socket architecture. We describe how these concepts reduce the complexity of architecture de nitions, and can in many cases help guarantee that the components of a conforming system communicate correctly. The paper is presented independently of any particular formalism, since the concepts can be represented in widely di ering architecture de nition formalisms, varying from graphical languages to event-based simulation languages. 1 Introduction In recent years object-oriented techniques have caused a paradigm shift in systems development. As a result, we have become much more ecient at building objects | the components of systems. So much so, in fact, that in just ten years since Ada83 [15] was rst adopted as the DoD standard programming language, it was deemed necessary to undertake a large redesign (Ada9X [7]) to incorporate OO technology. However, while object-oriented techniques have made us better at building components, they do not solve the conspicuous problem of combining components into complete systems. Indeed large scale software systems continue to be plagued with a variety of development problems which have been amply discussed in the literature (see, e.g., [5]). There is now a widespread belief that software engineering must go beyond object oriented methods to a new technology based upon \architecture". Unfortunately, it is fair to say that the concept of architecture, although widely used, has no generally accepted precise de nition. Often the term has little meaning other than a graphical diagram consisting of boxes and arrows that serves as a pictorial table of contents for detailed design and code documents. The most common answer given to the question \what is architecture?" is \interfaces and connections". This is not a bad answer, but the devil is in the details of what the properties of \interfaces" and \connections" are, how they are related to the system, and what use can be made of them.  This project is funded by DARPA under ONR contract N00014-92-J-1928 and AFOSR under Grant AFOSR91-0354 1 The general expectation is that an architecture speci es the modules (or objects) of a system (called the components of the system), and how the components interact so as to satisfy the requirements of the system. However, most people go beyond this de nitional goal to postulate that architectures are also useful in building or managing a system. So there is also an expectation that an architecture should be a template for guiding the development of a system (or family of systems) to satisfy a given set of behavioral requirements. As a template, an architecture de nes constraints on a system. A system \has" that architecture if it conforms to those constraints (in a sense to be de ned), and if it does, then it meets the given requirements. How an architecture can be used to develop systems depends upon (i) the kind of information it provides about a system, (ii) a precise de nition of the conformance relationship between architecture and system, and (iii) the kinds of automated tools that can be constructed to support the use of architecture. For example, an architecture could contain enough information to allow simulation to assess system behavior and performance before the system is built. It could de ne behavioral constraints that allow formal reasoning to establish that a system conforming to that architecture will satisfy the system's requirements. Or it might contain information that allows changes to a system to be made, so as to maintain required behavior, on the basis of analyzing the architecture alone. Certainly, as a minimal expectation, an architecture should guarantee important properties of a system that is built to conform to it. Conformance should be testable at every stage in system development. Given the range of possible roles of architecture in building systems, the primary issue is to clarify the concept itself. We should be able to give some answers to the following questions:  does every system have an architecture?  what is an architecture | how does it di er from a system?  how does an architecture constrain the system?  how can an architecture be used to build or modify systems?  how should architecture de nition languages (abbrev. ADLs) di er from programming languages? In this paper an architecture is assumed to be a speci cation of a class of systems at some level of abstraction. An architecture consists of interfaces, connections, and constraints. The interfaces specify the components of the system, and the connections and constraints de ne how the components may interact. The main relationship between an architecture and a system is conformance. Conformance de nes when a system has (or conforms to) an architecture. For our discussion it is not important whether an architecture is an actual part of a system, as it is in some views, or whether it is totally separate from a system, such as a diagram on paper. We present three concepts of architecture: (i) object connection architecture, (ii) interface connection architecture, and (iii) plug and socket architecture. The rst kind of architecture is typical of objectoriented systems in the current O-O programming languages. It is probably what most people who answer \yes" to the rst question above have in mind. The second kind is typical of systems (whether object-oriented or not) that are developed from architectural plans, such as communication protocols and hardware. The third kind of architecture is typical of hardware, but we shall argue it should be used to plan many software systems. The rst two concepts of architecture di er in how they constrain a system that conforms to that architecture, how they facilitate the construction of a system, and the properties they can guarantee that conforming systems will possess. Plug and socket architectures are a specialization of interface connection architectures to deal with issues of (i) scalability (i.e., de ning large architectures), and (ii) guaranteeing properties of conforming systems by simple tests on the architecture only. Our three de nitions of architecture require progressively more sophisticated interfaces and connections. We show how the object-oriented concept of interface is used in architectures of the rst kind, but needs to be extended with new kinds of features for the second kind, and organized into groups of features (\plugs" and \sockets") for the third kind. We describe how the concept of connection also changes. The new kinds of interfaces and connections lead us to suggest, in general terms, some new features for ADLs. These three concepts of architecture are not restricted in any sense to being static. The number of interfaces is not bounded a priori, and connection de nitions are not restricted to de ning interactions between nite sets of components. 2 We de ne three basic conformance criteria : 1. decomposition : for each interface in the architecture there should be a unique module corresponding to it in the system (i.e., the component implementing that interface). 1 2. interface conformance: each component in the system must conform to its interface. We assume that behavioral constraints can be part of interfaces, so this constraint is, in general, stronger than the syntactic interface conformance usually required by programming languages. 3. communication integrity: the system's components interact only as speci ed by the architecture. We use two common system maintenance tasks to illustrate how interface connection architectures are more useful than object connection architectures for manipulating conforming systems. This discussion leads us to formulate properties that interface connection architectures should possess in order to guarantee that systems conforming to them will also possess required properties: ideal interfaces, connectability of interfaces, and correct connections. However, determining if an architecture possesses these properties, and also determining if an arbitrary system conforms to an architecture, are often dicult problems, and in the general case, undecidable. Moreover, we discuss how interface communication architectures can inherit the complexity of the communication structure in a system. These considerations motivate a search for new concepts of architecture in which some of these problems are easier to solve. Plug and socket architectures are a specialization of interface connection architectures to deal with issues of (i) scalability (i.e., de ning large architectures), (ii) re nement (i.e. the process of de ning an architecture), and (iii) guaranteeing properties of conforming systems by simple tests on the architecture (rather than the systems as implemented). We show how the interface concept as used in interface connection architectures should be extended with a new ADL concept of duality of features. This allows interfaces to be organized into \dual" groups of features (\plugs" and \sockets") to enable the de nition of plug and socket architectures. Finally we note that recent work has attempted to de ne popular categories of architectures ( e.g., client-server, pipe-and- lter, etc., see [4]). These categories depend upon the roles and properties of various components of the architecture. Here we are concerned with de ning concepts of architecture that apply to any category. 2 Some Terminology To discuss concepts of architecture we need a small amount of terminology. The following concepts are explained in general terms so as not to imply any particular language or semantics; di erent languages, (e.g., C++ [3], VHDL[6], Ada [15], Rapide [10], [9]) de ne these concepts using their own semantics. Also, to keep our discussion independent of any language, examples are given using a syntax that is easily understood by anyone familiar with C++, VHDL, or Ada. feature = a computational element of a module, e.g., a function or port or action. uses = makes use of a feature, e.g, function call, send message to a port. speci cation = a set of constraints expressed in a formal language. interface = a de nition of a set of features, e.g., public part of a C++ class, or together with a speci cation an Ada package speci cation of their behavior. module = a computational entity containing e.g., an Ada package body. the set of features de ned in an interface; modules may compute independently of, or concurrently with, one another. conformance = a module conforms to an interface if it contains the features speci ed by the 1 More sophisticated decomposition criteria, such as requiring an abstraction mapping from sets of system components to interfaces in the architecture, are beyond the scope of this presentation. 3 interface so that they have the behavior speci ed by the interface; this is called interface conformance. object connection = a relation between modules e.g., one module uses a implying interaction, feature of another module. architecture = a de nition of a set of modules and the interactions between them, by means of interfaces, connections, and constraints. component = a module corresponding to an interface in an architecture. 3 Object Connection Architectures An object-oriented interface speci es the features that must be provided by modules conforming to the interface. Typically, a feature is a function, an interface speci es the name and signature of the function, and a module contains an implementation of a function with that name and signature. Examples are C++ classes, Ada package speci cations, and VHDL entity interfaces.2 An object-oriented system consists of (i) object-oriented interfaces, (ii) a set of modules, each conforming to an interface by providing an implementation of the features speci ed in that interface, and (iii) connections de ned by the uses each module makes of the features speci ed in the interfaces of other modules. An object connection architecture consists of the interfaces and connections of a system. An object connection architecture is depicted in Figure 1. In this gure, interfaces are shaded \lids" of the boxes, and the boxes represent modules that conform to the \lids"; connections are shown as directed arcs from a module to a feature in an interface of another module. The direction of a connection indicates which interface speci es a feature being used; the dotted arrows indicate the association between an interface feature and its implementation in a module (often simply association by name). Figure 1 could represent a C++ program, for example, in which features are functions, interfaces are classes (public parts), and connections are function calls. The architecture in Figure 1 is called an object connection architecture because the connections are from object to object. It is, in fact, part of the system. It has the major disadvantage that the modules must be built before the architecture is de ned, so it cannot be used to plan the system. It is, however, a very common (mis)conception of \architecture". Conformance to an object connection architecture is usually enforced by the language in which the system is programmed. For example, decomposition is satis ed in most programming languages by rules for associating an interfaces with a unique module; similarly, communication integrity is enforced by the rules of visibility between modules. Interface conformance is the only non-trivial constraint which is usually only partially checked by compiletime checking of syntactic rules; conformance to semantic constraints is not guaranteed. Example To illustrate how the ease or diculty of determining properties of a system depend upon the kind of architecture the system has, we take the well-known paradigm example of a compiler. Our simple compiler has the architecture shown in Figure 1. It consists of three modules, a Parser, a Semanticizer and a Code Generator. Its interfaces are shown in Figure 2. The interfaces consist of only a subset of the features a \real" compiler implementation might have, but suce to illustrate how the kind of architecture impacts on commonly practiced modi cations to the system. What kinds of uses might we want to make of our architecture? Problem 1: Determine which modules are a ected by a change to an interface. For example we might wish to remove the function Incremental Semantize from the Semanticizer interface. To determine the e ects of this change we must determine which modules are connected to 2 These examples of interfaces di er in some respects, e.g., packages and entities are not types in Ada or VHDL; but each allows the interface features of a module to be visible outside the module, and permits the module to encapsulate or hide other features from outside use. 4 Parser uses Interface feature module Code Generator Semanticizer Figure 1: An object connection architecture. Incremental Semantize. To do this we need to examine each of the modules to see if any of them uses this function. So, we must examine all modules in the system.3 Problem 2: Determine whether we can replace a module by another one that conforms to the same interface. Imagine then that we want to change our compiler by substituting a new module for the Code Generator interface instance G. It conforms to the Code Generator interface just as the module it replaced did. Object-oriented subtyping such as in C++ allows this kind of change. But does the changed system have the same functional behavior? From Figure 1 we see that the original Code Generator module made a call to the Initialize function of the Parser. The new Code Generator module is not required by its interface to make this call and thus might not. The failure to call the Initialize function would likely result in the misbehavior of the Parser and the failure of the entire system. So even interchanging modules that conform to the same interface may have disastrous e ects. 2 3 This issue is distinct from that addressed by the with clauses of Ada programs. The Ada with clause indicates possible compilation unit dependencies for separate compilation. 5 class Parser is function Initialize(); function FileName() return String; end Parser; class Semanticizer is function Semantize(Tree); function Incremental_Semantize(Context :Tree, Addition : Tree); end Semanticizer; class Code_Generator is function Generate(Tree); end Code_Generator; P: Parser; S: Semanticizer; G: Code_Generator; Figure 2: Compiler module interfaces and instances. This example illustrates that we cannot rely only upon the object connection architecture of a system to determine the e ects on the system of changing an interface or interchanging modules that conform to an interface | two relatively simple and desirable uses of architecture. 4 Interfaces for Architecture Ideally, an interface should ensure substitutivity of modules that conform to it. The ideal interface principle: ( )  ( ) , 8 ( ) jxy  which we read as \If the interface of module x is the same as the interface of module y, then for any program P which contains module x and can be shown to behave in some required manner on the basis of the information in the interface alone, then module y could be substituted for x and the resulting program would satisfy the same behavioral requirements."4 This principle could be generalized further to encompass subtyping: I x I y P x ;P P The ideal subtyping principle: ( ) : ( ) ) 8 ( ) jxy  As the previous example shows, the use of an interface feature, such as whether it is called, can be crucial in interchanging modules for the same interface. To specify such use, the interface must contain speci cations of the semantics of its features. Thus, the ideal interface principle, requires that an interface must contain speci cations of the semantics of its features and not just signature information. Unfortunately, it is an undecidable problem whether a module conforms to a semantic speci cation given a suciently powerful speci cation language. But even if conformance with speci cations of provided features was decidable, object-oriented interfaces cannot satisfy the ideal principles. Part of the failing of object-oriented interfaces is that they specify only the features provided by modules. Connections cannot be de ned in terms of interfaces. This forces architecture connections to be object to object. Consequently, when objects implementing the same interface are interchanged, the connections may change. Therefore, the concept of interface in ADLs should de ne also those features that modules require from their environment. ADL interfaces should specify ve characteristics: 1. A list of the features provided by the module, 2. A list of the features required by the module, 3. A speci cation of the behavior of the provided features, I y 4 < I x P x ;P P I. e., the behavior of the new program satis es the requirements that were satis ed by the previous program. 6 4. A speci cation of the behavior of the required features. 5. A speci cation of the mutual interaction between two or more features (e.g., the use of one feature changes the behavior of other features). By specifying all of the required features used by a module, an ADL interface explicitly expresses the dependencies a conforming module has on its environment. We say the interface is contextualized . Speci cation of interactions between features adds additional constraints on how a module depends upon context; e.g., the Parser interface in Figure 2 could specify that Initialize must be called before calls to FileName will return values. Object-oriented interfaces such as in C++ have traditionally only contained characteristic 1, with characteristics 2, 3, 4 and 5 left to informal comments or buried in the implementation of the interface. As a result, the object-oriented notion of subtyping (substitutability) is based only on characteristic 1. This is probably due in part to the in uence of the original Simula Class design [11], but also due to an emphasis on the design of the interfaces to support information hiding [12]. We argue that in leaving out the features a module requires, object-oriented interfaces have hidden too much to be useful for architecture de nition, as illustrated by the previous example. Interfaces that speci ed both provided and required features were part of the Euclid language design in the 1970's [8]. The motivation of Euclid was to support abstract data types and program veri cation [2]. Our motivation here is to support de nition of architectures that can be used to plan and guide system development. 5 Interface Connection Architectures An interface connection architecture de nes all connections between the modules of a system using only the interfaces. Interfaces specify both provided and required features. Such an architecture, and a system conforming to it, is shown in Figure 3. Connections are de ned between a required feature and a provided feature. A connection from a using module to an interface feature of a providing module in Figure 1 is represented in Figure 3 as an arc from a required feature speci ed in the interface of a user to a provided feature speci ed in the interface of a provider. Thus all of the connections between objects in the object connection architecture are de ned as connections between interface features in the interface connection architecture. This is possible because ADL interfaces specify required features. Two new ADL mechanisms are needed to de ne connections in interface connection architectures that are not available in present-day programming languages such as C++ or Ada :5  A mechanism to de ne connections between required features of one interface with provided features another interface. Connections could be as trivial as identifying pairs of names in interfaces (having a semantics similar to pin connections in hardware modeling languages), or as powerful as the pattern triggered reactive rules of Rapide [10]. In examples we assume that some sort of featureto-feature identi cation is used, shown in Figure 4 as \connect : : : ".  A mechanism to allow a module to \use" the required features of its own interface. This is shown in Figure 3 by dashed arrows between the modules and their interfaces. An example of this mechanism could be function call, but now the only way a module can invoke non-local functions is through its own interface. The architecture must then connect the module's interface functions with interface functions of other modules. The semantics of connection changes from that used in object connection architectures: interface connection = an association between a required interface feature, f , and a provided interface feature, f , such that any use of f is replaced by a use of f . E. g., calls to function f become calls to f . 5 Simulation languages such as Verilog and VHDL do contain rudimentary forms of such features. 7 Parser provides requires Code Generator Semanticizer Figure 3: An interface connection architecture and system. An interface connection architecture constrains the modules of a system to satisfy the three conformance criteria (Section 1). In particular, ensuring communication integrity is no longer trivial. If communication integrity is not ensured, the ability to manipulate the system using only information in its architecture, as illustrated below, will be lost. Examples Our compiler example might be rewritten with contextualized modules as shown in Figure 4. We write \provides" and \requires" to separate the provided and required features. We also use a simple syntax to connect required features to provided features. The interface connection architecture of our new compiler system is depicted in Figure 3. The modules no longer use features of other modules directly. Instead the interfaces specify exactly the features provided and required by each module. The compiler should function exactly as before, but now the connections between the modules are expressed in the interface connection architecture before the modules are built. Also, since required features are speci ed, formal speci cations in interfaces can 8 class Parser is provides: function Initialize(); function FileName() return String; requires function Semantize(Tree); function Generate(Tree); specification ... end Parser; class Semanticizer is provides: function Semantize(Tree); function Incremental_Semantize(Context : Tree; Addition : Tree); requires: function FileName() return String; specification ... end Semanticizer; class Code_Generator is provides: function Generate(Tree); requires: function Initialize_Parser(); function Semantize(Context : Tree; Addition : Tree); specification ... end Code_Generator; P: Parser; S: Semanticizer; G: Code_Generator Connect P.Semantize to S.Semantize; P.Generate to G.Generate; S.FileName to P.FileName; G.Initialize_Parser to P.Initialize; G.Semantize to S.Incremental_Semantize; Figure 4: An interface connection architecture for a compiler specify relationships between the provided and required features as well as properties of each feature individually. This allows more powerful speci cations in interfaces than before, so we have indicated interface speci cations in Figure 4 by including a \speci cation" part of the interface de nition. The interface connection architecture can be used to analyze the two problems we raised previously. How dicult are our two problems now? Problem 1: We can determine potential users of a provided feature in an interface simply by inspecting the architecture connections. Interfaces whose required features are connected to the provided feature are interfaces of modules that are potential users. So connections are used to bound the search. For example to determine the users of function Semantize provided by the Semanticizer S, we check if there is a connection from a required function of either the Parser or Code Generator. Note that a connection from either of the required functions, Semantize in the Parser P or Code Generator G, would satisfy the function subtyping constraint (below) that is a necessary condition for correctness 9 of connections { a call to either of these would supply the Tree parameter needed for the successful evalutation of the provided function in the Semanticizer; however, a connection from, say the required function Initialize Parser in G, could not be correct because that function is not a supertype of the provided function. To determine if a potential user actually uses an interface feature we would need to analyze specications in the interface of the user | and assume that modules satisfy the semantic speci cations in their interfaces. In an object connection architecture we have to inspect all modules to nd potential users, even if interfaces contained speci cations because they could only identify the provided features. Then we have to analyze those modules to see what use they make of the feature. Problem 2: Assuming that the compiler's modules satisfy the communication integrity constraint, we can interchange any two modules that conform to an interface. This will result in a system that behaves exactly as the previous one whenever that behavior is logically implied by the speci cations in the interfaces and the connections. So, we are assuming that the modules satisfy their interface speci cations, and, given a particular desired behavior, that the interface speci cations together with the connections, imply that behavior. For example, we want to replace the Code Generator module as before, and we are concerned about its e ect on initializing the Parser. The code generator's interface has a required function, Initialize Parser, that is the same type as the provided function, Initialize , in the Parser interface. A correct connection between those two functions is consequently possible. If such a connection does not exist, then neither the old nor new Code Generator module can initialize the Parser (by communication integrity), so the system must function correctly without initializing the Parser. If there is such a connection, then we inspect the speci cations in the Code Generator interface. If they imply that a call must or must not be made, then both the new and the old modules are obliged to satisfy the constraint { and we can be sure that the Parser initialization requirement is not violated when the exchange occurs. If there is no constraint about calling Initialize then we assume that the system will function correctly in either case. 2 This example illustrates a general approach to our two common problems: they can be resolved in systems with interface connection architectures by analysis of only the interfaces and connections. Therefore, we argue, these problems are easier to solve in systems with interface connection architectures than object connection architectures. But our solutions only work if we assume that (i) modules conform to interfaces, (ii) the system's behavior that we want to preserve is implied by the constraints on the interfaces and connections of the architecture, and (iii) modules obey communication integrity. Although these assumptions can be checked in many cases, there is no general algorithm for doing so. 6 Satisfying Communication Integrity Communication integrity implies that all communication between components of a system is speci ed by the connections of the interface connection architecture. This is a powerful constraint on the implementation of a system. Note, however, that only communication between components is constrained. For example, a component could directly call a data structure say, an arithmetic module, that was not a component (i.e., did not correspond to an interface of the architecture) provided this data structure is not used to communicate with another component. There are many approaches to ensuring that a system maintains the communication integrity of its interface connection architecture. These can involve language restrictions, or various \sucient" programming style rules. We discuss some approaches brie y here. Strict Interface Visibility: A component of a system is allowed to interact with other components only by using its own interface features. This restriction guards against object connections being programmed between components where there is no connection between those components in the architecture. If the system is programmed in 10 C++, for example, the normal visibility rules of C++ would have to be restricted where they applied to system components. An object that is a component could only access functions of another component by calling functions in its own class interface. C++ classes would need to be extended to declare required functions. 6 If the features of a module are used by two or more components of a system, or the module (or an access to it) is passed as a parameter of communication between components, then we say that the module is shared between the components. If a module is shared by components it should have a safe interface : safe interface = an interface with constraints requiring that the use of a feature does not in uence the behavior of future uses of that or other features of the interface. A safe module has no state whereby results of using its features can be in uenced by prior uses. Examples of safe modules are stateless packages such as an arithmetic module, and modules implemented in the function-oriented programming style. Safe Sharing: A module is safely shared between components of a system if either it is a component and those components are all connected to it, or the module is safe. This restriction attempts to guard against a module being used to establish communication paths that are not de ned in the interface connection architecture. Unspeci ed communication could take place either by components directly using features of a module, or by passing a module (or pointers or access rights to it) to one another. A module conforming to a safe interface may be shared between components without being represented in the architecture. When an interface is not safe it is called a communication interface: communication interface = an interface allowing the use of a feature to in uence the behavior of future uses of that or other features of the interface. A communication module is one that has a communication interface, e.g., a le system. If a le system is shared between components, they may communicate by reading from and writing to shared les. As a consequence of safe sharing, a communication module that is shared between components must be a component to which the components that share it are connected. Communication integrity forces an interface connection architecture to de ne the communication of a system \completely". If system components are to share a le system, for example, the possible communication between them must be represented. This raises issues of scale and complexity of interface communication architectures. This is good, because now we are forced to face some of the complexity issues of systems at the architecture design stage. Such issues are hidden by object connection architectures, and become sources of error for portability and composition of systems. 7 ADL Features for Scale and Connectability Interface connection architectures allow us to de ne the interfaces and connections of a system before building the system. The advantage is that they can be used as a plan to study and develop a system. However new issues arise that are not usually recognized as problems for object connection systems, but become obvious in interface connection architectures. These fall into two categories, issues of scale and connectability: 1. Proliferation of interface features. 6 For example, required functions could be introduced into C++ by a convention of declaring function pointers in a class public part and objects of the class assuming that functions are assigned to those pointers by other objects. 11 2. Proliferation of connections. 3. Connectability of interface features. 4. Correctness of connections. Scale poses a new issue for ADLs: how to express succinctly large numbers of features in interfaces, and connections between them. Architectures at detailed levels of abstraction can often have on the order of 100 features in an interface with each feature being connected to several others in di erent interfaces (e.g., the Sparc V9 instruction set architecture in Rapide [13]). This situation has been accentuated by introducing requires features into interfaces, and also by making the connections between interfaces explicit | whereas they were implicitly de ned inside the modules of object connection systems. Proliferation of interface ports and port-to-port connections is already a problem in representing hardware models in present simulation languages such as Verilog [14] and VHDL [6]7 . To put it simply, an object connection system will hide a complex spaghetti of connections inside the objects, whereas an interface connection architecture will raise the level of visibility of connections so that they become a prominent property of the architecture. Indeed, complexity of connections is exactly the kind of issue one wants to reveal as early as possible in system planning. But now, ADLs must nd ways of coping with the potentially large number of features of an interface. A second issue, related to scale, is connectability of interface features. An ADL should not allow interface features to be connected if there is no possibility that the resulting communicationwill make any sense | e.g., if the data communicated would violate type requirements at either end of the connection or if two ends of a connection obey incompatible protocols. Connectability is a concept that depends upon the particular semantics of interface feature and connection. It should be a necessary condition for correctness of connections, and should be both powerful enough to disallow many kinds of erroneous connections, and easily testable, say by compile time checks. An ADL should have a semantics which is suciently powerful to allow these two concepts to be de ned: connectability of interface features = an easily checked property of interface features necessary for correct connection, e.g., the types of functions, or the signatures of ports. correct connection = a connection between two interface features such that the implied transfer of data is consistent with all constraints on the features. Correctness of a connection is a logically stronger concept than connectability. Correctness implies that if a connection results in data ow, the data satis es the data type requirements of features at either end of the connection, and also satis es any semantic constraints required of the connected features. Correctness will usually be hard to determine in speci c architectures, and is an undecidable problem in the general case. Examples 1. Suppose interface features are functions. Each function has a type determined by the type of its arguments and the type of its return value. Connectability could be de ned as the type of a provides function g must be a subtype of the type of a requires function, f , i.e., Type(g) <: Type(f ). Suppose a connection between f and g is de ned as identi cation of f with g, so that any call to f is replaced by a call to g with the same arguments. For example, a required function f with no arguments whose return type is Integer could be connectable to a provided function g of no arguments whose return type is Positive Integer. The reverse however would not be connectable since any given Integer value may not be acceptable when we require a Postive integer. Also, a required function with no arguments whose return type is Integer and who's semantics is that it returns only prime numbers, is connectable to a provided funtion with no arguments whoe return type is Integer and who's semantics is that it returns only even numbers; but such a connection would not be correct. 7 E.g., VHDL has an iterative loop-like generate construct to de ne connections over enumerable sets of entities. 12 2. Suppose interface features are ports as in VHDL. A port has a mode, in or out, and a type that de nes the data carried on the port. (Here, out and in correspond to provides and requires.) Connectability could be de ned requiring an out port to be connected with an in port. A correct connection is one between an out port of one entity interface and an in port of another entity interface where both ports are of the same type. 3. In a graphical formalism for de ning architectures, features could be represented by colored shapes such as circles and triangles in boxes representing interfaces. Two features might be connectable if they have the same shape. Connections could be represented as directed lines joining features in di erent boxes. A connection might be correct only if the features it connects are the same shape and color. 4. In [1] a feature is a port represented as a CSP process, which may be viewed as a formal speci cation of the events at the port. A connector is a set of role processes together with a process that coordinates (or schedules) the roles, called the glue. The concept of connectability is associated with a port and a role: the port process must be a re nement of the role process. A correct connection between a set of ports by means of a connector is a binding of ports to roles of the connector to which they are connectable, so that the instance of the connector has certain properties, freedom from deadlock being one of them. 2 In the rst and last examples above we see that, in general, correctness of a connection in an architecture depends upon the semantics of the features it connects, and not simply upon some syntactic property such as the signature of a function. Just as determining whether or not a module in a system conforms to its interface is an undecidable problem, so is determining the correctness of a connection in an architecture, given a reasonably rich language for expressing feature semantics. Thus we must expect connectability to depend only upon syntactic properties in order to be easily checkable. This situation is analagous to type compatibility in languages like C++, which is automatically checked by the compiler, whereas type correctness, which takes account of the semantics of the operations of the types (see Section 4), is usually not checked at all although in many cases it could be. Similarly, although in the general case correctness of connections is an undecidable problem, we believe that for many kinds of real life architectures it can be checked automatically. 8 Duality and Interface Services In general, communication between modules in a system involves sets of connections between sets of interface features of the modules. Often, there is a protocol relating the order and data ow between features in the sets. Correct connection must satisfy both the formal constraints on individual interface features and the protocols relating data ow among the di erent features in the set. Here we introduce two new ADL concepts, duality and services. The purpose of these concepts is to structure interfaces into sets of features (called services). In Section 9 we de ne a concept of a connection between a pair of dual services which denotes a set of connections between interface features in the two services. Service connections can often be easily checked for correctness. dual features = features in di erent interfaces that can be correctly connected. E.g., required and provided functions of the same type with the same formal constraints. service = a set of provides and requires interface features and formal constraints. E.g., a contextualized interface with constraints. dual services = two services each consisting of a set of features each member of which is a dual of a feature in the other service. E.g. hardware plugs and sockets. Dual features and dual services are easily recognized in many practical cases, e.g., if two features are connectable and have the syntactically identical constraint. If correct connectability is a symmetric 13 relation among features, so also is duality of features and services, and furthermore, a feature or service is a dual of its duals. We note that a pair of dual services de nes a bi-directional communication subsystem containing both the signatures of the features in the subsystem and the semantics of their use. Next, we allow services to appear in interfaces. That is, the ADL concept of contextualized interface is extended so that services can appear in interfaces (see Figure 5). A service is always a provided feature of an interface 8 . The semantics of a service is that it is simply a device for structuring an interface into related groups of features, each group having its own formal constraints. Thus, an interface containing services can be \ attened", i.e., it is equivalent to an interface that consists of the sets of provides and requires features of each of its services together with their constraints, each feature being suitably named to prevent name clashes with features from other services. The concept of services may be realized in a particular ADL in di erent ways, e.g., services might simply be interfaces within interfaces. provides function Msg (data ); requires function Ack ; constraint ( Msg , Ack ) * ALTernate Interface A requires Msg provides provides Ack requires ( Msg , Ack ) Msg Ack ( Msg , Ack ) * B * ALT dual ALT Sender Receiver connect Sender A to Receiver B Figure 5: Dual services and a service connection between them Examples A service can be viewed as a plug and its dual as a matching socket (and conversely). This is a notion which is very common in the hardware world. For example, the RS-232 standard de nes a set of twenty or so wires (features) together with their semantics, i.e., the direction of the signals on each wire and the protocol de ning the orderings of the signals. An interface for a hardware component such as a modem or computer can provide a number of RS-232 ports, each one being declared either RS232 or dual RS232 8 As we shall see, duality commutes with provides and requires. 14 (duality declares which side of the RS232 interface is provided, DTE or DCE). Then, a single ribbon cable can be strung between two such dual services provided by di erent pieces of equipment. A correct connection of the twenty or so wires is assured because both services conform to the same protocol constraint (see example, Section 9). Figure 5 shows two interfaces, each containing a service. The Sender interface contains service A, and the Receiver interface contains service B. Service B is an instance of an interface called ALT. In this example features are functions and the dual of a provides feature is a requires feature with the same name, signature and constraints. Service A contains a dual of each feature of ALT together with the same constraint (explained later). A is therefore a dual service to B. Using service names to qualify feature names, the Receiver interface contains a provides function, B.Msg and a requires function, B.Ack; the Sender interface contains a provides function, A.Ack and a requires function, A.Msg. 2 Finally, we note here that an interface may have the capability to relate features that are speci ed in separate services within that interface. Constraints within the interface could be used, for example, to specify protocols involving two services: e.g. \whenever somebody contacts me on service A, then I report that contact on service B". So services in the same interface, although they group features together, are not necessarily disjoint as regards the behavior of components conforming to that interface. 9 Plug and Socket Architectures Plug and socket architectures are interface connection architectures in which interfaces are allowed to provide services, and dual services may be connected together by a service connection : service connection = a single connection between two dual services that denotes a set of interface connections, one between each pair of dual features in the two services. One service connection denotes a number of individual connections between interface features. One may imagine in an ADL that a service connection has a concise notation using service names, so that it is notationally no more complex than a connection between a pair of interface features. One service connection therefore reduces the notation required for a set of interface connections in a large architecture to the same complexity as the notation for a single member of that set | rather like a mess of separate wires being bundled together into a single cable. A service connection is correct if all of the interface connections it denotes are correct. For many common examples of dual services, it is easy to show that the set of interface connections denoted by a service connection between those services must satisfy the service constraints. This is true for common kinds of protocols which constrain the order in which interface features are used, for example. In such cases, if two modules having the dual services conform to their interfaces, then they will communicate correctly on a connection between those services. We give an example below of correctness of a service connection between dual services with a simple protocol constraint.9 Examples Correctness of a service connection Figure 6 expresses the interfaces and connections shown in Figure 5. The constraint on the ALTernate interface describes a simple communication protocol (in this case using regular expressions). It should be read as saying the correct use of the interface is to call function Msg followed by a call to function Ack followed optionally by another call to Msg which must be followed by a call to Ack, ad in nitum. 9 A general de nition of the constraints for which service connections are known to be correct is beyond the scope of this paper. 15 class ALTernate is provides function Msg(Data); requires function Ack; constraint: (Msg; Ack)* end class; class Sender is service A : dual ALTernate; end class; class Receiver is service B : ALTernate; end class; S: Sender; R: Receiver; connect S.A to R.B; Figure 6: A simple plug and socket architecture In other words, there is an Ack following each Msg and a call to Msg may not happen until a preceding call to Ack (except for the rst Msg, obviously). The Sender and Receiver interfaces contain dual instances of services of type ALTernate. As long as each Sender and Receiver module conforms to the constraints in its interface (which includes the constraints in the services in its interface) then a connection between the two services will also be correct. To see this, consider that the Sender must obey the constraint in its service. Its functions have provides/requires modes that are duals of those in the ALTernate interface. Its constraint may be read as \Sender may call the Msg function (which it requires) but someone must call the Ack function (which it provides) before Msg can be called again." Similarly, the Receiver must obey the same constraint in its service. The constraint is over functions with the same provides/requires modes as the functions in the ALTernate interface, and may be read as \After the Msg function is called by someone, the Receiver must call the Ack function, and may not call it again until the Msg function is called again." Now the semantics of interface connections is that a use of a required feature is replaced by a use of the provided feature connected to it (e.g., aliasing of function calls). So, if the Sender calls its interface Msg function then the Receiver's interface Msg function is called; similarly a call by the Receiver to its Ack function results in a call to the Sender's Ack. Therefore, the two interface constraints will be simultaneously satis ed if the modules conform to their interfaces. That is, \The Sender may call the Msg function after which the Receiver must call the Ack function. Only after the Ack function call may the Sender call the Msg function again." So, the communication de ned by this service connection will satisfy the interface constraints, assuming interface conformance. A plug and socket architecture for our compiler By looking at the interfaces in Figure 4 one cannot tell which functions are intended to be connected. One cannot easily decide which other module is intended to use the Parser's Initialize function, or whether the Initialize and Semantize functions (in the Parser and Semanticizer ) were expected to be used by the same module. If there is an error in the connections (very common in hardware modelling languages) there is no easy cross check. Indeed, we have used the same function names in di erent interfaces to suggest intended connections. In general it is dicult to tell which feature in one interface 16 class CodeGenerator_Semanticizer is provides: function Incremental_Semantize(Data : Tree; Context : Tree); end class; class CodeGenerator_Parser is provides: function Initialize(); requires: function Generate(Data : Tree); end class; class Parser_Semanticizer is provides: function Semantize(Data : Tree); requires: function FileName() return String; end class; Figure 7: Interface services for compiler components was intended to be connected to what other features in a di erent interface or which features in a particular interface were meant to be associated together for the purpose of connection | i.e., are part of a communication protocol. The interface connection architecture for our compiler could be re ned into a plug and socket architecture. Services (plugs and sockets) could be de ned to group the features used to communicate between each pair of interfaces in the architecture. These services are shown in Figure 7. We have used obvious mnemonics to indicate which pairs of modules are intended to communicate by a given service. Using these services we can rewrite the interface connection architecture in Figure 4 as in Figure 8. Each interface contains two services, with each service encapsulating the communication between a speci c pair of interfaces; each pair of interfaces contains duals of the service de ning the communication between them. The three service connections are shown in Figure 8, and the architecture is depicted graphically in Figure 9. Advantages of services are illustrated in this and the previous example. First an interface is structured into groups of features (the plugs and sockets) that indicate which other types of interfaces it should be connected to in architectures | i.e., those with dual services. So services indicate context with more precision than before. Secondly, service connections are less prone to trivial syntactic errors because they connect dual services { not simply individual features. Thirdly, as shown in the previous example, service connections can often result in correct sets of connections, and the correctness is easy to determine. Re ning communication in the compiler architecture Services are also useful in the process of re ning the detail in the communication between components of an architecture without increasing the complexity of its syntactic representation in an ADL. As the detail in specifying the communication between the components increases, the number of features in each of the services in Figure 7 increases. But while the plugs become more complex, the plug and socket architecture as shown in Figure 8 can remain unchanged. For example, one could re ne the service de ning the communication between the Semanticizer and the Code Generator. The Semanticizer could supply more a ne grained interface to the Code Generator, allowing the Code Generator to ask for speci c symbol table information, or di erent semanticization schemes. The CodeGenerator Semanticizer interface might become so complicated that we subdivide 17 class Parser is provides: C_P : service CodeGenerator_Parser; P_S : dual service Parser_Semanticizer; specification ... end Parser; class Semanticizer is provides: C_S : service CodeGenerator_Semanticizer; P_S : service Parser_Semanticizer; specification ... end Semanticizer; class Code_Generator is provides: C_P : dual service CodeGenerator_Parser; C_S : dual service CodeGenerator_Semanticizer; specification ... end Code_Generator; P: Parser; S: Semanticizer; G: Code_Generator connect P.P_S to S.P_S; G.C_P to P.C_P; G.C_S to S.C_S; Figure 8: A plug and socket architecture for a compiler. its features even further into Symbol Table features and Semanticize features. Such a re nement is illustrated in Figure 10. Similar expansions in detail could be made in the other services in our compiler architecture. The Parser interface could add features which select among di erent grammars (C, C++, etc). The Code Generator could provide features which control its heuristics (fast generation of inecient code, slow generation of ecient code) or its target instruction set (i486, Sparc, etc). The number of connections (and potential misconnections) in the interface connection architecture corresponding to such a plug and socket architecture becomes large. The expanded CodeGenerator Semanticizer service can be used in place of the previous service in the plug and socket architecture in Figure 8. The syntactic representation of the interfaces and the connections need not change, so the syntactic complexity of the architecture remains constant. Of course, the meaning of the interfaces and connections has changed. Whereas before each service connection denoted two or three function connections, the new service connections denote dozens or more function connections. Adding new components to the compiler architecture Services also provide a simple and error-free way to add new components to an architecture. Suppose the new component's interface is already designed. The dual of the new component's interface is added as a new service to each of the interfaces of those components that should be connected to the new one. Corresponding service connections between these new services and the new component interface are added to the architecture. The new features in interfaces are cleanly encapsulated in the new services, 18 Parser Semanticizer Code Generator Figure 9: A plug and socket architecture and conforming system. and separated from previous features, and the new connections are clearly de ned. Mis-connecting new features with features in existing components rather than the new component is avoided. For example, at some point in the development of an architecture communication integrity will become a concern. As mentioned in Section 6, all connections between more than one component and any unsafe component must be expressed in the architecture, otherwise a system is likely to have communication between its components that is not speci ed by the connections in the architecture. Assume that each of the components in our compiler needs to perform I/O with the le system. A typical le system is certainly unsafe. The architecture in Figure 9 should be extended by adding a le system component and connections between it and the existing components. We may suppose that an interface for a le system, say something like Figure 11, is already in a component library. So, we add the dual of this interface as a new service in each of the interfaces for the Parser, Semanticizer, and Code Generator. Now each component is speci ed to have a socket for connection to a le system. The architecture is then extended by adding a File System interface and connections between it and these new services as shown in Figure 12. Assuming that each of the compiler components conforms to its new interface, which implies that they use the le system service correctly, then the new connections 19 class Symbol_Table is provides: function Is_Apply_Node(Data: Tree) return Boolean; function Is_Selection_Node(Data:Tree) return Boolean; function Is_Statement_Node(Data:Tree) return Boolean; ... function Line_Number(Data:Tree) return Integer; function Column_Number(Data:Tree) return Integer; function Attribute_Of(Data:Tree; Attribute_Index:Integer) return Attribute; ... end class; class Semanticize is provides: function Semantize_Compilation_Unit(Data:Tree; ST:Symbol_Table); function Semantize_Statement(Data:Tree; Context:Tree; ST:Symbol_Table); function Semantize_Expression(Data:Tree; Context:Tree; ST:Stmbol_Table); ... end class class CodeGenerator_Semanticizer is provides: ST: service Symbol_Table; S : service Semanticize; end class; Figure 10: Expanded CodeGenerator Semanticizer service interface class File_System is type File; provides function Open_File(name: String) return File; function Close_File(f: File); function Write(f: File; data: String); function Read(f: File) return String; ... end class; Figure 11: File System Interface. will be correct. 2 Service connections are not restricted to being one-to-one or static. We may have architectures in which one plug is connected to several sockets, and plug-to-socket connections may depend upon execution time variables. 10 Conclusion This paper presented three concepts of architecture: (i) the object connection architecture, (ii) the , and (iii) the plug and socket architecture. The rst two kinds of interface connection architecture 20 Parser File System Semanticizer Code Generator Figure 12: The compiler's plug and socket architecture with File System. architecture di er in the way they are related to systems. An object connection architecture, typical of many object oriented systems, is de ned by the system. Consequently, as illustrated in the paper, an object connection architecture cannot be used as a template to construct and modify systems, or to decide questions about the correctness of the system. The interface connection architecture overcomes this problem by requiring that all communication into and out of a component go through that component's interface. A more complex concept of interface is needed to support interface connection architecture. This allows the communication architecture to be de ned purely in terms of the interfaces, before components are constructed to implement those interfaces. We have indicated how interface connection architectures are templates for system development and modi cation. Conformance of a system to an interface connection architecture requires both interface conformance and communication integrity. Conformance is often dicult to determine, and in general, undecidable. Also, interface connection architectures have the e ect of raising the communication topology of the system to the level of the architecture, thus introducing concerns about scale early in the development process. 21 The nal concept of architecture, the plug and socket architecture, preserves the advantages that the interface connection architecture has over the object connection architecture while introducing some ways of dealing with the scale and conformance problems of the interface connection architecture. Through the use of services and the notion of duality, an interface's spec cation may be kept manageably compact. We have sketched how language syntax might take advantage of plug and socket architecture to reduce complexity, and we also indicated how services may be used to lessen the burden of proof for system/architecture conformance. The examples we have used have all been rather simple, static architectures. However, the observations of this paper apply to dynamic architectures, where connections and components may be created or removed as during the actual execution of a software system. Further works lies in determining more powerful and useful concepts of architecture, and in incorporating connection topology into the notion of architectural class (or type). References [1] R. Allen and D. Garlan. Formalizing architectural connection. In Proceedings of Sixteenth International Conference on Software Engineering, pages xx{yy. IEEE Computer Society Press, May 1994. [2] O. J. Dahl, E. W. Dijkstra, and C. A. R. Hoare. Structured Programming. Academic Press, 1972. [3] Margaret A. Ellis and Bjarne Stroustrup. The Annotated C++ Reference Manual. Addison-Wesley, 1990. [4] D. Garlan and M. Shaw. An Introduction to Software Architecture, volume I. World Scienti c Publishing Company, 1993. [5] W. Wayt Gibbs. Software's chronic crisis. Scienti c American, 271(3):86, September 1994. [6] IEEE, Inc., 345 East 47th Street, New York, NY, 10017. IEEE Standard VHDL Language Reference Manual, March 1987. IEEE Standard 1076{1987. [7] Intermetrics Inc., Cambridge, Mass. Ada 9X Reference Manual, June 1994. ANSI/ISO Draft International Standard. [8] B. W. Lampson, J. J. Horning, R. L. London, J. G. Mitchell, and G. L. Popek. Report on the programming language Euclid. ACM SIGPLAN Notices, 12(2), February 1977. [9] David C. Luckham, John J. Kenney, Larry M. Augustin, James Vera, Doug Bryan, and Walter Mann. Speci cation and analysis of system architecture using Rapide. 1995. [10] David C. Luckham, James Vera, Doug Bryan, Larry Augustin, and Frank Belz. Partial orderings of event sets and their application to prototyping concurrent, timed systems. Journal of Systems and Software, 21(3):253{265, June 1993. [11] K. Nygaard O-J. Dahl. Simula { an algol-based simulation language. Comm. A.C.M., 9(9):671{678, 1966. [12] D. L. Parnas. The in uence of software structure on reliability. In Proceedings of the International Conference on Reliable Software, pages 358{362, April 1975. [13] Alexandre Santoro and Woosang Park. SPARC-V9 architecture speci cation with Rapide. to appear, Stanford CSL Technical Report, 1995. [14] D. E. Thomas and P. R. Moorby. The Verilog hardware description language. Kluwer Academic Publishers, 1991. [15] US Department of Defense, US Government Printing Oce. The Ada Programming Language Reference Manual, February 1983. ANSI/MIL-STD-1815A-1983. 22

References (15)

  1. R. Allen and D. Garlan. Formalizing architectural connection. In Proceedings of Sixteenth Inter- national Conference on Software Engineering, pages xx yy. IEEE Computer Society Press, May 1994.
  2. O. J. Dahl, E. W. Dijkstra, and C. A. R. Hoare. Structured P r o gramming. Academic Press, 1972.
  3. Margaret A. Ellis and Bjarne Stroustrup. The Annotated C++ Reference Manual. Addison-Wesley, 1990.
  4. D. Garlan and M. Shaw. An Introduction to Software A r chitecture, v olume I. World Scienti c Publishing Company, 1993.
  5. W. Wayt Gibbs. Software's chronic crisis. Scienti c American, 2713:86, September 1994.
  6. IEEE, Inc., 345 East 47th Street, New York, NY, 10017. IEEE Standard VHDL Language Reference Manual, March 1987. IEEE Standard 1076 1987.
  7. Intermetrics Inc., Cambridge, Mass. Ada 9X Reference Manual, June 1994. ANSI ISO Draft International Standard.
  8. B. W. Lampson, J. J. Horning, R. L. London, J. G. Mitchell, and G. L. Popek. Report on the programming language Euclid. ACM SIGPLAN Notices, 122, February 1977.
  9. David C. Luckham, John J. Kenney, Larry M. Augustin, James Vera, Doug Bryan, and Walter Mann. Speci cation and analysis of system architecture using Rapide. 1995.
  10. David C. Luckham, James Vera, Doug Bryan, Larry Augustin, and Frank Belz. Partial orderings of event sets and their application to prototyping concurrent, timed systems. Journal of Systems and Software, 213:253 265, June 1993.
  11. K. Nygaard O-J. Dahl. Simula an algol-based simulation language. Comm. A.C.M., 99:671 678, 1966.
  12. D. L. Parnas. The in uence of software structure on reliability. I n Proceedings of the International Conference o n R eliable Software, pages 358 362, April 1975.
  13. Alexandre Santoro and Woosang Park. SPARC-V9 architecture speci cation with Rapide. to appear, Stanford CSL Technical Report, 1995.
  14. D. E. Thomas and P. R. Moorby. The Verilog hardware description language. Kluwer Academic Publishers, 1991.
  15. US Department of Defense, US Government Printing O ce. The Ada Programming Language Reference Manual, F ebruary 1983. ANSI MIL-STD-1815A-1983.

Welcome to Academia

Sign up to get access to over 50 million papers

By continuing, you agree to our Terms of Use

Continue with Email

Sign up or log in to continue.

Welcome to Academia

Sign up to continue.

Hi,

Log in to continue.

Reset password

Password reset

Check your email for your reset link.

Your link was sent to

Please hold while we log you in