Component-Based Programming of Distributed Applications Vladimir Marangozov, Luc Bellissard Projet SIRAC, IMAG-LSR, BP 53, 38041 Grenoble Cedex 9, France e-mail:
[email protected]
Abstract: Building new architectures and frameworks that integrate already existing components is more than ever a challenging direction of distributed software engineering. However, application designers still face a real problem when attempting to reuse, build and interconnect software components in a flexible and configurable way. This survey outlines some existing principles and architectures commonly used in the attempt to improve software reuse, to ease the construction of distributed applications and their configuration. It ends up with some open questions on component-based models, on software components and connectors. Evolution of both the telecommunications technologies and the structure of companies and organisations has lead to the emergence of complex distributed applications. Those applications are usually made of several existing, heterogeneous software modules that must cooperate in a common integrated environment. The design, the development and the maintenance of such applications are challenging problems and the current solutions available on the market are still judged as inadequate. The following points are some of the problems faced by the applications designers : Reuse and integration of existing software pieces Configuration of (distributed) applications Management facilities of applications The following section lists some of the techniques frequently used to answer the general problem of constructing distributed applications as well as the more specific problems stated above. This brief survey will start from the world of object-orientation, to the one of distribution, integration and configuration. The paper ends up with some open questions on how those design and programming techniques can be applied to large-scale distributed applications.
1 From Distributed Objects to Components Object paradigm has succeeded on various points such as providing a better way of carrying real world problems into software systems and furthering reuse through a natural and easy to understand mechanism: the inheritance. Another benefit is the clear data encapsulation that provides both protection and localisation of structural and procedural knowledge. However, the construction of distributed applications, especially when the heterogeneity factor springs up, is still a challenging problem when promoting software reuse, application architecture flexibility and configurability. The following issues are some of the causes of this challenge: Integration of Heterogeneous Software PiecesDistributed systems tend to be more and more built out of various software units (librairies, objects hierarchies, modules, ...) originally designed in very different application contexts, languages or systems. A common representation, a wrapping entity is thus needed to ease the encapsulation of heterogeneous
software pieces in order to produce an homogeneous unit independent from any context usage. Objects are not well suited for this purpose, because they are commonly defined in their own closed environment. Reuse and Context DependencyThe success of reusing existing software entities highly depends on the ability of the developer to identify the context dependencies, e.g. the used global variables, their expected values, etc. The usual way of context determination is the reading of the source code in order to produce a more or less approximative idea of the software behavior, but this depends on both the quality of the source and the developer’s knowledge. From this point of view, the object paradigm is a progressive one because the context dependency of an object is reduced: the state is local and accesses are done through predefined entry points (methods). However, depending on language implementations and models, dependencies related to global variables, external method calls and data types are still too hard and too complex to be easily determined without errors. In that sense, OO succeeds in vertical reuse, using inheritance networks, but fails in horizontal reuse, using different object composition networks. Distributed Objects Broker Existing facilities on distributed platforms (such as sockets, RPC, ...) hardly help in the process of recomposing multiple, heterogeneous parts into a global application with an overall vision of its structure. However distributed objects are one way to benefit of the advantages of object orientation to build distributed applications. The OMG framework may be considered as an attempt to ease construction of distributed aplications. CORBA [OMG91] is the first layer of the framework. It enables to define objects with a clear interface, described in a specific language, the IDL [Lamb87]. Inter-object communications is carried out by the ORB (Object Request Broker) with an RPC-like mechanism. It provides a pure client-server model of interactions. The Inter Language Unification (ILU) project[Xerox95] is another kind of ORB and the associated Interface Specification Language (ISL) is more adapted to language heterogeneity (e.g. mapping with C, C++, Modula-3, Common Lisp and Python are available). Nevertheless, there is no way neither at the IDL level nor at the ORB level to specify relations between objects. Interfaces stand alone at the broker level, so the deployment of an application with all the necessary interface is still a painful task. Moreover, it is hard to describe dynamicity inside an application, e.g. creating or destroying a previously called object, or even to create a set of identical interfaces on different nodes of the system. CORBA has been enriched with Object Services that enable specifications of relations and dependencies between interfaces. However, no overall vision of the application is available; object services are helpful for a bottom-up approach of construction. The problems of horizontal reuse and integration of existing pieces of software still remain because distributed objects comply with the standard object model. Software Busses Software busses [Cutko93][Oki93][Reiss90][Boyer95] are another interesting direction to follow when integrating existing applications into a more complex one. Actually, the concept of software busses is on the opposite direction of object-orientation. The software bus is a service that enables the binding of software components in a hidden way. Providers declare to the bus the services they can offer, while the clients of the bus ask for a service by sending an appropriate request. It is worth noting that at runtime there is no possible prediction on who will be bound together. The main
benefit of the software bus approach is the easy integration of various software parts. It is a partial solution to the problem of horizontal reuse, but imposes the programmer to comply with the API of the bus. Morover, software busses let no control on the communication between service seekers and their respective providers. Module Interconnection Languages Module Interconnection Languages [DeRemer76] are means for isolating program structures from the execution context. The developer is able to concentrate on the functional requirements of the modules and then, using a higher-level language, it is possible to describe the interactions between modules. Polylith [Purtilo94] is an example of this approach. It offers modules and the module interconnection mechanisms independently from the deployment platform. The runtime support of Polylith encapsulates the communications between modules as well as the data transformation so that the treatment of interfacing requirements is decoupled from that of functional requirements. Programmers have not to pay constant attention to constraints imposed by the underlying architecture, the language processors or the communication media. Furthermore, when an application has been configured for one execution environment, its execution within another environment is treated separetely, automatically and independently from the modules implementation. Conic [Kramer89] and more recently Darwin [Magee94] offer a more flexible approach than Polylith. The structure of an application is made of components, a very similar notion to modules except that a component is an instance of a class and may be composed of several already defined instances of components. The application is seen as a hierarchy of interacting components defined by the application designer using the Darwin configuration language. The management process of a distributed application, for instance execution monitoring, becomes easier because the manager and the designer have the same view of the application. They can focus on communication between components, placements on nodes of the distributed system without having to modify the code of basic components. The Olan Configuration Language [Bellissard96] extends the above approaches and stresses on the dynamic aspects of the application configuration. It introduces connectors as specialized binding objects between components, as well as associative naming of the interconnected set of components. The first consequence of this approach is to give a more important role to interconnections, the code related to communications is now external to the component and becomes visible, configurable and reusable. The use of connectors is a way of decoupling communication from the core implementation thus leading to explicit configuration and dynamic naming of involved components. Connectors can connect components with, a priori, incompatible services (e.g. different method names or signatures) by using predefined marshalling rules. Connectors are the way to define various interconnection topologies with the same set of components by using different connectors or different associative naming schemas. New connectors types can be easily obtained by allowing connector compositions, thus increasing both the flexibility for interconnecting several existing components and the possibility to produce subsequently new application behaviour with minimal changes of the interconnection semantics.
2 The Future of Component-based Programming As we stated in the previous section, a significant amount of work has been done in the computer science community in order to introduce easy-understandable, high-level abstractions for building various applications, such as components and connectors. However, the main difficulty consists in mapping these abstractions to concrete working computer systems, having in mind both their
heterogeneity and the multiple system and application requirements. In our sense, the future work on component-based approaches should be guided by the process of application construction. This includes all aspects of application configuration and management, but also the existing relations between an application and the underlying system. It is important to define more precisely the QOS within a component-based approach in terms of services required by the application and how the system can be "opened" in order to provide them. Before pointing out some related open problems (that we propose to discuss at the workshop), let us briefly resume the major key-features of the Olan component model, in order to explicit the notions we use when building applications in terms of components. The Olan component model An application whose configuration is described with Olan can be viewed as a hierarchy of interconnected components. Each level of the hierarchy is a separate Olan description derived from a component class which encapsulates components - in fact components’ instances - contained in the next level. As in object oriented programming languages, components are described by an interface and an implementation. The interface of a component class contains information that allows using the component without knowledge of its implementation. We have extended the usual concept of an interface, as defined for example in the CORBA IDL, to include the description of all the properties required from a component to work properly. An interface contains services, notifications and attributes. Services are functions or procedures that can be executed or requested by a component. Provided services are always offered by the implementation of a component class while required services are the services expected to be called by the implementation of the component class. Notifications are events whose broadcasting can trigger the execution of reactions on several components. A component which receives a notification may optionally react to it by executing a code sequence called a Reaction. Notifications are not necessarily connected to a reaction, nor is a reaction necessarily triggered when it receives a notification. This is the intrinsic property that allows separating services from notifications. Attributes are typed variables whose values are set at instantiation time and can change during execution. The value of a given attribute can be imported from the implementation or set from outside the component. A component class implementation is either made of a hierarchy of "sub-components"or of "real" pieces of software. We thus distinguish two kinds of components. A primitive component class is the unit of encapsulation and reuse of existing code. The implementation of a primitive component class is made of pieces of software (C modules, C++ classes,...) that implement the provided services declared in the interface. A composite component class, commonly referred to as component class, is the main structuring tool. Its implementation is made of "sub-components" and interactions between them. "Sub-components" are instances of component classes described elsewhere. Compared to usual programming languages, the implementation defines which other components are needed and how they should communicate to realize the interface rather than how the functions of the interface are to be directly implemented. Connectors are the units that mediate the interactions between components. They establish the
rules that drive component interactions and specify the required protocol at runtime level. Rules at the connector level include: the interface conformity rules (e.g. parameter types conformity, homogeneity of connections,...), the protocols used for the effective communication (asynchronous vs. synchronous communication, event broadcast vs. remote procedure call,...), and the specification of an expected behavior, such as a set of constraints expressing Quality of Service requirements (e.g. for multimedia communication support). Open questions When considering application construction through the Olan model or a similar component-based approach, several questions arise: About the model: Is it really easy to build applications in terms of interconnected components, separating the communication part from the service implementation inside components. Are component-based approaches suitable for building large scale distributed applications, for example, on the WWW. About components: Is it possible to describe and build in a common way various components, independently from the underlying system platform. What is the cost to pay in order to achieve this. Is an actual interface description (e.g. required/provided services, notifications/reactions, ...) sufficient to express the many possible interactions that may actually take place inside an application. About connectors: What exactly connectors should allow us to do with and which are the adequate connectors we should provide. How easy is it to change the application behaviour by simply replacing some connectors with others. What are the different ways to implement connectors and what about their implementation in a local context versus a distributed one. Some possible answers to these questions will be presented at the workshop, while others can be discussed having a set of guidelines derived from the presentation.
Footnotes [1] OMG has defined the Object Service, one of them being in charge of implementating a distributed Event Service based on asynchonous commnucation between objects.
References [Bellissard96] Bellissard L., Ben Atallah S., Boyer A., Riveill M., ‘‘Distributed Application Configuration’’, Proceedings of the 16th International Conference on Distributed Computing System (ICDCS’96), to appear IEEE, Hong Kong, May 27-30 1996. [Boyer95] Boyer F., ‘‘Coordinating Software Development Tools with Indra’’, 7th Conference on Software Engineering Environments (SEE’95), pp. 1-13, IEEE Computer Society Press,
Noordwijkerhout (Netherlands), 5-7 April 1995. [Cutko93] Cutkosky M.R., Engelmore R.S., Fikes R.E., Genersereth M.R., Gruber T.R., Mark W.S., Tenenbaum J.M., Weber J.C., ‘‘PACT: An Experiment in Integrating Concurrent Engineering Systems’’, Computer Journal, pp. 28-37, January 1993. [DeRemer76] De Remer F. and Kron H., ‘‘Programming-in-the-large versus Programming-in-the-small’’, IEEE Trans. Softw. Eng., vol. 2, num. 2, pp. 80-87, June 1976. [Kramer89] Kramer J., Magee J., Sloman M., ‘‘Constructing Distributed Systems in Conic’’, IEEE Transactions on Software Engineering, vol. Vol.15 , num. No.6, pp. 663-675, 1989. [Lamb87] Lamb D. A., ‘‘IDL: Sharing Intermediate Representations’’, ACm Trans. Program. Lang. Syst., vol. 9, num. 3, pp. 297-318, July 1987. [Magee94] Magee J., Dulay N., Kramer J., ‘‘A Constructive Development Environment for Parallel and Distributed Programs’’, Proceedings of the International Workshop on Configurable Distributed Systems, Pittsburgh, March 1994. [Oki93] Oki B., Pfluegl M., Siegel A., Skeen D., ‘‘The Information Bus - An Architecture for Extensible Distributed Systems’’, ACM SIGOPS’93, pp. 58-67, Dec. 1993. [OMG91] Object Management Group, ‘‘The Common Object Request Broker: Architecture and specification’’, num. 91.12.1, December 1991. [Purtilo94] Purtilo J.M., ‘‘The POLYLITH Software Bus’’, ACM TOPLAS, vol. Vol.16 , num. No.1, pp. 151-174, Jan. 1994. [Reiss90] Reiss S., ‘‘Connecting Tools Using Message Passing in the FIELD Environment’’, IEEE Software, pp. 57-66, July 1990. [Xerox95] Xerox Corp., ILU 1.8 Reference Manual, Xerox Parc, Palo Alto CA, October 1995.