Functional and Non-Functional Contracts Support for Component-Oriented Programming Philippe Collet Objects and Software Components Group Laboratoire I3S - CNRS - Universite´ de Nice - Sophia Antipolis Les Algorithmes- Bat. ˆ Euclide B, 2000 route des Lucioles BP 121, F-06903 Sophia Antipolis Cedex, France
[email protected] ABSTRACT
2. Behavioral contracts, that is some semantic description of data types,
This position paper focuses on contracts for component interfaces, looking at both their functional and non-functional aspects. We investigate how the different levels of contract may relate to each other and what properties must be provided on each form of contract. We argue that a meta-level mechanism will be necessary to support these contracts in a Component-Oriented programming language.
1.
3. Synchronization contracts, which deal with concurrency issues. 4. Quality of Service (QoS) contracts, which encompass all non-functional requirements and guarantees. Current component frameworks are based on OO programming languages, with a large majority being based on the first level of contract. Only a few OO languages, such as Eiffel [8], inherently incorporate behavioral contracts with preconditions, postconditions and invariants. Recent work [4, 5] provide a sound framework for behavioral contracts on interfaces based on pre and postconditions. The expression and verification of contracts related to synchronization or quality of service are clearly not trivial issues. The proposed solutions will certainly be quite complex, at least in their first versions. So one can absolutely ask whether it is worth to investigate such a complete contractual approach for component programming. Actually we consider it is crucial to dispose of such contracts if we want software components to behave like components in other engineering domains. Consequently, to create a real market of software components, application developers must be capable of browsing, comparing and choosing components [9] according to all their exposed properties: an expression of services and quality of these services is then obviously necessary. However a lot of research is still to be done to provide a contract mechanism supporting the four levels defined above in the context of software components. In this position paper, we investigate what properties need to be provided by the languages supporting such contracts, by considering first each contract level individually and then the global contract which is implicitly defined by the four levels. We finally argue that the language mechanism which is intuitively best adapted to support contracts is a meta-level mechanism.
INTRODUCTION
Component-based software development intends to deliver the beneficial effects that the object-oriented approach failed to completely provide: reuse of out-sourced pieces of software and thus increased productivity. In order to promote the component-oriented approach, it is necessary to find out what are the key ingredients of the component-oriented style of programming and what language mechanisms must be provided to support them. The definition of component devised during the 1996 Workshop on Component-Oriented Programming is the following: “A software component is a unit of composition with contractually specified interfaces and explicit context dependencies only. A software component can be deployed independently and is subject to composition by third parties.” [1]. This position paper focuses on the “contractual” specification of interfaces, as we believe this feature can be decisive to provide an adapted environment for component programming and assembly: a component must expose functionalities, through its functional contract, and its performances, using some non-functional contract. More precisely, Beugnard et al [3] categorize contracts in four levels: 1. Syntactic contracts, that is signatures of the data types.
2.
THE CONTRACT LEVELS
Each contract level defines a contract by itself, but the combination of the four levels also define a global contract. The syntactic level of contract is provided by the type signatures of the services described in a interface. This contract tends to be checked statically and the common rules of subtyping permit substitution.
Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Copyright 2001 ACM X-XXXXX-XX-X/XX/XX ...$5.00.
1
We consider behavioral contracts expressed on interfaces through executable assertions organized into preconditions, postconditions and invariants. This approach has some problems in specifying re-entrance [11], but we believe it is currently the best trade-off between expressiveness, easiness towards the application developer and ability to be monitored at runtime. The expressiveness of the assertion language can be enhanced with specific constructs: reference to the state at method entry, frame condition, call propagation, collective operations, etc. We believe these enhancements should be handled by providing a meta-model for the assertion language, which enables to add new operations as long as they can be monitored at runtime by producing some appropriate checking code. The synchronization aspects of contracts still need to be studied in a general component framework, as concurrency issues are often reduced to the means of communication of a give connector in a component. It is important to note that the monitoring of a behavioral contract can be different according to the concurrency model used. Regarding QoS, contracts have been investigated in the world of distributed objects and components systems. To our knowledge, QML (QoS Modeling Language) [6] is the most advanced QoS specification language. In QML, the QoS specification is made through three mechanisms: contract type, contract and profile. Contract type are QoS aspects, such as performance or reliability. A contract is an instance of a contract type and a profile associates a QML contract with an interface. The QoS aspects that can be represented in QML are quite powerful, with different domains of value, constraints and even statistics on measured values over a period of time. However QML does not provide any means to express a QoS contract according to some parameters that would come from the component interface, e.g. to specify a time constraint in relation with the size of an input data structure. Moreover resources consumption cannot be specified. As new QoS specification formalisms are likely to be proposed, a Component-Oriented programming language must be kept open enough to take them into account. A general purpose QoS language should permit the specification of different domains of values, with a proper attention to time and space constraints, access to functional properties of the components and necessary resources. In order to correctly combine all four levels to make up a global contract, we must determine what properties a contract must supply.
3.
The syntactic contract is specified through type signatures, behavioral subtyping is the conformance rule and usually, type checking can be done at compile/assembly time. For behavioral contracts based on pre/postconditions and invariants, the specification formalism is an assertion language. As shown in recent work [5], the conformance of behavioral contracts must follow the subtyping hierarchy: preconditions can be weakened and postconditions can be strengthened. This property is well known in the assertion world, but it is not correctly enforced by contracting systems for Java, as interface inheritance and implementation inheritance can be combined and thus can violate the rule. The contract soundness theorem proposed in [4] should be applied to component interfaces as it directly extends behavioral subtyping with pre and postconditions according to the interface and not the implementation. The monitoring technique for such contracts consists in checking the appropriate preconditions at the entry of a method and postconditions at the exit. As we have no ideal candidate as QoS specification language, we refer to QML to study the properties of some QoS contracts. In QML contracts are made of constraints on domains of values, and a contract can refine another one by adding constraints or putting stronger constraints on an already constrained domain. Each kind of constraint that can be defined in QML must specify a total order among its values. A conformance relation is then defined between the contracts. Monitoring QoS is not considered in QML [6], but other QoS approaches monitor some properties at runtime by configuring the middleware, or more cleverly by using meta-level mechanisms [2].
3.2
• The specification formalism is the grouping of all formalisms. • The conformance rule is the conjunction of all conformance rules. However, it is also important to consider the case where some partial conformance is achieved, for example if a component functionally conforms to the contract but does not provide a strong enough QoS contract. This can lead to a renegotiation of the contract, which is typical in QoS-aware system. In this case, different actions can be engaged:
REQUIREMENTS FOR CONTRACTS
– Termination if the QoS contract is too important to be renegotiated.
To be used as such, we consider that a contract must provide :
– Renegotiation of the QoS contract with weaker constraints (e.g. a 3D component cannot provide a 30 frames/s rate and the new QoS contract asks for 25).
• A specification formalism. • A rule of conformance, to allow substitution.
– Withdrawal of the QoS contract, getting back to a best-effort approach.
• A runtime monitoring technique, if the contract cannot be enforced before runtime.
– Renegotiation of the functional contract and possibly of the QoS contract (e.g. the same 3D component is asked to lower its resolution and may be asked to maintain the 30 frames/s rate).
Let us look at some of the contract levels according to these properties. Then we will look at the combination of all contract levels in one global contract.
3.1
Application to the global level
Considering all four levels together, a proper combination can be determined in order to provide a global contract:
• Monitoring at runtime needs a proper support so that a local contract monitoring does not affect another
Application to each contract level 2
monitoring process at a different level. For example, behavioral and QoS monitoring can interfere if the monitoring code that evaluates assertions create new objects when the QoS is monitoring space occupancy. In the same way, the time spent in monitoring must not be taken into account in profiling time, unless explicitly specified.
showed that renegotiation of QoS contracts must be supported and that different monitoring codes must be aware of each other and must not interfere. Consequently we argue that contract monitoring must be handled globally inside a meta-level that clearly separates the two levels in all functional and non-functional aspects.
6. 4.
LANGUAGE MECHANISM FOR CONTRACTS SUPPORT
Thanks to Jacques Malenfant for discussions on non-functional contracts and for pinpointing the QoS specification language QML.
We believe that a Component-Oriented programming language must support the appropriate formalisms to specify the four levels of contract. Actually, the formalism used at each level is not so important, as long as the properties for each contract level are available. It should then be possible to provide a meta-model for the four levels of contracts, each one can then be instantiated, with a formalism, some code for conformance and some code for monitoring. However, looking at the problems of contract renegotiation and monitoring interference, it is clear that such a coarse-grained combination will certainly not be viable. A more precise framework is needed. Monitoring behavioral contracts can be seen as an aspect in the sense of aspect-oriented programming [7]. Monitoring some QoS properties in middleware has been done through message reflection [2]. Consequently we consider that the language mechanism that will support the monitoring of all forms of contracts is a meta-level with message interception (as contracts are mainly monitored on method calls). It is consistent with the fact that contracts have already been considered as metadata [10]. However this meta-level must satisfy strong constraints, as it must provide a clear separation between the normal behavior and other aspects, so that monitoring of contracts can be as transparent as possible to the semantics and to QoS for the client. Some low-level operations are concerned by monitoring: object allocation during monitoring must not be taken into account, time measurement must distinguish the meta-level and the normal behavior of the application. It is not sure that current implementations that provide access to a meta-level or to some aspect techniques really consider their meta-level as separated as we want it to be. As an extension, we can now consider the role of a container (or context) in a component framework that supports the described contracts. Taking a EJB container as an example, we can note that the contract is established between the container and the client and that the container provides effective resources to the component. If contracts are managed at the meta-level, this will place the container at the meta-level as well. This is also consistent with the fact that a container manages the life cycle of component instances, as well as security and concurrency issues for example, which are all cross-cutting aspects. More work is clearly needed on the interactions between the component architecture with its contextual model and all kinds of contract.
5.
ACKNOWLEDGMENTS
7.
REFERENCES
[1] International Workshop on Component-Oriented Programming (WCOP’96), 1998. [2] M. Aksit, A. Noutash, M. van Sinderen, and L. Bergmans. Qos provisioning in corba by introducing a reflective aspect-oriented transport layer. In 1st ECOOP Workshop on Quality of Service in Distributed Object Systems (QoSDOS 2000), 2000. [3] A. Beugnard, J.-M. J´ez´equel, N. Plouzeau, and D. Watkins. Making components contract aware. Computer, 32(7), July 1999. [4] R. B. Findler and M. Felleisen. Contract soundness for object-oriented languages. In Proceedings of OOPSLA’2001, 2001. [5] R. B. Findler, M. Latendresse, and M. Felleisen. Behavioral contracts and behavioral subtyping. In Proceedings of Foundations of Software Engineering (FSE’2001), 2001. [6] S. Frolund and J. Koistinen. Quality of service specification in distributed object systems design. Distributed System Engineering, December 1998. [7] G. Kiczales and al. Aspect oriented programming. In Proceedings of the 2Oth European Conference on Object-Oriented Programming (ECOOP’97), number 1241 in Lecture Notes in Computer Science. Springer Verlag (Berlin), 1997. [8] B. Meyer. Object-Oriented Software construction. The O-O series. Prentice Hall Inc. (Englewood Cliffs, NJ), 2nd edition, 1997. [9] H. L. Nielsen and R. Elmstrom. Proposal for tools supporting component based programming. In Fourth International Workshop on Component-Oriented Programming (WCOP’99), 1999. [10] A. Orso, M. J. Harrold, and D. Rosenblum. Component metadata for software engineering tasks. In Proceedings of the 2nd International Workshop on Engineering Distributed Objects (EDO 2000), 2000. [11] C. Szyperski. Component Software — Beyond Object-Oriented Programming. Addison-Wesley Publishing Co. (Reading, MA), 1998.
CONCLUSION
Functional and non-functional contracts must be supported in a Component-Oriented programming language. As different levels of contracts are specified, each one must provide a conformance rule and a way to be monitored. By considering a global contract merging all kinds of contracts, we 3