Three-Layered Framework with Separation of ... - Semantic Scholar

1 downloads 0 Views 102KB Size Report
[1] Ralph E. Johnson and Brian Foote. Designing Reusable. Classes. Journal of Object-Oriented Programming, 1(2):22–. 25, July 1988. [2] Rebecca Wirfs-Brock, ...
Three-Layered Framework with Separation of Concerns Ant´onio Rito Silva, Lu´ıs Gil and Jo˜ao Martins INESC/IST Technical University of Lisbon R. Alves Redol no 9, 1000 Lisboa, PORTUGAL Tel: +351-1-3100287, Fax: +351-1-3145843 [email protected]

consistent. It is the responsibility of framework users to choose the right combinations.

A previous version of this paper was presented at the OOPSLA’96 Workshop on Exploration of Framework Design Principles, San Jose, California, October 7, 1996.

 Combinatorial Explosion. Frequently, the specialization of a framework class requires the specialization of other classes in an uncontrolled manner. The number of classes that need to be specialized to construct a solution is variable and may be large.

Abstract This paper describes an object-oriented framework which emphasizes on separation of concerns. The framework design defines an architecture with three layers: Concern, Composition and Application. The Concern layer contains components with solutions for specific minimal problems (concerns). The Composition layer contains components which are responsible for the combination of concern components. The Application layer integrates the framework within the application and allows framework customization. This architecture reduces the explosion of combinations when introducing new concern components and provides a well-defined customization procedure. An Object-Oriented Framework for object concurrency and synchronization is described to illustrate the proposed approach.

This paper describes a three-layered framework with separation of concerns that presents solutions for the problems above. The rest of this paper is structured as follows. Next section describes the architecture of a three-layered framework with separation of concerns. Section 3 describes a three-layered framework addressing the object concurrency and synchronization concerns. Framework features are presented in section 4 and section 5 discusses advantages and drawbacks of three-layered frameworks. Section 6 introduces a larger framework where the approach was applied. Related work and conclusions are presented in sections 7 and 8 respectively.

Keywords: Object-Oriented Frameworks, Design Patterns, Software Components.

1 Introduction 2 Three-Layered Framework Architecture

An object-oriented framework is a reusable design exFigure 1 depicts the three-layered framework architecpressed by a set of classes [1]. These classes constitute a skeleton which provides a generic solution for a class ture. A box represents a group of classes. Dashed arrows of problems. This skeleton can be fleshed out to support represent use and specialization relationships between layer entities. application-specific needs [2]. Frameworks have proven to be a powerful tool for software development. However, some problems have been pointed out:

CONCERN LAYER

 Understandability. Frameworks are designed, after a domain analysis, by experts in a particular domain. As result of this activity, a large set of classes and interactions is designed. Framework users may be non-experts in the particular domain. However, they have to be able to understand the framework so they can use it.

COMPOSITION LAYER

APPLICATION LAYER

CONCERN COMPONENT A

COMPOSITION COMPONENT X

INTEGRATION M

CONCERN COMPONENT C

CONCERN COMPONENT B

COMPOSITION COMPONENT Y

INTEGRATION N

APPLICATION

Figure 1: Three Layer Framework Architecture.

 Inconsistent Specialization. Frameworks offer flexible ways of specializing abstract classes. However, not all the combinations of specialized classes are

The Concern layer contains components which offer solutions for specific minimal problems. The Composition layer 1

 Explicit Interface. To achieve an explicit interface the domain analysis should in addition identify the variable and stable parts of each concern. The stable part should be encapsulated by an interface. The variable part should be “objectified” for future specialization.

contains integration components which are responsible for the combination of concern components. At the Application layer composition components are integrated within the application and concern components are specialized according to the application-specific requirements.

2.1 Concern Layer Concern components are responsible for offering a solution for a minimal problem (concern). The minimal characteristic allows, and simplifies, the composition of concern components thus increasing reuse.

2.2 Composition Layer Composition components are responsible for integrating concern components and to make inter-concern dependencies consistent. Composition components should also offer a simple interface for final integration in the application and hide the particularities of inter-concern dependencies from programmers at the application layer.

Concern components should hold the following properties:

 Independence. The solution provided by a concern Composition components should have the following component should be independent of those provided properties: by other components. This property reduces the number of dependencies between concern components al Consistency. The combination of concern compolowing independent concern components’ instantianents may result in the integration of incompatible tion. From a software engineering perspective, this concern policies. So, the different concern compoproperty enforces modularity of concern components. nents should be consistently integrated in a composition component disallowing the combination of in Abstraction. A concern component should abstract compatible concern policies. a set of solutions to allow component customization. Each solution is called a concern policy. This property increases framework flexibility because the component can be specialized according to applicationspecific needs. From a software engineering perspective, this property enforces extensibility of concern components.

 Minimal Interface. Composition components should offer a minimal interface to the programmer at the application layer. This minimal interface allows composition components to be smoothly integrated in the application so that the programmer can easily, almost transparently, integrate the composition component within the application.

 Explicit Interface. The concern component should provide an interface to be used in the composition of In order to build composition components holding the concern components. This property reduces the exproperties above the composition activity should support: plosion of combinations as it reduces the number of visible elements of each concern component. From  Consistency. This property is achieved by apa software engineering perspective, this property enplying design solutions which avoid incompatible forces encapsulation of concern components. combinations[3] and by writing the necessary code to integrate components. In order to build concern components holding the prop Minimal Interface. To achieve a minimal interface the composition component should aggregate the explicit interfaces of each of the concern components in an interface which hides all aspects deemed nonrelevant for the application programmer.

erties above, a domain analysis should be done for each concern.

 Independence. To achieve independence a careful identification and separation of domain concerns should be done. The identification process should verify whether and how concern algorithms can be 2.3 Application Layer decoupled. In the application layer composition components are integrated in the final application and concern policies may be  Abstraction. To achieve abstraction a domain analycustomized: sis should be done for each concern. As result of the domain analysis a significant set of policies should be  Integration. A composition component is integrated abstracted and described by abstract classes. Afterin the application through its minimal interface. This wards, the policies may be made concrete by specialcan be done using a design solution, like the Proxy ization of the abstract classes. pattern [4] or the Surrogate pattern [5] which decouples an object’s interface from its implementation. 2

 Customization. Concern components, which are integrated in the composition component, may be customized by specializing their variable parts according to application specificities. Variable parts were isolated in classes at the concern layer such that customization becomes a well-defined and localized procedure.

Intent The Customizable Object Synchronization pattern abstracts several object synchronization policies. It decouples object synchronization from object functionality (sequential part).

Structure and Participants

3 Framework for Object Concurrency and The Booch class diagram in Figure 2 illustrates the structure of the Customizable Object Synchronization pattern: Synchronization To illustrate the three-layered framework architecture, this section presents a fragment of a framework for heterogeneous concurrency, synchronization and recovery in distributed applications [6] which is implemented in C++ on top of the ACE environment [7]. The framework architecture has the properties discussed in the previous section. The described fragment, framework for object concurrency and synchronization, supports several policies of object concurrency and synchronization.

Synchronization Interface

Sequential Object m’()

m()

Synchronizer Queue

The diagrammatic notation will use Booch class diagrams [8]. A dotted cloud represents a class and if it is an abstract class a triangular adornment should appear inside the cloud. Containment relationship is represent by a line with a black circle in the container side. Uses relationship is represented by a line with a open circle in the using side. Inheritance relationship is represented by an arrow pointing to the base class. A template class is represented by a dotted cloud with a dotted rectangle, the template arguments. A dotted cloud with a solid rectangle represents a template instantiation.

Object Synchronization Data

preControl() postControl()

N Synchronization Predicate status

Figure 2: Pattern Structure. The main participants in the Customizable Object Synchronization pattern are:

3.1 Concern Layer The framework considers two concern components: object synchronization and active object. Object synchronization component supports variations of optimistic and pessimistic synchronization policies for object invocations. Active object component defines an object with an internal activity which selects pending invocations for execution.

 Sequential Object. Contains the sequential code and data, where accesses should be synchronized.  Synchronization Interface. Is responsible for the synchronization of invocations to the Sequential Object. It uses the services provided by the Synchronizer. It creates a Synchronization Predicate object for each invocation.

Concern component description is twofold: pattern and implementation description. The pattern description emphasizes on the design abstraction implemented in the component and its properties. The implementation description emphasizes on how the pattern is implemented in the concern layer. Some of the classes in the pattern description are not implemented by the concern layer, so, they do not appear in the implementation description. Moreover, the implementation description may introduce new classes to support further combination at the composition layer.

 Synchronizer. It decides whether an invocation may continue, stop or should be delayed. Operations preControl and postControl control the order of invocations.  Queue. Contains Predicate objects of It is passed to each new Predicate by the Interface.

The pattern description uses the object-oriented design patterns format in [4]. It is also described how the concern component accomplishes the properties required for the concern layer.

Synchronization pending invocations. Synchronization Synchronization

 Synchronization Predicate. Identifies the invocation and contains its current status, (attribute status), which can be: pre-pending, executing,

3.1.1 Object Synchronization Component The Object Synchronization component implements the Customizable Object Synchronization pattern which is described in [9]. 3

combination at the composition layer were introduced. Synchronized Invocation contains the common part of invocations, their status. To avoid template propagation Synchronization Predicate was defined as an abstract class hav Object Synchronization Data. Provides ing Synchronization Predicate Template global object synchronization data. It may as a subclass. Synchronization Predicate use the Sequential Object to get syn- Template uses Queue, the chronization data. It is passed to each containment relationship in the the pattern description will new Synchronization Predicate by the be defined at the composition layer. Synchronization Interface. post-pending and terminated. It also defines the synchronization semantics of an invocation, which determines whether the invocation should proceed, be delayed or terminated.

Properties Collaborations

The Object Synchronization component has the properWhen method m is invoked, a Synchronization ties required by concern components: Predicate object is created by the Synchronization Interface. Afterwards, it invokes preControl  Independence. Object synchronization is decoupled and postControl on the Synchronizer, respecfrom object functionality which is implemented in tively, before and after method m’ is executed on the Sequential Object. It will be shown at the Sequential Object. To evaluate synchronization composition layer that it is also independent of the conditions (operations preControl and postControl) concurrency concern. the Synchronizer interacts with Synchronization  Abstraction. The component supports pessimistic Predicate. The Synchronization Predicate policies, which synchronize invocations before access may use the synchronization data in other pending in(operation preControl), and optimistic policies, vocations, iterating on Queue, or in the Object which synchronize invocations after access (operaSynchronization Data. tion postControl). These policies are abstractImplementation Description ed by Synchronizer. The component also supports several object-specific customizable policies, The Booch class diagram in Figure 3 illustrates the struce.g. readers/writers or producer/consumer, which are ture of the Object Synchronization component: abstracted by Synchronization Predicate and Object Synchronization Data. Synchronization Interface

Synchronized Invocation

 Explicit Interface. The component’s stable part is the participants interactions which are encapsulated by Synchronization Interface. This follows the object-oriented design principle stating that variations should be “objectified” such that polimorphism can be used.

status

Synchronizer Synchronization Predicate A

3.1.2 Active Object Component

SYNC_INVOCATION

SYNC_INVOCATION Queue

Synchronization Predicate Template

The Active Object component implements the Active Object pattern described in [10].

Object Synchronization Data

Intent The Active Object pattern decouples method invocation from method execution. An active object holds an internal activity which selects pending methods for execution.

Figure 3: Component Structure.

Comparing with the pattern description, class Structure and Participants Sequential Object is missing. It will be defined The Booch class diagram in Figure 4 illustrates the strucat the application layer. Some containment relationships ture of the Active Object pattern: of Synchronization Interface are also missing. Subclasses of Synchronization Interface, to be The main participants in the Active Object pattern are: defined at lower layers, will contain Sequential Data, Queue and Object Synchronization Data.  Sequential Object. Contains the sequential code and data which are shared by concurrent activiNew classes, Synchronized Invocation ties. to support and Queue, 4

Active Interface

Sequential Object

Future m()

Active Interface

m’()

Scheduler

ACT_INVOCATION

dispatch()

Queue

Scheduler A

ACT_INVOCATION Scheduler Template dispatch()

Queue N

Method Object status

Method Object

Active Invocation status

Figure 4: Pattern Structure.

 Active coupling Object Method

Figure 5: Component Structure. Interface. Is responsible for demethod invocation to the Sequential from method execution. It creates an Object for each invocation.

 Independence. Active Object decouples object concurrency from object functionality which is implemented in Sequential Object. It will be shown at the composition layer that it is also independent of the synchronization concern.

 Scheduler. Triggers the execution of Method Objects associated with pending invocations (operation dispatch).

 Abstraction. It supports a single policy of object concurrency, active object. It does not need to abstract passive object policy since Sequential Object is already passive.

 Queue. Contains the Method Objects of pending invocations.  Method Object. Identifies the invocation and contains its current status, (attribute status), which can be: pending, executing and terminated. It contains the context necessary to execute the invocation.

 Explicit Interface. The component’s stable part is the participants interactions which are encapsulated by Active Interface.

 Future. A call to an active object is asynchronous. It is returned to the caller for future synchronization. 3.2 Composition Layer The framework has two composition components: active synchronized object and passive synchronized object. The Collaborations former integrates object synchronization component with When method m is invoked a new instance of Method active object component, while the latter adapts (integrates) Object is created and inserted in the Queue. A Future the object synchronization component for passive objects. object is returned to the caller. Afterwards the caller has to Invocations should have the semantics of the synchronize with the Future to obtain the result values. composition. Figure 6 shows the use of inThe Scheduler selects a pending Method Object heritance (multiple) to adapt/compose invocations. and starts its execution. Method Object execution pro- For instance, Active Synchronized Invocation ceeds on the Sequential Object. holds a Method Object and a Synchronization Predicate. The new classes should be redefined to supImplementation Description port the composition semantics, e.g. garbage collection of The Booch class diagram in Figure 5 illustrates the struc- terminated invocations. ture of the Active Object component: Figures 7 shows the interface hierarchy. Inheritance The rational behind the implementation at the concern (multiple) is also the chosen composition technique. layer is similar to the Object Synchronization implementaA Queue object is defined to be shared by components. tion. It corresponds to Queue, Queue Properties and Queue classes described in figThe Active Object component has the properties required ures 2, 3, 4 and 5. The new subclasses should be redefined to support the composition semantics and properties, e.g. by concern components: minimal interface.

5

CONCERN LAYER

X_Status preControl(Pass_Sync_Inv*); // defines postControl X_Status postControl(Pass_Sync_Inv*);

Synchronized Invocation

Active Invocation

private: // invocation queue Queue queue_; COMPOSITION LAYER

Active Synchronized Invocation

// ACE synchronization mechanisms ACE_Mutex mutex_; // mutex ACE_Mutex cond_mutex_; // mutex for condition ACE_Condition_Mutex cond_; // condition

Passive Synchronized Invocation

};

Figure 6: Active and Passive Invocation Hierarchy. CONCERN LAYER

Active Interface

Execution of preControl on the Synchronizer is a mutual exclusion implemented by mutex . When necessary, invocations are delayed in cond .

Synchronization Interface

Active Synchronization Interface

// pre-control phase int Pass_Sync_Int::preControl(Pass_Sync_Inv* inv) { X_Status status; // execution status do { // begin mutual exclusion mutex_.acquire();

Passive Synchronization Interface

COMPOSITION LAYER ActiveSynchronized Invocation

PassiveSynchronized Invocation

Queue

// verify compatibility status = sync_->preControl(inv);

Queue

// end mutual exclusion mutex_.release();

Figure 7: Active and Passive Interface Hierarchy.

// if there are incompatibilities wait if (status == DELAY) { cond_.wait(); cond_mutex_.release(); }

3.2.1 Passive Synchronized Object Component

} while (status == DELAY); //retry

This component has the properties required by composition components:

// return result return status; }

 Consistency. Invocations to passive objects proceed using the caller activity. So, the Passive Synchronization Interface is concurrently accessed by several activities which may result on data corruption. This is a consistency problem which results from integrating synchronization in a passive object. The following code shows the implementation of mutual exclusion in methods preControl and postControl to consistently integrate Object Synchronization with Passive Object. It also implements delay and awake of invocations in the passive context. Identifier names have been shortened.

Execution of postControl on the Synchronizer is also a mutual exclusion. When necessary invocations are delayed in cond and awaked whenever another invocation finishes execution. Awaked invocation should re-evaluated synchronization conditions. // post-control phase int Pass_Sync_Int::postControl(Pass_Sync_Inv* inv) { X_Status status; do { // begin mutual exclusion mutex_.acquire();

The code below defines the Passive Synchronization Interface where the ACE library [7] is used to support mutual exclusion.

// verify compatibility status = sync_->postControl(inv);

// defines a passive synchronizer interface class Pass_Sync_Int : private Sync_Int { public: // defines a passive synchronized object // Synchronizer is passed to superclass constructor Pass_Sync_Int(Synchronizer* sync); protected: // creates an invocation Pass_Sync_Inv* createInv( Sync_Pred_T* pred);

// end mutual exclusion mutex_.release(); // if there are incompatibilities wait if (status == DELAY) { cond_.wait(); cond_mutex_.release(); } else // only if CONTINUE or ERROR // awake pending invocations cond_.broadcast(); } while (status == DELAY); //retry

// defines preControl

6

// return result return status;

// post-control // if active invocation status is terminated if (inv->getActStatus() == Act_Inv::TERM) // evaluate postControl int_->postControl(inv);

}

 Minimal Interface. Class Passive Synchronization Interface defines three operations, createInv, preControl and postControl, to be used by the final application programmers. Note, from the code above, how invocation execution retry is hidden from final programmers.

}

The code below defines the Active Synchronization Interface. Contrarily to the passive case, it is not necessary to explicitly re-execute the synchronization code while the result is DELAY: this is done by the Sync Scheduler. Furthermore, mutual exclusion is easily provided by the internal scheduler activity and invocation wait is implemented by moving the invocation to the end of the queue.

3.2.2 Active Synchronized Object Component This component has the properties required by composition components:

// pre-control phase int Act_Sync_Int::preControl(Act_Sync_Inv* inv) { X_Status status;

 Consistency. To consistently integrate Active Object and Synchronization Object components a subclass of Scheduler should be defined. The Active Synchronization Interface should also support a mutual exclusion on accesses to Synchronizer.

// it is not necessary to define a mutual // exclusion, synchronization code is being // executed by the scheduler internal activity // verify compatibility status = sync_->preControl(inv); // if there are incompatibilities move // invocation to end of queue if (status == DELAY) moveEnd(inv);

Since Scheduler is responsible for selecting and dispatching the execution of pending invocations its integration with object synchronization requires the definition of a subclass Sync Scheduler.

// return result return status; }

class Sync_Scheduler : public Scheduler_T { public: // defines a Scheduler for active synchronized objects Sync_Scheduler(Queue* queue, Act_Sync_Int *int);

// post-control phase int Act_Sync_Int::postControl(Act_Sync_Inv* inv) { X_Status status; // it is not necessary to define a mutual // exclusion, synchronization code is being // executed by the scheduler internal activity

protected: // scheduler dispatch void dispatch();

// verify compatibility status = sync_->postControl(inv);

private: // active synchronization interface Act_Sync_Int* int_; };

// if there are incompatibilities move // invocation to end of queue if (status == DELAY) moveEnd(inv); // only if CONTINUE or ERROR // Sync_Scheduler will awake pending invocations

This class is responsible for invoking preControl and postControl on the Synchronizer. The code below shows operation dispatch of the Sync Scheduler. Note that the invocation is done through the interface (int ), the interface acts as a Mediator Pattern [4] between the components.

// return result return status; }

 Minimal Interface. The programmer at the application layer only needs to invoke createInv method of Active Synchronization Interface. Invocation of methods preControl and postControl are responsibility of the Sync Scheduler and hidden from the final application programmer.

void Sync_Scheduler::dispatch(void) { // get first of pending invocations Act_Sync_Inv* inv = queue_->first(); // pre-control // if active invocation status is pending if (inv->getActStatus() == Act_Inv::PEND) // evaluate preControl if (int_->preControl(inv) == CONTINUE) // if execution can proceed

3.3 Application Layer At the application layer composition components are integrated in the application and concern components are customized.

// execute method object inv->execute();

7

3.3.1 Integration

// pre-control preControl(inv);

The Figure 8 shows the integration of composition components with a buffer object.

// invocation proceeds on sequential object buffer_->put(val); // post-control postControl(inv);

COMPOSITION LAYER

Passive Synchronization Interface

Active Synchronization Interface

}

A synchronized put invocation on an active buffer only needs to create an invocation. The Sync Scheduler will dispatch the invocation. Put Pred and Put Method are respectively, synchronization predicate and method object. A Future object is created, where the caller synchronizes immediately after invocation.

Buffer Interface A

APPLICATION LAYER

Passive Synchronization Buffer Interface

Active Synchronization Buffer Interface

void Act_Sync_Buffer_Int::put(int val) { // defines a future object Future future;

Buffer

// creates a predicate initializing it // with the object synchronization data // and creates a method object initializing it // with buffer and future Act_Sync_Inv* inv = createInv (new Put_Pred(syncData_), new Put_Method(buffer_,future,val));

Buffer Synchronization Data

Figure 8: Application Layer Integration.

// synchronize in future future->wait();

Programmers decide which component to use, Active } Synchronization Interface or Passive Synchronization Interface, and by inheritance 3.3.2 Customization they define their own, respectively, active and passive In the previous example the following classes were cussynchronized interfaces (in Figure 8 the Proxy Pattern [4] tomized: Pess Synchronizer, which defines a pesis applied). simistic policy of synchronization, Buffer Sync Data, Note that Buffer corresponds to Sequential which defines the buffer synchronization data, Put Pred, Object and Buffer Synchronization Data is a which defines the put synchronization predicate, and subclass of Object Synchronization Data, fig- Put Method, which defines the put method object. ures 2, 3 and 4. The code below shows the constructor of a passive syn- 4 Framework Features chronized buffer. A Pessimistic Synchronizer The three-layered framework presents some characterisand a Buffer Synchronization Data are created. tics which are orthogonal to the implementation language: The constructor of an active synchronized buffer is similar. object classification, layered description and layered knowledge. Any framework emphasizing separation of concerns Pass_Sync_Buffer_Int::Pass_Sync_Buffer_Int(int size) benefits from having this features. : Pass_Sync_Int(new Pess_Synchronizer()), Buffer_Int(size), buffer_(new Buffer(size)), syncData_(new Buffer_Sync_Data(buffer_)) { }

4.1 Object Classification In the framework, objects can be classified according to their properties:

A synchronized put invocation on a passive buffer is presented below. The programmer only needs to create an invocation and bound the execution on the Buffer with operations preControl and postControl. Put Pred is the synchronization predicate.

 Stable Objects represent the objects which are encapsulated within concern components and do not need to be specialized. In the example there are no stable objects, the participant’s interactions is the stable part.  Variable Objects represent the objects which need to be specialized for integration or customization:

void Pass_Sync_Buffer_Int::put(int val) { // creates a predicate initializing it // with the object synchronization data // information about arguments may be included Pass_Sync_Inv* inv = createInv (new Put_Pred(syncData_));

– Integration Objects are variable objects used for integration at composition and application layers. Interface and Invocation 8

objects are examples of integration objects. Synchronization Sequential Sync Scheduler is also an integration object Object Interface m’() m() since it integrates the Scheduler of Active Object component with the Synchronizer of Object Synchronization component. – Customizable Objects are variable objects used Synchronizer Object Synchronization preControl() for policy customization. Two kinds of cusData postControl() tomizable objects were identified: applicationspecific and object-specific. The former, rely on the application semantics, e.g. synchronizaN tion policies can use two different generic algoSynchronization Predicate rithms: pessimistic, when the object is expected pending status to have high contention, and optimistic, when the level of contention is expected to be low. An example of an application-specific object is Pess Synchronizer. Object-specific obFigure 9: Pure Pattern Structure. jects rely on the object semantics, its structure and operations. Examples of object-specific objects are: Put Pred, Buffer Sync Data 4.3 Layered Knowledge and Put Method. Associated with the layered description there is a layered knowledge allowing different framework programmers 4.2 Layered Description expertise: As a consequence of its structure, the framework can be described in terms of its layers improving framework  Concern Programmer is responsible for the definition understanding. of concern components and it should be an expert on the particular domain.  Concern Layer has two descriptions: pattern and implementation. The former describes the overall con Composition Programmer is responsible for the intecern solution. The latter presents the details of implegration of concerns components. Knowledge of commenting the concern component. position techniques and of consistent policy combinations is required. Pattern description can be completely independent of implementation details, emphasizing on the abstrac Application Programmer integrates the composition tion properties and the resulting extensibility by decomponent interface within the application and cusscribing the supported policies and showing how they tomize the concern component. The concern pattern are implemented using the customizable objects. It description emphasizing customization can be used. is also possible to include some implementation hints Moreover, pre-defined application-specific customizreducing the gap to components descriptions. For able objects may be used as well as generic objectinstance, figure 9 shows the pattern description comspecific customizable objects. For instance, a pespletely independent of implementation details, corresimistic synchronizer for the former and read/write sponding to the pattern description reducing the gap synchronization predicates for the latter. to implementation shown in figure 2. Note that queue is replaced by pending relationship and some containment relationships are not presented because they 5 Discussion are used for initializations only. The approach is centered on the domain semantics. The For the sake of space limitations, in this paper we only used the pattern description which reduces the gap between descriptions.

domain analysis allows to abstract groups of policies and identify the stable and variable parts of the concern but there is an open issue whether separation of concerns is scalable. This is an issue of current research work. However, we have successfully applied the three-layered architecture in a larger framework than the Object Concurrency and Synchronization framework as will be described in section 6.

 Composition Layer describes how concern components are integrated as well as the consistent combinations of concern policies. For the latter a table can be drawn. It should also be described the minimal interface which will be used by final programmers.

The problems described in the Introduction are solved by the three-layered architecture:

 Application Layer describes how composition components are integrated in the application and which customizable objects should be instantiated. 9

 Understandability. The three-layered architecture offers layers of knowledge and description which improve understandability. Moreover, the application programmer only needs to understand the concerns required by the application due to the independence property of concern components.

The framework allows multiple compositions, as Passive and Active Synchronized Recoverable Objects, where synchronization can be both intra- and inter-object, Passive and Active Activity Synchronization Managers, which are responsible for generation, synchronization and recovery of activities. Both, passive and active objects can associate a new activity with method execution.

 Inconsistent Specialization. The composition layer Currently the framework is being extended with the conis responsible for consistent combination of structures cern components for replication, configuration, naming and and policies. Composition components encapsulate communication. these combinations from the application programmer, which only needs to specialize the customizable ob7 Related Work jects. The work in [15] defines two properties required by scal Combinatorial Explosion. Combinations in the able software libraries: minimal building blocks and combithree-layered architecture is done at component’s nation generators. Three-layered framework minimal buildgranularity, reducing the combinatorial explosion. Ining blocks are the concern components which are combined tegration objects are specialized in the composition in the composition layer. We do not follow the generation layer as a whole, limiting the number of new subapproach since concern combination is not trivial requiring classes that need to be defined. The specialization of tailoring in a case by case basis. customizable object at the application layer also limOur approach is centered on the domain semantics while its the number of new classes due to the independence other emphasize the composition techniques. The OOram property of concern components. method [16] describe components in terms of role models and provide a synthesis mechanism which combine roles 6 DASCo Framework models. In [17] the OOram techniques are extended with The three-layered framework was defined in the context the specialization relationship. These approaches may be of an approach to the development for distributed appli- applied to the description of the three-layered framework, cations with separation of concerns (DASCo) described in where the concern component corresponds to a role model [11, 12]. and synthesis generates composition components. The DASCo method identifies in the solution space a set of concerns. A constructive, stepwise, development process is defined by establishing solutions for each concern and integrating concerns solutions. In DASCo the concerns of concurrency, synchronization, recovery, replication, naming, configuration and communication were identified. The DASCo method and its separation of concerns motivated the construction of three-layered frameworks, where concerns solutions are defined in the top layer, integration of concerns is done in the intermediate layer and the lower layer is responsible for integration in the application. The illustration example is part of a larger three-layered framework for heterogeneous concurrency and synchronization policies for distributed applications [6]. This framework considers the other concern components, besides Object Synchronization and Active Object:

Reflection is a composition technique which is provided in languages [18] and operating systems [19]. Reflection supports meta-objects which define the semantics of objects. Incremental definition of objects is achieved by changing object’s meta-objects. In [20] it is presented a reflexive framework which decompose fine-grained behavior into objects and their subsequent composition into object models. This approach differs from ours in the composition techniques used and it does not address composition problems. In [3] the problem of framework inconsistent specialization is addressed. Design solutions which cope with this problem are presented, e.g. the Abstract Factory pattern [4]. These solutions can be used in the composition layer.

8 Conclusions A three-layered framework with separation of concerns is presented and its qualities discussed. The top layer is formed by concern components which may be described as object-oriented design patterns [21]. The qualities of the concern layer, independence, abstraction and explicit interface, allow the definition of minimal components which can be reused by combination at the composition layer and customized at the application layer. The intermediate layer, composition layer, contains integration components which are responsible for the combination of concern components.

 Object Recovery. It abstracts several object recovery policies [13].  Concurrency Generation. It abstracts several concurrency generation policies, it associates activities with method execution.  Activity Synchronization It abstracts several interobject synchronization policies [14].

10

The qualities of the composition layer, consistency and min- [11] Ant´onio Rito Silva, Pedro Sousa, and Jos´e Alves Marques. Development of Distributed Applications with Separation of imal interface, allow the consistent integration of concern Concerns. In Proceedings of the 1995 Asia-Pacific Software components and their smooth integration in the applicaEngineering Conference APSEC’95, pages 168–177, Bristion. At the application layer the concern components are bane, Australia, December 1995. IEEE Computer Society customized and composition components constructively inPress. tegrated in the application. [12] Ant´onio Rito Silva, Fiona Hayes, Francisco Mota, Nino Torres, and Pedro Santos. A Pattern Language for the Perception, Design and Implementation of Distributed Application Partitioning, October 1996. Presented at the OOPSLA’96 Workshop on Methodologies for Distributed Objects.

The paper presents a small framework to illustrate the approach but the proposed architecture has already proven to work on larger frameworks [6]. This framework is publicly available from the DASCo page http://albertina.inesc.pt/˜ars/dasco.html.[13] Currently work is being done on other domains to construct and combine more concern components: replication, configuration, naming and communication.

Acknowledgments.

Ant´onio Rito Silva, Joao Pereira, and Jos´e Alves Marques. Customizable Object Recovery Pattern. In Dirk Riehle Robert Martin and Frank Buschman, editors, Pattern Languages of Program Design 3. Addison-Wesley, 1997.

[14] Ant´onio Rito Silva and Jos´e Alves Marques. Customizable Activity Synchronization Pattern, 1996. In preparation.

We would like to thank our colleagues, Francisco Rosa and Teresa Gonc¸alves for their comments which helped to improve this paper.

[15] Don Batory, Vivek Singhal, Marty Sirkin, and Jeff Thomas. Scalable Software Libraries. In Proceedings of ACM SIGSOFT’93: Symposium on the Foundations of Software Engineering, pages 191–199, Los Angeles, California, December 1993.

References [1] Ralph E. Johnson and Brian Foote. Designing Reusable Classes. Journal of Object-Oriented Programming, 1(2):22– 25, July 1988. [2] Rebecca Wirfs-Brock, Brian Wilkerson, and Lauren Wiener. Designing Object-Oriented Software. Prentice-Hall, 1990. [3] Andreas Ruping. Framework Patterns. In European Conference on Pattern Languages of Programs, EuroPLoP ’96, Kloster Irsee, Germany, July 1996. [4] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns: Elements of Reusable ObjectOriented Software. Addison Wesley, 1995. [5] Robert Martin. Designing Object-Oriented Applications Using the Booch Method. Prentice-Hall, 1995. [6] Ant´onio Rito Silva, Joao Pereira, and Jos´e Alves Marques. A Framework for Heterogeneous Concurrency Control Policies in Distributed Applications. In Proceedings of the 8th International Workshop on Software Specification and Design, pages 105–114, Schloss Velen, Germany, March 1996. IEEE Computer Society Press. [7] Douglas C. Schmidt. The ADAPTIVE Communication Environment: An Object-Oriented Network Programming Toolkit for Developing Communication Software. In 11th and 12th Sun User Group Conferences, San Jose, California and San Francisco, California, December 1993 and June 1994. [8] Grady Booch. Object-Oriented Analyis and Design with Applications. The Benjamin/Cummings Publishing Company, Inc., 1994. [9] Ant´onio Rito Silva, Joao Pereira, and Jos´e Alves Marques. Customizable Object Synchronization Pattern. In European Conference on Pattern Languages of Programs, EuroPLoP ’96, Kloster Irsee, Germany, July 1996. [10] R. Greg Lavender and Douglas C. Schmidt. Active Object: an Object Behavioral Pattern for Concurrent Programming. In John M. Vlissides, James O. Coplien, and Norman L. Kerth, editors, Pattern Languages of Program Design 2, pages 483– 499. Addison-Wesley, 1996.

11

[16] Trygve Reenskaug, Per Wold, and Odd Lehne. Working With Objects: The OOram Software Engineering Method. Manning Publications Co., 1996. [17] Dirk Riehle. Describing and Composing Patterns Using Role Diagrams. In Proceedings of the Ubilab Confereence ’96, pages 137–152, Zurich, Switzerland, December 1996. [18] Shigeru Chiba and Takashi Masuda. Designing an Extensible Distributed Language with a Meta-Level Architecture. In ECOOP ’93, pages 482–501, Kaiserslautern, Germany, July 1993. [19] Yasuhiko Yokote. The Apertos Reflective Operating System: The Concept and Its Implementation. In Proceedings of the 1992 Conference on Object-Oriented Programming Systems, Languages, and Applications, pages 414–434, Vancouver, Canada, October 1992. [20] Jeff McAffer. Meta-level Programming with CodA. In ECOOP’95, pages 190–214, Aarhus, Denmark, August 1995. [21] Ralph E. Johnson. Documenting Frameworks using Patterns. In OOPSLA ’92, Proceedings, pages 63–76, Vancouver, Canada, October 1992.

Suggest Documents