Tool Support for Coordination-Based Software Evolution

2 downloads 31974 Views 52KB Size Report
tion of whether technology is forming business or vice-versa by integrating their business and IT ... ing practical tools that can effectively support software evolution. ..... Coordination technology may be applied to different levels during system ...
Tool Support for Coordination-Based Software Evolution J.Gouveia, G.Koutsoukos, L.Andrade OBLOG Software S.A. Alameda António Sérgio 7 – 1 A, 2795 Linda-a-Velha, Portugal jgouveia,gkoutsoukos,[email protected]

J.L.Fiadeiro Department of Informatics Faculty of Sciences, University of Lisbon Campo Grande, 1700 Lisboa, Portugal [email protected]

Abstract In today’s global and highly competitive business environments, organisations are replying to the question of whether technology is forming business or vice-versa by integrating their business and IT strategies, thus using technology to do business. As a consequence, there is an increasing pressure for building software systems that are able to cope with new requirements imposed by both technological advances and different business rules. At the same time, it is now widely accepted that, although Object-Oriented techniques have provided useful tools for software construction, their support cannot be extended directly to evolution. Even worse, it is becoming evident that there is a lack of theoretical principles and accompanying practical tools that can effectively support software evolution. In this paper, we describe in detail a development tool that is based on sound mathematical principles and supports an architecture-based approach to evolution centred on the notion of coordination contract – a modelling primitive that treats components as black boxes and is compositional with respect to change.

1 . Introduction The theory and practice of business indicate that there are six strategic thrusts in which every business organisation has to be competitive (Wiseman strategic thrusts in [9]): Differentiation (provide different products-services), Cost (reduce costs), Innovation, Growth (new markets), Alliances (acquisitions or mergers) and Time (move fast). For many years, these elements were not of particular interest to those engaged in the Software areas. However, in the meanwhile, business organisations have integrated their business and IT strategies. As a consequence, Software Engineers and Developers are being asked, more and more, to dance according to what is now a familiar tune: “We are using technology to do business”. This message captures, implicitly, a significant shift of power and interest in the Software industry. It advises us, indirectly, to focus more on how to build systems that provide different services by making innovative use of technological advances (Internet, wireless technology, and so on) and, at the same time, can be easily integrated with other systems in order to support business alliances. All this is supposed to happen, of course, very quickly and at low cost. At the same time, this message conveys another, implicit, meaning for the Software engineer: we have to build systems that are flexible, adaptive to change, in very short delays and with minimum cost. In other words, we have to focus more on Software Evolution. Unfortunately, we have not been able to provide a really effective reply to this pressing question. For many years, we have been adopting ObjectOriented techniques and component-based frameworks on the account of the benefits gained while applying them to system construction. We are now realising that, for reasons such as the ones we put forward in [1,2], such techniques cannot be extended directly to address software evolution. Even worse, methods and techniques that, in the past, were devised explicitly for supporting evolution, often fail in the face of the challenges raised by today's economical rules, and end up buried in the literature. In this paper, we describe a tool that supports an architecture-based approach to evolution that we have presented in [1]. This approach is based on new methodological principles and grounded in mathematical techniques as described elsewhere in these proceedings [2]. It is centred around the notion of coordination contract, a primitive that we proposed in [3], for capturing the structuring power of architectural connectors in conceptual modelling. As a modelling primitive, coordination contracts support the separation between computation and coordination, i.e. between what in systems is responsible for the functionalities exhibited

by individual components and the interactions that need to take place between these components to ensure that the behaviour required of the system emerges from their joint behaviour. Coordination contracts allow, at both the design and implementation phases, to distinguish between “stable” and “unstable” entities as far as the evolution of the application domain is concerned. They support evolution by allowing "unstable" entities, corresponding to business rules that coordinate the behaviour of the "stable" ones, to be inserted or modified in a “plug and play” mode while leaving untouched the "stable" ones. Our aim in this paper is to show how such principles can be supported, in practice, on current working environments. More precisely, we follow up a strategy that we outlined in [3,5] and propose and analyse a Design Pattern as the main technique to implement coordination contracts. The remainder of this paper is organised as follows: Section 2 gives an overview of coordination contracts along with an example of how they support evolution. Section 3 describes the Contract Development Tool (CDT). Section 4 presents and analyses the Coordination Contracts Design pattern, and gives some hints on its implementation in Java and C++. Concluding remarks and an outline of on-going and future work round up the paper.

2 . Coordination Contracts In general terms, a coordination contract is a connection that is established between a group of objects (participants). Through the contract, rules and constraints are superposed on the behaviour of the participants, which determines a specific form of interaction. From a static point of view, a contract defines what in the UML is known as an association class. However, the way interaction is established between the participants is more powerful than what can be achieved within the UML and similar OO languages because it relies on the mechanism of superposition as developed for parallel program design [6,8,11]. When a call is made from a client object to a supplier object, the contract “intercepts” the call and superposes the forms of behaviour it prescribes. In order to provide the required levels of pluggability, neither the client, nor any other object in the system, needs to know what kind of coordination is being superposed. To enable that, a contract design pattern is presented, in Section 4, that allows coordination contracts to be superposed on given objects in a system to coordinate their behaviour without having to modify the way the objects are implemented (black box view). Coordination contracts are partially supported by a specification language called Oblog [12]. Using the Oblog notation, a coordination contract is defined as follows: contract class participants constraints attributes operations coordination end class

A contract consists of a collection of role classes (that identify the types of objects that can be partners in the contract), constraints that represent invariants defining in which conditions instances from the participating classes may be related by the contract, attributes and operations private to the contract, and the prescription of the coordination effects that will be superposed on the partners. Each interaction under a coordination rule is of the form:

when with

The name of the interaction is used for establishing an overall coordination among the various interactions and the contract’s own actions. The condition under “when” establishes the trigger of the interaction. The trigger can be a condition on the state of the participants, a request for a particular service, or a signal received by one of the participants. Several conditions can be placed in the “when” clause using the keyword “AND”. If one of such conditions is not satisfied, the contract is considered as being “inactive” and, as a result, either the original code of the trigger or another contract is executed. This mechanism provides the ability for controlling which of the contracts imposed on a component will be responsible for coordinating it.

The set of actions identifies the reactions to be performed, usually in terms of actions of the partners and some of the contracts own actions. When the trigger corresponds to an operation, three types of actions may be superposed on the execution of the operation: 1 . before action: to be performed before the operation 2 . replace action: to be performed instead of the operation (alternative) 3 . after action: to be performed after the operation

before

before

*->> x()

replace

after

after

C1

C2

Figure 1. Execution of before, replace and after In the case in which an object participates in multiple contracts with the same trigger, the sequence of execution for the before, replace and after clauses is shown in Figure 1. It should be noted that the semantics of contracts allow for only one “replace” clause to be executed, thus preventing the undesirable situation of having two alternative actions for the same trigger. Furthermore, any such replacement action must adhere to whatever specification clauses apply to the operation (e.g. contracts in the sense of [Meyer] [13] specifying pre- and post-conditions). This ensures that the functionality of the original operation, as advertised through its specification, is preserved. The set of actions that are executed are called the synchronisation set associated with the trigger. The semantics of contracts requires that this set be executed atomically, guarded by the conjunction of the guards of the individual actions together with the conditions included in the "with" clause. Therefore, the “with” clause puts further constraints on the execution of the actions involved in the interaction. If any condition under the “with” clause is not satisfied, an exception is thrown as a result and none of the actions in the synchronisation set is executed. For a more detailed description of coordination contracts, the reader is urged to consult [1,2,3,5]. In what follows, we give a short example of how contracts can support evolution in a telecommunications transaction processing system. Consider the following specification of an account from a telephone service provider. The main purpose of the class is, simply, to charge the account whenever a phone-call finishes. The other operations of the class are, also, self-explanatory. class Account declarations attributes object tel_number: Integer; balance: Integer:=0; charge_rate: Integer; operations class *Create(client: Customer); object ?Balance(): Integer; // function, returns balance Charge(call_time: Integer); body

methods Charge is { set balance:= Balance()+call_time*charge_rate; }end end class

A second class specification can be defined with the purpose of modelling the phone calls that each client makes. The operations specified here are used for illustrative purposes. Therefore, they are limited to the ones that calculate the duration of a call and determine the end of a call. class Call declarations attributes object caller_number:Integer; operations class *Create(client: Customer); object FinishCall(); ?CalculateCallTime():Integer; body methods FinishCall is { // body of finish call detects end of call }end CalculateCallTime is { // body-calculates the duration of the call }end end class

In this context, how can the customer’s account be charged as soon as the phone-call ends? Assuming that the two components are completely independent and are not aware of the existence of each other, a third component is needed that becomes responsible for detecting the end of the phone-call, calculate the duration and perform the charge. We argue that the best choice is to have a contract as the third component and that, in this case, contracts provide a very effective way to evolve the system without modifying the existing components. Consider the following simple contract, Traditional Charging, that has the role of the third component and provides the required functionality while offering the advantage that the mechanism (contract) that controls the usage of the given objects is modelled as a first-class entity and, hence, can be evolved independently of the other two. contract class Traditional Charging participants x : Account; y : Call; constraints x.tel_number:=y.caller_number; coordination when *->>y.FinishCall(); after local time: Integer:= y.CalculateCallTime(); call x.Charge(time); end class

Consider now the situation in which the telephone provider wants to have two types of customers and charge them according to different rules. For instance, it could charge important customers only after the call exceeds a specific number of seconds, whereas not important customers are charged for the whole duration of their phone-call. In this case the solution is simply to add to the system a contract like the one below. contract class VIP_Charging participants x : Account; y : Call; attributes free_call_limit:Integer; constraints x.tel_number:=y.caller_number; coordination when *->>y.FinishCall(); after

local time: Integer:= y.CalculateCallTime(); if (time> free_call_limit){ x.Charge(time - free_call_limit); } end class

The functionality of both the previous contracts is straightforward. They coordinate the charging of the Account according to the type of customer and the business rules the network operator defined. Note that if a “*->>” is specified in the coordination part of the contract, any call to the service triggers the rule and that the keyword local just defines a local variable. If a future business requirement determines different behaviour for the components, a new contract, like the VIP_Charging contract above, can be added to the system in a “plug and play” mode in order to achieve the required behaviour. One could argue that a possible solution to handle the situation could be the use of inheritance in order to model the different requirements. However, there are two problems with the use of inheritance for this purpose. Firstly, inheritance does not provide coordination as a first-class entity like contracts do, which means that interactions have to be "coded" directly in the components. Secondly, from the business point of view, the adaptations that make sense may be required on classes other than the ones in which the restrictions were implemented: in the example above, this is the case when it is the type of client and not the type of account that determines the nature of charging. Another solution to deal with such dynamic behaviour could be the use of existing design patterns. However, such patterns would not provide, like contracts do, modelling of coordination as a first class entity. They would also have the disadvantage of having the behaviour of components spread among several classes. A second scenario of evolution is the one in which we have different charging schemes related to the charge rate. For instance, a VIP Customer, can be charged with a charge_rate_1 when the duration of the call is within a time range [0-time_limit] and with a charge_rate_2 when the duration of the call exceeds time_limit. Again the following contract where the charging rates are decided inside the contract can offer a very effective and flexible solution. contract class VIP_Charging_2 participants x : Account; y : Call; attributes charge_rate_1, charge_rate2, time_limit : Integer; constraints x.tel_number:=y.caller_number; coordination when *->>y.FinishCall(); after local time: Integer:= y.CalculateCallTime(); if (time time_limit){ x.charge_rate:= charge_rate2; } x.Charge(time); end class

Clearly, one can come up with many other similar scenarios of evolution that coordination contracts support. However, we believe that the previous examples are enough to illustrate how contacts can externalise the interactions between objects, making them explicit in the conceptual model, and support compositional evolution of systems with respect to the evolution of business requirements. In the following section we present a tool that supports the use of contracts in software development practice.

3. A Development Tool for Coordination Contracts A system suitable for evolution based on the ideas presented above is structured in two layers. The Component layer and the Coordination layer. The former includes the basic building blocks that can be potentially coordinated. The latter defines the contracts that coordinate such blocks. Using a coordination-based approach in the software development process requires some new activities to be integrated in the process. An environment for a software development process that supports the approach should have a tool dedicated to the coordination layer development. This tool may be autonomous or be integrated with the rest of the environment by one of the several integration techniques currently in

place. In this section we describe the main requirements for such a tool, referred as CDT (Coordination Development Tool). The main goal of CDT is to allow the definition of contract types between given components and provide the necessary deployment of the final pieces of the system. The tool assumes that components to be coordinated are somehow available, developed by other part of the environment or given by the developer. What is designated here by a component will be the issue of a detailed discussion later in this section. The CDT should provide facilities not only for the development/testing of coordinations, but also run-time facilities for the management of contracts. We will call this part of the tool the CDT-Rt (CDT Run time configuration). In general terms, the process activities supported by the CDT are represented in Figure 2. Component Development

Context Setup

Contract Development

Deployment

Testing Run-Time Configuration

Figure 2. Process activities supported by the CDT The CDT should provide the following functionalities, at the development level: • Registration: components are registered to the tool as candidates for coordination. • Edition: Contract types are defined connecting some registered components. Coordination rules and constraints are defined on those contracts. • Deployment: the code necessary to implement the coordinated components and the contract semantics in the final system is produced by generating some parts according to the contract design pattern and adaptation of the given component part. • Animation: some facilities are provided allowing testing/prototyping of contract semantics, either in the development environment or in the production environment SYSTEM ASSEMBLER DEVELOPER

CDT Regist Components Contract Type Creation / Edition …

Deploy System

Testing TESTER

Figure 3. CDT Use Cases The CDT-Rt provides configuration mechanisms for the run-time management of contracts, like manual creation/deletion of contracts between objects, configuration of policies for automatic creation of contracts, priorities, and others. An Animation layer can also be generated to allow rapid testing of the application functionality, independently of the original application interface. This layer provides a simple way of creat-

ing and triggering operations on application objects, observe their state, and the dynamics associated with the existence of contracts at work. Contract Type Registration Contract Creation Run-time Configuration Definition

CDT-Rt

DEPLOYED SYSTEM

Trigger Operation Observe Object …

User Application Interface

Animation Interface

Figure 4. CDT Run Time In terms of the architecture of the CDT (Figure 5) there are no special requirements that have to be mentioned. There are four components: the Editor, the Builder, the Repository and the Animator. These logical components support the facilities presented above.

Regist Components

Contract Editor Edit Contracts

Build

Animator

CheckIn/CheckOut

System Builder

Code generation

Test

REPOSITORY 0100 0100 1001 1001 0010 0010 1010 1010

Java Code

Figure 5. CDT Architecture Coordination technology may be applied to different levels during system development depending on several factors, such as the characteristics of the components, the way components are built, the development phase where the coordination concept is going to be used, among others. One of the main motivations in the development of the contract coordination concept was to provide coordination as a top-level abstraction in development, right from the modelling phases. By using the concept, on can provide a clear separation between computational concerns and the communication aspects, leading to flexible and clear models. Current modelling techniques that are used in industry, even state-of-the-art such as UML, do not provide any similar concept. Therefore, to be effective in a working environment, a tool providing coordination facilities must be integrated with existing UML modelling tools. This may be achieved via a plugin technology, or any other integration technique (e.g. using XMI). However, developers may choose to work with the contract coordination concept at a more detailed design / implementation level, where coor-

dination aspects do not appear as modelling artefacts but, rather, as implementation constructs that provide more flexibility in terms of evolution. These two contexts of use can be summarised as follows: Model Coordination: Coordination is used at the Analysis or Design phases. Components are model classes (e.g. UML classes). Coordination contracts make a Coordination Model on top of the Analysis/Design Model. The deployment activity must take into account the way final coded components are obtained from model components and provide the necessary integration. Construction Coordination: Coordination is used in the construction phase. Components are the final coded components of the basic building blocks of the system. Coordination contracts are defined directly over implementation classes. It is suitable to be applied on the evolution of an existing system. We realise, however, that the type of components under potential coordination may define the context and capabilities in which the CDT is used. Furthermore, the specific language and technical environment may impose constraints on the coordination features that can be used because techniques to achieve the implementation of its semantics may not be available. We will call to each context in which the CDT is to be used and the corresponding capabilities a CDT configuration. In what follows we present an example of a concrete CDT configuration (for Java) and its characteristics: Components: Components are Java classes Component format: Java source code files Action language: The language in which coordination actions are specified is Java (or a restricted subset of Java) Coordination Semantic features: Possible triggers for coordinations are operation requests and conditions. Coordination based on events is only possible if a common framework for implementing event-based communication is used. Synchronisation sets (the actions of all the coordinations active) are not fully transactional in the sense that there is no rollback associated, when a failure or exception occurs. This is due to the semantics of the underlying language (Java). Component Generation/adaptation: Coordination pattern components are fully generated and the source components need some minor adaptations. We present more details on that in Section 4. Output: The output of the CDT builder is Java source code files, that are compiled into the rest of the system at the deployment phase. The previous example illustrates what the CDT can provide in a certain configuration. It also makes clear that the output of such a tool is strongly dependent on several other environmental conditions. Therefore, in order to effectively use coordination technology in the development process, two main aspects must be clearly defined first: where to use it, and what are the building blocks that can be put under coordination.

4. A Design Pattern for Coordination Contracts Manual implementation of coordination contracts or tools such as the Contract Development Tool (CDT) require an underlying micro-architecture (design pattern) for their implementation. Apart from the general benefits of using design patterns, as discussed in [10], such an architecture accompanied with implementation guidelines is necessary for three additional reasons: Firstly, it acts as a blueprint for the implementations of coordination contracts. Secondly, it ensures that such implementations obey the intended semantics. Thirdly, it provides an abstract description of tool generated contract-based code. In what follows, we present the basic requirements of a coordination contracts design pattern together with the basic assumptions that apply, and, finally, we describe and analyse the pattern that is used in the Contract Development Tool (CDT). We conclude this section by discussing some implementation issues based on our experience in implementing the pattern in Java and C++. The main requirements of the pattern can be divided into two categories: General architecture requirements and “low-level” design requirements. The former refer to the general pattern architecture while the latter are more related to code design issues that draw from the scope and semantics of contracts. In this context, the general architecture requirements are the following: a. As explained in previous sections, the aim of contracts is to provide the ability to coordinate the behaviour of software components. This is achieved by having contracts “intercepting” calls to components and superpose whatever forms of behaviour each contract prescribes. Additionally, contracts can detect conditions (and events) on participants and define additional actions or put

constraints on the components’ actions. Therefore, two distinct requirements of the pattern are implied. Firstly, the pattern must provide a means of delegating to contracts the requests made on the components, while ensuring isolation between the components and the coordination part (contracts), i.e none of the components knows that coordination takes place. Secondly, the pattern must either explicitly allow or not prevent (during implementation) contracts to be able to detect conditions or events on components and take appropriate actions. b. The proposed architectural solution must provide the required functionality by minimising the number of required changes to the original components. In other words, ideally, no changes to the components are allowed and if this is not feasible such changes have to be limited to (a small number) of changes not related to the implementation of the components’ interfaces. c. The scope and goals of coordination contracts require for the pattern to provide the ability to add and delete contracts in a “plug and play” mode. d. The pattern should allow for contracts to be able to effectively coordinate components that are not “stand-alone” i.e they are subclasses of other components or, generally, they participate in inheritance hierarchies. The “lower-level” design requirements are the following: a. Satisfy the semantics of contracts. This implies that the pattern and its implementation must allow for the correct instantiation of contracts (invariant satisfaction) and for the correct sequence of execution of the synchronisation set. Moreover, it is necessary to implement a contract exception handling mechanism, throwing and handling exceptions when an action of the contract fails or a constraint under “with” is not valid. b. Optimise performance . The pattern should introduce the minimum possible number of additional calls and its implementation should be intelligent enough to minimise a negative impact on performance. The basic concepts of coordination contracts make it necessary to state some assumptions that make easier the development and ensure a better understanding of the pattern’s intended functionality. Firstly, because contracts are used for controlling the communication between components, they need not coordinate the participants’ internal operations. Therefore, the pattern will not deal with internal operations of the components. Secondly, the components are of a form that allows them to be coordinated as described. For instance, the preconditions of their operations are not “hard-wired” inside the code. This implies that the components’ implementations provide computation features only. If this is not the case, there will be limitations to the range of different contracts that can be superposed and a re-engineering phase that results in components of a suitable form is required. The Coordination Contract Design Pattern consists of two parts: The component part and the coordination part. The former consists of the features that have to be provided for each component so that it can become coordinated by a contract. The latter concerns the mechanisms that allow for the coordination of a given component through the contracts that are in place for it. The classes that participate in the proposed pattern are shown in Figure 6. Thick black-line boxes represent tool-generated components. The detailed functionality of the various classes, also summarised in Table 1, is as follows: Component Part -SubjectInterface. It is an abstract class (type) that defines the operations under potential coordination. In fact, it is the common interface of services provided by SubjectToProxyAdapter and ISubjectProxy. -Subject. This is the real component, candidate for coordination, which provides the concrete implementation of the various services and inherits from SubjectToProxyAdapter. -SubjectToProxyAdapter. Defines the ability to alternative use a proxy or internal methods for the implementation of a given Subject interface. It is a concrete class that allows, at run time and using the polymorphic entity proxy, for delegating received requests to ISubjectProxy in the case in which Subject is under coordination. Such requests are then delegated to ISubjectPartner that links the subject to the contracts that coordinate it. If no contract is involved SubjectToProxyAdapter may forward requests directly to Subject. In order to achieve the previous functionality two actions are necessary. Firstly, Subject inherits from SubjectToProxyAdapter. Secondly, the operations of Subject are renamed with the operations having the initial names being moved to SubjectToProxyAdapter as concrete operations and the new operations occurring in SubjectToProxyAdapter as abstract operations. For instance, Subject’s

operation( ) exists now as operation() in SubjectToProxyAdapter and as _operation( ) in Subject. Moreover, _operation() is also declared as an abstract operation in SubjectToProxyAdapter. Requests for operation() are made to Subject. However, due to renaming, the operation does not, in fact, exist in Subject but in SubjectToProxyAdapter from which Subject inherits. In the case that there is no contract (no proxy) involved, operation() in SubjectToProxyAdapter forwards the request to the corresponding real implementation, _operation(), in Subject. Otherwise, as already stated above, it delegates the request to ISubjectProxy. -ISubjectProxy. It represents an object with the capability of implementing the Subject interface. It is an abstract class that defines the common interface of Subject and ISubjectPartner. The interface is inherited from SubjectInterface to guarantee that all these classes offer the same interface as Subject with which real subject clients have to interact. Coordination Part -ISubjectPartner. Defines the general abilities of a concept to be under coordination. It maintains the connection between the real object (Subject) and the contracts in place for it. The class is responsible for delegating received requests to CtSubjectConnectors according to a chain of responsibility. The class contains operations for managing the chain of responsibility. Alternatively, the required management operations can be included in an abstract class, ContractPartner, from which ISubjectPartner inherits. However, this is rather a “low-level” design issue and therefore such a class is not presented in the pattern. -Ct_i_SubjectConnector. A partner that represents the specificities of Subject coordination for a given contract in which Subject is a participant. For each contract there is exactly one Ct_i_SubjectConnector. The class implementation may be responsible for the execution of the rules defined in the coordination part of the contract and for ensuring satisfaction of the contracts’ semantics. -Contract-i. A coordination object that defines the rules that will be superimposed on Subject. Component Part SubjectInterface Subject SubjectToProxyAdapter ISubjectProxy

An abstract class that defines the operations under potential coordination. The real component that is candidate for coordination. Defines the ability to alternative use a proxy or internal methods for the implementation of a given Subject interface. It represents an object with the capability of implementing the Subject interface.

Coordination Part ISubjectPartner Ct_i_SubjectConnector Contract_i

Defines the general abilities of a concept to be under coordination. A partner that represents the specificities of Subject coordination for a given contract in which Subject is a participant. A coordination object that defines the rules that will be superimposed on Subject.

Table 1 . Coordination Contracts’ Design Pattern Class functionality It should be noted that in cases of inheritance between objects that are under coordination, some additional classes and some new associations may exist. Due to space limitations, these are not presented in Figure 6 and will not be discussed in this paper. We intend, however, to present them in the future along with a more “formal” description of the pattern [10]. In what follows, we discuss some “lessons learned” from our experience implementing the pattern in Java and C++. Clearly, a variety of different “low-level” design decisions can be applied to implement the above general pattern. However, such decisions should always take into account the requirements presented in the beginning of this section. In this context, there are four issues we wish to discuss:

Coordination Part

Component Part

SubjectInterface

Chain of responsibility

ISubjectProxy

SubjectToProxyAdapter



_operation ( ) operation ( )

0 …* ISubjectPartner

Subject



Ct_1_SubjectConnector

_operation( )

Ct_2_SubjectConnector

1 1

1 1

Contract1

: UML implements

: UML extends Contract2

Figure 6. Coordination Contracts Design Pattern a. The first issue that should be considered is related to the implementation of Subject in Java. As explained above, Subject inherits from SubjectToProxyAdapter. The question is, what if Subject has to inherit from another class, for instance SuperSubject, since Java does not support multiple inheritance?. In that case, a good solution is for Subject and SubjectToProxyAdapter to be merged into a

single class, Subject, that provides the functionality of both the previous classes. It should be noted that having SubjectToProxyAdapter as a Java interface would not provide a solution because the dynamics of the pattern rely on call delegations that are defined in the method implementations of SubjectToProxyAdapter. Contrary to Java, in C++ multiple inheritance is supported and therefore a C++ implementation is not concerned with such an issue. b. Contracts should be independently and explicitly created so that they can be added and deleted in a “plug and play” mode. A good solution is to explicitly create each contract parameterising its constructor with the contract’s participants (Subjects). The contract is then responsible for creating its CtSubjectConnector passing as argument itself and the participant to which the CtSubjectConnector is associated. The CtSubjectConnector simply checks whether it is the first partner in the chain of delegation. If it is the first partner it sets the subject proxy to point to itself, otherwise it adds itself as the last partner. c. In cases of inheritance, implementations of the pattern maintaining a single chain of responsibility will encounter the problem of having a “non-uniform” chain of responsibility. By the term “non uniform” we refer to the fact that the chain can contain a mixed sequence of the different connectors of the base and the subclasses objects. The chain of delegation management should be responsible for dealing with this situation by retrieving and delivering partners that comply with the corresponding Subject interface for the trigger being processed. d. Correctly retrieving the contracts’ rules and executing the contracts’ synchronisation set are additional issues that have to be considered when implementing the pattern. There are different strategies that can be adopted to deal with such issues. For instance, having a more centralised management of the execution of the contracts rules versus managing the execution in the ISubjectPartner. Due to space limitations, we will not discuss further these issues. We intend, however, to analyse them in future papers.

5. Concluding Remarks In today’s global environment, no one can admittedly deny the fact that business strategy is integrating with IT strategy [7]. Therefore, all traditional business strategic thrusts are now having a direct impact on organisations’ information systems. As a result, there is an increasing pressure for systems and applications to be adaptive to change. Therefore, Software Engineers and Developers are asking, more and more, for disciplines and tools that allow them to build systems that can be easily reconfigured or to evolve existing systems fast and with minimum impact on the already implemented services. In this paper, we proposed tool support for the coordination-based development methodology presented in [1,2] as the answer to this need. We briefly discussed coordination contracts and we presented some examples that motivate their use. However, because, as experience indicates, software techniques that leave on the developer the entire burden of implementation often end up buried in the literature, we described in detail how the notion of coordination contracts can be supported by a development environment. We presented the general requirements and architecture of the environment and we analysed a design pattern that can be used to implement coordination contracts. The pattern draws from the original coordination contracts pattern presented in [3,5] but was improved and enriched with implementation guidelines based on our experience in implementing it in Java and C++. We believe that the notion of coordination contracts, their design pattern and the contracts development environment form a very strong basis for engineers and developers to meet the challenge of designing and developing systems that are better structured, consist of reusable parts and are adaptive to change. Meanwhile, we will continue working on extensions of this work in order to enhance and support the use of coordination contracts, being convinced from our experience in applying contract-based development in the financial domain, that coordination contracts contribute to the development of better software. We, also, believe that a tool such as CDT that generates code that will be incorporated into contractbased applications must be as user-friendly and as flexible and extensible as possible. Therefore apart from making effort for the generated code to be as expressive as possible in terms of appropriate names and extensive use of comments, we are currently investigating alternatives on making CDT more user friendly and easy to extend and integrate with other tools. Moreover, we are researching the possibility of introduc-

ing a notion of contract inheritance allowing for increased opportunities for reuse at the implementation level. Furthermore, we are very much concerned with the issue of performance. That is a critical concern in many application areas (telecommunications systems, on-line systems) in which we believe that contracts can be applied very effectively. Therefore, we are making an increased effort to reduce possible performance bottlenecks in our pattern implementation. Finally, we are not very much satisfied with the fact that the components specified as input to the CDT tool are required to be of a form that allows for their coordination. Therefore, although re-engineering is a necessary and valid requirement in order to achieve coordination-based development, in the future we intend to provide tool support for such reengineering to be performed in a fast and easy way.

6. References [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]

L.F Andrade and J.L.Fiadeiro, “Evolution by Contract”, position paper presented at the ECOOP'00 Workshop on Object-Oriented Architectural Evolution. (extended version submitted for publication available as Contracts: Supporting Architecture-Based Evolution at http://www.fiadeiro.org/jose). L.F.Andrade and J.L.Fiadeiro, "Coordination – the Evolutionary Dimension", in this volume. L.F.Andrade and J.L.Fiadeiro, "Interconnecting Objects via Contracts", in UML'99 – Beyond the Standard, R.France and B.Rumpe (eds), LNCS 1723, Springer Verlag 1999, 566-583. L.F.Andrade, J.Gouveia, P.Xardoné and J.Câmara, "Architectural Concerns in Automating Code Generation", in Proc. TC2 First Working IFIP Conference on Software Architecture, P. Donohoe (ed), Kluwer 1999. L.F.Andrade, J.L.Fiadeiro, J.Gouveia, A.Lopes and M.Wermelinger, "Patterns for Coordination", in COORDINATION'00, G.Catalin-Roman and A.Porto (eds), LNCS 1906, Springer-Verlag 2000, 317-322. K.Chandy and J.Misra, Parallel Program Design - A Foundation, Addison-Wesley 1988. Michael J. Earl: “An Organizational Approach to IS Strategy-Making”, in Information Management: The Organizational Dimension, M. J. Earl (ed.) Oxford University Press, 1998. N.Francez and I.Forman, Interacting Processes, Addison-Wesley 1996. Carrol W. Frenzel, Management of Information Technology, (3rd ed.), Course Technology, Cambridge, MA, 1999. E. Gamma, R.Helm, R. Johnson and J. Vlissidis. Design Patterns: Elements of Reusable Object Oriented Software , Addison Wesley, 1995. S.Katz, "A Superimposition Control Construct for Distributed Systems", in ACM TOPLAS 15, 1993 337356 The Oblog Corporation, “The Oblog Specification Language”, http:// www.oblog.com/tech/spec.html B.Meyer, "Applying Design by Contract", in IEEE Computer, 1989, 40-51.

Suggest Documents