Previous article

Next article


A Rule-Based Approach to Framework Evolution

Mariela Cortés, Computer Science Department PUC-Rio. Rua Marquês de São Vicente, 225 – 22453-900, Rio de Janeiro, RJ, Brazil.
Marcus Fontoura, Computer Science Department. IBM Almaden Research Center, 650 Harry Road, 8CC/B1, San Jose, CA, 95120, USA.
Carlos Lucena, Computer Science Department PUC-Rio. Rua Marquês de São Vicente, 225 – 22453-900, Rio de Janeiro, RJ, Brazil.

space ARTICLE

PDF Icon
PDF Version

Abstract
Framework development is very expensive, not only because of the intrinsic difficulty related to capturing the domain knowledge, but also because of the lack of appropriate methods and techniques to support the evolution of the framework architecture. In this context, we introduce the concept of extension rules. Extension rules allow the addition of new features into the framework design, making sure the consistency with the applications previously instantiated. We propose the use of extension rules in combination with the refactoring approach to support framework evolution. In addition, we propose a methodology to prove the correctness of evolution processes. The approach is illustrated through Avestruz, a framework for web searching.


1 INTRODUCTION

A framework is an extensible semi-finished piece of software that represents a generic solution to a set of applications in a specific domain. A framework is composed of a kernel subsystem, which is common to all the applications that may be generated within the framework, and variation points, which represent areas of variability within a framework that can be adapted or extended to provide application specific behavior [Codenie97]. They are the means by which frameworks provide the flexibility to build many different applications within a domain. Therefore, the framework behavior is strongly bound to the behavior of the applications that may be instantiated from it.

A framework constitutes an ever-evolving representation of our knowledge of the domain in terms of variations and commonalties. A very important point is that the framework design should not start by trying to model its variability and flexibility at once. Instead, a fixed application should be designed from the framework domain and generalize it only when the fixed case is understood [Schmid99]. In this context, the most complex problem regarding framework evolution is the impact of the changes in the framework design on the rest of the system, and possible incompatibility with previously defined applications. This situation represents the principal difference to be considered between framework evolution and stand-alone application evolution: specialized rules are needed to support the framework evolution in consistence with instance applications.

Given the well-known complexity and iterative nature of object-oriented framework development, the basic philosophy described in [Batory89, Coad92] may be summarized by:

Framework development is Framework evolution

Framework evolution = Framework refactoring + Framework extension

Refactoring of source code [Opdyke92, Fowler99] is a well-known approach suggested for the development and evolution of frameworks by restructuring a program in the way that it allows other changes to be made more easily. In early development stages, framework evolution consists in the definition of a white box structure [Roberts97]. Later, immutable code can be encapsulated and parameterized by turning the framework into a black-box one. In specific situations, refactorings can be useful to implement extensions into the framework design, creating variation points [Fayad99]. The mechanics consists in turning the original behavior (kernel) of the framework in an alternative behavior that is encapsulated into a prefabricated class of the framework design. However, refactorings are not sufficient to deal with this development process. In this paper we introduce the concept of extension rules to carry out the framework extension process. On the basis of this concept, we show how the extension rules can be combined with the refactoring technique to support framework evolution, and thus, framework development.

Extension rules [Fontoura99, Cortés02, Cortés04] are based on metapatterns [Pree95], i.e., the basic principles of object-oriented software construction that describe how to construct frameworks independent of a specific domain. So-called template and hook methods represent the metapatterns required to design frameworks. A template method provides the skeleton of a behavior and a hook method is called by the template method and can be tailored to provide different behaviors. The different ways of realizing flexibility (the different types of variation points) are classified and linked to a metapattern. Metapatterns address the implementation of flexibility and abstract coupling required in frameworks at a small scale. Several design patterns are based on metapatterns [Tokuda01]. The motivation for using metapatterns [Pree95] is to provide a means to categorize and describe design patterns on a meta-level, and to support framework construction.

Metapatterns are applied in order to obtain abstract coupling in a design. They (1) provide the ability to treat several objects (chain or tree) or a single object uniformly (the Recursive pattern) and (2) introduce a lower (more abstract) coupling between classes (the Separation pattern) and methods (the Unification pattern). Thus, the extension step is carried out more efficiently through extension rules since a larger number of situations can be modeled, including those shaped through refactorings. These rules can modify the variation points structure to support the incorporation of alternative behaviors into the framework design.

Complicated changes to a program can require both refactorings and extensions. The combination of refactoring and extension rules to evolve framework designs in a controlled way is the key point of this work. These technologies are very useful in developing efficient and flexible application frameworks and they fit well into the iterative framework development process. Both refactoring and extension rules preserve the observable behavior of the original design1. The remainder of this paper is organized as follows: Section 2 describes the semantics of refactorings and extension rules. Section 3 presents the methodology proposed for the formal verification of the evolution processes (refactoring and extension rules). Section 4 illustrates how refactorings and extension rules can be applied in practice, using the Avestruz framework as an example. In Section 5 we comment on some related works. Finally, Section 6 presents our conclusions and future research directions.

2 EVOLUTION PROCESS

In [Butler01], framework development is considered equivalent to the evolution process involving the execution of two tasks: restructure and extension. In this work we propose the use of the refactoring technique [Opdyke92, Fowler99] and extension rules [Fontoura99, Cortés02, Cortés04], respectively, to support the execution of these tasks. We consider both techniques as evolution processes which are used to restructure the code and to add new abstractions.

These evolution processes may be used to avoid the architectural drift problem [Codenie97] by changing the variation point structure of the system. This phenomenon occurs when the framework does not support the required customization and the application developers need to violate its structure. As a consequence, the application tends to drift away from the framework architecture. When the design modeled by the application is not a valid instance of a framework, evolution processes may be applied to add flexibility into the framework design, therefore, promoting its reutilization but preserving the original behavior, in the computational sense. The framework flexibility is based on the variation point structure that can be accessed by the users (application developers). Evolution processes can be considered behavior-extending transformations, since the cardinality of the application set is increased after its application.

2.1. Refactoring

The refactoring activity involves the redesign of a program unit to take advantage of good practices in design, such as design patterns, to improve it. Refactoring is a technique that also plays a major role in Extreme Programming [Roock00] and can occur at various times throughout the development process. In this section, several refactorings that support programming and evolution activities are illustrated.

The transformation represented in Figure 1 represents the Push Up Method refactoring that moves a common behavior to the abstract superclass [Fowler99] to avoid the duplicated code problem. In this example, since the same method M() belongs to the classes A and B, a new superclass is created and the redundant method is moved.

Figure 1. Application of the refactoring Push Up Method

In the resultant class hierarchy the common behavior is concentrated in the superclass. Meanwhile, specific and additional behavior is added to the subclasses, avoiding code redundancy. Based on the new structure, new variant behavior can easily be modeled by the addition of a variation points to the superclass.

A large part of Fowler’s refactorings [Fowler99] describes methods to package code properly. The key refactoring in this category is Extract Method (Figure 2), which takes a code fragment and turns it into its own method. Subsequently, a call to the new method is used to replace the removed fragment.

Figure 2. Extract Method refactoring

Extract Method changes the system structure through the incorporation of the Unification metapattern [Pree95] into the design, where the old method M1() is transformed into a template method, that invokes the new (hook) method M2(). As it will be shown later, this refactoring is used in the mechanics of several extension rules.

A natural relation between patterns and refactorings is presented in the design patterns catalogue by Gamma et al. [Gamma95]: “Patterns... supplies targets for your refactorings”. In other words, refactorings allows designers to focus on basic patterns when they are developing software projects. Patterns can be added through refactorings: “… refactorings turn explicit the design patterns that are subjacent into the code” [Gamma95]. The use of design patterns has costs related to complexity and indirection. For this reason, design should be as flexible as needed, not as flexible as possible.

Refactorings have been shown to directly implement certain design patterns [Tokuda01]. Examples of refactorings with this property are Replace Type Code with State/Strategy and Form Template Method [Fowler99]. In the rest of this section we present some of these refactorings2.

Replace Type Code with State/Strategy implements directly the transformation that incorporates the State/Strategy pattern into the design (Figure 3). This refactoring substitutes the code type of a generic object with a state object, adding one subclass for each type.

Figure 3. Replace Type Code with State/Strategy refactoring

In this way, the variability that before was manipulated through mechanisms as switch-case features, are manipulated by a class hierarchy in the target design. Replace Conditional with Polymorphism [Fowler99] describes a similar situation. Both of these refactorings are equivalent to the extension rule Add Unification Pattern (compare Figure 3 with Figure 5 to see the similarities).

The second example presents the class structure of the Template Method pattern. This pattern defines a skeleton of behavior in a method template, which can be tailored to provide different behavior through hook methods in subclasses. This pattern is based on the Unification metapattern [Pree95].

Form Template Method is a refactoring that incorporates the Template Method pattern into the design. This refactoring can be applied when two methods in subclasses (the class hierarchy already exists) execute similar steps in the same order, yet the steps are different. In the target design, the common code is factored in the superclass and the variant behavior is implemented in the subclasses, preventing the duplication.

2.2. Extension Rules

Extension rules are used to extend the framework behavior, making it possible to instantiate a greater number of applications. These rules implement transformations that alter the framework variation point structure.

The variation point structure introduces variability that is transparent outside the subsystem, either by inheritance or by composition. Using extension rules during the evolution process, two situations are possible: whether the base class of the variation point subsystem is introduced as a new class, or whether the responsibility of an existing class is extended by the responsibility of the base class. In the first case, we speak of an expanding transformation since we have expanded the original class structure by a new class. In the second case, we speak of an extending transformation, since we have extended an original class by new responsibilities.

The extension rules are based on framework metapatterns [Pree95], which implement variation points as a combination of template and hook methods [Pree91, Gamma95, Pree95]. A template method3 provides the skeleton of a behavior. A hook method is called by the template method and can be tailored to provide different behaviors. Currently, there are four extension rules, which automate the incorporation of the basic framework patterns proposed by Pree [Pree95]. In the remainder of this section we present each of them by means of a set of short descriptions including:

  • The description of the associated metapatterns.
  • The motivation to describe why the rule should be implemented.
  • The solution proposed.
  • The mechanics of how to carry out the evolution.

The evolution processes are illustrated in terms of UML class diagrams. We use visual representations for the UML-F tags framework and application [Fontoura01].

Add Hook Rule

Description. This rule is used to incorporate a hook method into the framework design to implement a new variation point.

Motivation. The framework architecture does not support the required customization because a method of the kernel subsystem is not able to realize the behavior required for the application developer.

Solution. The instance application needs to change the implementation of a kernel method. In this way, each application can define alternative behaviors. Figure 4 illustrates this process.

Figure 4. Application of Add Hook rule

Mechanics. The mechanics can be resumed in the following steps:

  1. Create a subclass for each instance application, if it does not already exist.
  2. Create subclass methods that override the original methods.
  3. Make the superclass method abstract.

Add Unification Pattern Rule

Description. This rule is used to incorporate the Unification pattern into the design. This pattern occurs when both the template and hook methods belong to the same class.

Motivation. Application developers need to add flexibility to existing methods. The framework architecture does not support the required customization because the behavior supplied by the kernel methods is not completely adequate to the behavior required for the application developer. This might happen in any of the following situations:

  • New insights in the domain. Some application specific concepts may become general concepts and must be incorporated into the framework;
  • New design insights. Some design issues that were neglected in the framework’s initial design phase are discovered and need to be incorporated into the framework kernel.

Solution. Variant steps are implemented as a combination of template-hook methods. The hook method executes the special behavior required by the application developer. The method might be created through the Extract Method refactoring [Fowler99], which replaces a fragment of code with a call to the newly created method.

Figure 5. Application of Add Unification Pattern rule

Mechanics. The mechanics may be summarized in the following steps (Figure 5):

  1. Create the new method using the Extract Method refactoring [Fowler99].
  2. For each application, if it does not already exist, create a new subclass.
  3. Move the implementation of the new method to each subclass using the Push Down Method refactoring [Fowler99].
  4. Make the superclass method abstract.

Add Separation Pattern Rule

Description. This rule is used to incorporate the Separation pattern into the design. This pattern occurs when the template and hook methods belong to different classes. The application of this rule transforms a fragment of code from a method in the core into a hook method.

Motivation. The motivation here is the same as the one in Add Unification Pattern¸ but in this case the final design is more flexible – since the template and the hooks belong to different classes, adaptations can happen during runtime.

Solution. Create a new variation point method in a separate hook class (Figure 6). This variation point must be extended by composition. In the obtained design, an additional class is required to host the template method upon adding to the variation point subsystem.

Figure 6. Add Separation Pattern rule

Mechanics. The evolution process in this case may be summarized in following:

  1. Create the new method using the Extract Method refactoring [Fowler99].
  2. Create a new class using the Extract Class refactoring [Fowler99].
  3. Create a subclass for each instance application, if it does not already exist.
  4. Make the superclass abstract.

Add Recursive Pattern Rule

Description. This rule is used to incorporate the Recursive pattern into the design. This pattern occurs when an object of the template class refers objects in the hook class. In particular, the template class is a descendent of the hook class.

Motivation. Sometimes, it may be useful to create object compositions. These compositions can be treated as a simple object, which are useful to modify the object behavior without modifying the class structure already existent.

Solution. Create an object composition to handle object collections in order to selectively add or modify behavior to instances (Figure 7).

In the Recursive pattern design based any number of template classes can be defined as subclasses of H. These template classes can define additional/modified behavior. Note that any number and combination of instances of template classes can be attached to instances of H descendants.

During execution time, the hook class H forwards the control to either descendant (T or T1). The trick behind this design is that T1 can modify the behavior of methods and forward the call to the object referred by the reference. Furthermore, instance variables and methods can be added. This means that the modified behavior implemented in the composite class T1 can be attached to all descendants of H. If the call is forwarded to a T object, the behavior is preserved; if the call is forwarded to a T1 object, the behavior is extended with the associated special behavior.

The obtained design is coincident with the structural pattern Composite [Gamma95]. Thus, the application of this rule is useful for incorporating the corresponding pattern into the design.

Figure 7. Application of Add Recursive Pattern rule

Mechanics. The application of this rule may be summarized in following:

  1. Create the composite class.
  2. Create the abstract superclass.
  3. Add an instance variable of the composite class in the hook class.

2.3 Comparing Refactorings and Extension rules

Refactoring activity can be very useful to support framework restructuring and extension on the basis of specific design patterns. However, two points differentiating refactoring processes and extension rules must be highlighted:

  • There are no refactorings for all design patterns (for example, no refactoring addresses the incorporation of design patterns that are based on recursive subsystems). This incompleteness in the refactoring catalogue [Fowler99] can be solved through the use of extension rules, which are based on metapatterns. Metapatterns model all the possible combinations of template and hooks methods, including the recursive composition. Consequently, more situations can be described.
  • Some refactorings are helpful in the transition of whitebox frameworks into blackbox frameworks. This process does not change the framework behavior since it simply implements restructuring and moving of code already existing in the framework. In this way, the variant behavior that already exists inside the framework becomes explicit in the design by the use of refactorings. Differently, extension rules always incorporate new variation points into the system.

Design patterns are specific instances of metapatterns, which are the simplest construction principles. Since extension rules implement the introduction of metapatterns into the design, design patterns may be introduced using the same mechanics. Figure 8 describes some patterns that may be introduced using refactorings and extension rules. Each pattern is associated to the correspondent higher level metapattern.

Figure 8. Metapatterns, patterns, extension rules and refactorings

All referred patterns can be introduced through the extension rules, including those that can be generated using specific refactorings. Moreover, the applicability of extension rules is extended to a larger set of different situations than refactorings. For example, to support the introduction of patterns based on recursive structures.

3 FORMAL VERIFICATION

Ideally, the behavior preservation of refactorings should be proven formally [Tokuda01]. In practice and in previous research, this generally has not been done. Instead of formal proofs, the approach originally proposed by Barnejee and Kim for database schema evolution has been adopted [Banerjee87]. In [Opdyke92] a set of seven invariants to preserve behavior for refactorings was proposed, but no proof that these invariants preserved program behavior was presented.

In this paper we propose a formal methodology to verify the correctness of the evolution processes (refactoring and extension rules). In this sense, the system behavior, both before and after the evolution process, is formally defined. Based on the se formal descriptions, equivalence relations are used to check if the two programs may be considered equivalents. The methodology uses CCS [Milner89] as the formalism for the description of the program behavior and model checking techniques [CWB04] to establish the behavioral equivalence. The methodology proposes the following steps for the formal behavior verification:

  1. Create the state diagrams on the basis of the state of variables used by the program, before and after the program transformation. The diagram denotes the sequence of states. Each state denotes a particular situation of the variables manipulated by the program. To facilitate this step the statements in the program are labeled.
  2. Add the transitions that determine the control sequence throw in the program execution to the diagrams. The transitions may be classified into two groups:
    1. Named. These transitions connect different states in the diagrams. These transitions are denoted with different symbols in the diagrams.
    2. Invisibles. These transitions connect equivalents states (initial and final) in the diagrams. These transitions are denoted with the t (tau) symbol.
  3. Translate the diagrams into a CCS specification [Milner89].
  4. The two formal specifications are incorporated in the CWB (Edinburgh Concurrency Workbench) model checking tool. CWB [CWB04] is an interactive system that allows the user participation throw commands to check properties and to make analyses. The command eq is used to check the behavioral equivalence between processes. The system returns true if the behaviors of the process may be considered equivalents in the observational sense, and false in another case.

In following, we apply the proposed methodology to verify the correctness of a refactoring process. In this very simple example we illustrate the wrong use of the Rename Method refactoring. The original code with the labels and the corresponding sequence of states is presented in Figure 9.

Figure 9. Original code and state sequence before the refactoring process

The refactoring Rename Method is applied to rename the function F2 to F1. Note that a method with the same name and parameters already exists in the class Super. Thus, the behavior of the modified code possibly was modified. The code after the evolution process is presented in Figure 10.

Figure 10. Transformed code and state sequence after the refactoring process

In the next step, the transitions in both sequences are classified as named or invisibles. The resultant diagrams of transitions are depicted in Figure 11. In this case all transitions are named.

Figure 11. Transition diagrams before and after the refactoring process

Figure 12 presents the CCS description of the transition diagrams described in above. This description is used as input for the CWB model checking tool. In the CCS formalism each state in the diagram is modeled using the agent abstraction. Lines 1 through 7 simply bind agent identifiers to process expressions. These expressions consist in action_name. agent_name next. Action_name represents a transition in the diagram, and the agent_name represents the target state which can be derivate by the transition.

The line 8 tests the two agents identified by L1 and L11 for observational equivalence, also known as weak bisimilarity

Figure 12. CWB session for the Rename Method refactoring

 

The observational equivalence relation between the descriptions is determined with the eq command. Finally, the system responds with the result false (line 9) and the session conclude. In this way, on the basis of the methodology proposed, is possible determine that the application of the Rename Method refactoring in this case is not behavior preserving.

4 STUDY CASE: AVESTRUZ FRAMEWORK

The proposed approach is illustrated through the Avestruz framework, which is an ongoing project at the TecComm Laboratory (PUC-Rio) (http://www.teccomm.les.inf.puc-rio.br). Avestruz is a search engine framework designed to process and to parse HTML pages. The processing determines whether particular words are localized in the text of the pages. In the crawling process, links are extracted and stored for future searching. This is done in parallel, using several machines. The initial architecture of the framework is the simplest one that allows accomplishing these requirements. The core of the system is the ClScanner class. It is responsible for localizing the URL of the initial page of the site and transferring the control to the HTML processor module to parse the page. The abstract class ClHTMLDoc defines a variation point to allow independence between the framework and the HTML parser used in the custom applications. Figure 13 shows the class model and the semantics of the initial framework design.

When the framework finishes parsing a page it must recover the next page to be visited using the set of links that was extracted in the parsing process. During crawling, the index structures are stored by the ClScanner class according to the order of appearance in the HTML documents. Later, during runtime, applications need more flexibility and efficiency for recovering the search results. Then, we use extension rules to create a new variation point in the framework that allows the customization of the strategy for storing the index information.

Figure 13. Searching engine framework

We use Add Separation Pattern to create a new entity decoupled from ClScanner class, allowing customizations in runtime. Figure 14 illustrates the diagram and semantics for the Avestruz modules, with the changes generated by the evolution transformation. During this evolution process, the methods of the ClScanner class are transformed into template methods and their specific behavior is translated to the ClList class.

Figure 14. Adding flexibility for the link processor module

From the custom application point view, the transformation is behavior-preserving since the new structure of the ClScanner (abstract class) and ClList (concrete class from the user application) is suitable as the original design. On the other hand, the framework behavior is extended because a new structure of template and hooks methods was created during the evolution process. In the current design, overriding the hook methods in the ClStoreStrategy class can modify the behavior of the template class ClScanner. In its initial design, the ClStoreStrategy class was specialized to use lists. Later, a new strategy was developed for storing the page links, ClSmartStorage, which implements a more intelligent strategy that determines whether a link is relevant for the current search. Thus, the search is restricted to a specific site, avoiding searching in pages outside of the current scope.

Frequently, a web site includes repeated pages within a collection of related pages. When the framework was tested for different applications, in several situations the best strategy was to ignore the repeated pages. For that, a new abstraction was required to model a permanent memory of the visited pages, adding new requirements to the design. Consequently, we use extension rules to add this evolution to the framework. In this case, we use Add Separation Pattern rule to create a new class decoupled from ClScanner, ClPagesKeeper, to retain the history of the visited pages. The result for this transformation is shown in Figure 15. The semantics of the scan() method in ClScanner class is modified by the application of the extension rule because the specific behavior that implements the memory of visited pages is extracted and moved to ClRealKeeper class. If no memory is needed, the situation may be modeled with the new application class ClDummyKeeper.

Figure 15. Adding a permanent memory into the design

When the search of relevant pages is finished, the search results must be reported to the user. In the initial solution, the results were returned through a DOS window. To improve the design and to avoid the mixing of the result reporting with the parsing code, we create a new entity representing the channel that carries out the result reporting. This step of evolution is a behavior-preserving transformation because it improves the framework design but does not add semantics and does not modify the variation point structure. Consequently, refactorings come into play to support this evolution step. The most suitable refactoring for this situation is Extract Class [Fowler99]. In consequence, the ClScreenSender class is extracted from ClScanner class to show the results via DOS window. In this way, the original class is transformed in two classes with clear responsibilities: ClScanner and ClScreenSender.

Usually, the custom applications require the return of formatted results that may be received via e-mail when the search is finished, or via browser in processing time. Variations in the channel implementation may be required by framework instances. Then, extension rules can be used to turn the channel into a variation point. This can be done by the application of Add Unification Pattern to create the abstract class ClSender (Figure 16).

Figure 16. Defining a channel for the result reporting

Now, the new framework design allows the customization of several variation points, however, the answer processor is still insufficient in some situations. In particular, the ClScanner class is defined to accept only a ClSender object. It implies that the report of the searching results is realized through only one channel. However, in several situations reporting through more than one channel may be useful, e.g., mail and browser simultaneously. To reach this flexibility, new semantics must be added into the design. Therefore, extension processes are used to describe this step of evolution. The more suitable rule is Add Recursive Pattern, because it allows creation of a group of channels used by the custom application to the result reporting, which are represented by the ClGroupSender class. Figure 17 represents the final design of the framework after the evolution process.

Figure 17. Evolution to report results throws several channels

5 RELATED WORKS

Currently, there are very few framework design methods that deal with framework evolution. A pattern-based description of some accepted approaches underlying framework design can be found in [Roberts97]. Some interesting aspects regarding framework design such as framework integration, version control and over-featuring can be found in [Codenie97].

The Refactoring Browser [Roberts97] is a tool to help maintenance of frameworks written in Smalltalk. It currently does not support extension rules, but it has an open architecture and the introduction of the extension rules and new refactoring seems to be straightforward. The design pattern tool proposed in [Florijin97] also uses refactorings to achieve framework restructuring.

Roberts and Johnson propose the development of concrete applications before actually developing the framework itself [Roberts97]. They claim that framework abstractions can be derived from concrete applications. The extension-based development process may be used to systematize this approach. An approach that integrates framework and XP is presented in [Roock00].

A model for framework development based on viewpoints is proposed in [Fontoura00]. This method was used as our first approach to framework design, and the current version has been refined through the development of several case studies.

In [Schmid99] it was developed an approach to framework design that considers framework design as a generalization problem. Initially, it is fixed a class structure, which models a specific application from the framework domain and transforms it by a sequence of generalizing transformations, each one introducing a variation point into the class structure. Before the generalization, the class structure usually contains an aspect as a frozen spot in the form of a specialized class or responsibility as a part of a class; in some cases, an aspect is missing before the transformation. After the transformation, the class structure contains a variation point subsystem that represents this aspect. A generalization transformation [Schmid96] introduces the variability and flexibility of a variation point into the class structure. Extension rules can be used to support these generalization transformations.

In relation to the formal aspect, a theory for the formalization of the semantics of framework, based on the set of application-instance that can be generated, is presented in [Fontoura99]. This semantics is defined using sets theory and meaning functions. However, this theory does not permit the establishment of property semantics in relation the behavior. In [Opdyke92], the processes of refactoring are verified in accordance with a set of program properties, derivatives of the database area, added to a property that refers to equivalence semantics between operations. This latter property is not formally verified.

6 CONCLUSIONS

In this paper we define a set of rules to support the flexibilization of the variation point structure based on the metapattern approach [Pree95]. In addition, we show how extension rules can be combined with the well-known refactoring technique [Fowler99] to support framework maintenance and evolution. The applicability of the extension rules and refactorings is analyzed in different stages of the evolution process. Both the evolution processes: refactorings and extension rules, are transformations that can be used to avoid the architectural drift problem [Codenie97] by restructuring framework variation point structure during its evolution. As a consequence, the set of applications that may be instantiated based on the framework is enlarged, since new variation points were defined.

In addition, extension rules can be used in the context of different methodologies for framework development [Roberts97, Schmid99] to build white box frameworks [Johnson88] by generalizing from the classes in the individual applications. The rules can be useful for evolving frameworks since the immutable code can be encapsulated and parameterized by converting the framework into a black-box one.

The paper also proposes a methodology for the formal verification of the correctness of the evolution processes. The methodology is based on the CCS formalism [Milner89] to specify the behavior of programs. This formal specification will allow us to think about process properties using model-checking techniques, for example, to establish the behavioral equivalence of programs. This methodology, in conjunction with structural verification (i.e., syntactic analyses, metrics, etc.), can be very useful for understanding the evolution process and their consequences on the framework design and its instance applications.

The ongoing work consist in the extension of an already existing tool for software refactoring also supporting extension rules and the elaboration of new rules for different kinds of variation points.

Footnotes

1 In computational sense, this implies that these transformations always result in legal programs equivalent to the original program.

2 Note that when refactorings are applied on frameworks, the variation point structure may be modified, affecting the set of custom applications.

3 Template method must not be confused with the C++ template construct, which has a completely different meaning.


ACKNOWLEDGMENTS

This work is being supported in part by the National Research Council of Brazil (CNPq).

REFERENCES

[Batory89] Batory D., Barnett J., Roy J., Twichrll B., Garza J. “Construction of file management systems from software components”. Proceedings of COMPSAC. 1989.

[Banerjee87] Banerjee J., Kim W. “Semantics and Implementation of Schema Evolution in Object-Oriented Databases”. Proceedings of the ACM SIGMOD Conference. 1987.

[Butler01] Butler G., Xu L. “Cascaded Refactoring for Framework Evolution”. Proceedings of 2001 Symposium on Software Reusability. ACM Press, p. 51-57. 2001.

[Coad92] Coad P. “Object-oriented patterns”. Communications of the ACM, v.35, n.9, p. 152-159. 1992.

[Codenie97] Codenie W., Hondt K., Steyaert P., Vercammen A. “From Custom Applications to Domain-Specific Frameworks”. Communications of the ACM, 40(10), 71-77. 1997.

[Cortés02] Cortés M., 2002. “Computational Support for the Evolution of Object Oriented Frameworks”. Proceedings of the Doctoral Simposium of the International Conference of Software Engineering. Orlando, Florida.

[Cortés04] Cortés M., Fontoura M, Lucena C. “Refactoring and Unification Rules to Assist Framework Evolution”. Upgrade - The European Journal for the Informatics Professional. Novatica, vol. v, no. 2, pp. 49-55. March 2004.

[CWB04] CWB Model Checking. Available in: http://www.dcs.ed.ac.uk/home/cwb/.

[Fayad99] Fayad M., Schmidt D., Johnson R. “Application Frameworks”. Building Application Frameworks. New York: Wiley. p. 3-28. 1999.

[Florijin97] Florijin G., Meijers M, van Winsen P. “Tool Support for Object-Oriented Patterns”, ECOOP’97, LNCS 1241, Springer-Verlag, 472-495. 1997.

[Fontoura99] Fontoura M. A Systematic Approach to Framework Development. Ph.D. Dissertation, Computer Science Department, Pontifical Catholic University of Rio de Janeiro. 1999.

[Fontoura00] Fontoura M., Crespo S., Lucena C., Alencar P., Cowan D. “Using Viewpoints to Derive Object-Oriented Frameworks: a Case Study in the Web-based Education Domain”. Journal of Systems and Software, 54(3), 239-257. 2000.

[Fontoura01] Fontoura M., Pree W., Rumpe B. The UML Profile for Framework Architectures, Addison-Wesley. 2001.

[Fowler99] Fowler M. Refactoring: Improving the design of existing code. Addison-Wesley. 1999.

[Gamma95] Gamma E., Helm R., Johnson R., Vlissides J. Design patterns. Elements of Reusable Object-Oriented Software. Addison-Wesley. 1995.

[Milner89] Milner, R. Communicating and concurrency. Prentice-Hall, Hemel Hempstead. 1989.

[Opdyke92] Opdyke W. Refactoring Object-Oriented Frameworks, Ph.D. Dissertation, Computer Science Department, University of Illinois, Urbana-Champaign. 1992.

[Pree91] Pree W. Object-oriented versus conventional construction of user interface prototyping tools. Doctoral thesis, University of Linz.

[Pree95] Pree W. Design Patterns for Object-Oriented Software Development, Addison-Wesley. 1995.

[Roberts97] Roberts D. and Johnson R. Evolving Frameworks: “A Pattern Language for Developing Object-Oriented Frameworks”, Pattern Languages of Program Design 3, Addison-Wesley, R. Martin, D. Riehle, and F. Buschmann (eds.), 471-486. 1997.

[Roberts97] Roberts D., Brant J., Johnson R. “A Refactoring Tool for Smalltalk”. Theory and Practice of Object Systems, Volume 3, Issue 4. 1997.

[Roock00] Roock S. “eXtreme Frameworking - How to aim applications at evolving frameworks”. Proceedings of the XP’2000 Conference. 2000.

[Schmid96] Schmid H. “Design patterns for constructing the hot spots of a manufacturing framework”. Journal of Object-Oriented Programming, v. 9, n.3, p. 325-37. 1996.

[Schmid99] Schmid H. “Framework design by systematic generalization”. Building Application Frameworks. New York: Wiley. pp. 353-378. 1999.

[Tokuda01] Tokuda L., Batory D. Evolving Object-Oriented Designs with Refactorings. Automated Software Engineering, v.8, p. 89-120. 2001.

About the authors





Mariela Cortés received her BSc degree from the National University of La Plata (UNLP) Argentina, MSc degree from the Militar Institute of Engineering (IME), Brazil, and the PhD degree in Computer Science from the Pontifical Catholic University of Rio de Janeiro (PUC-Rio), Brazil. Her current research interests include object-oriented design and multi-agents systems development. At present, she is adjoint professor and researcher at the State University of Ceará (UECE). Email: mariela@larces.uece.br.

 





Marcus Fontoura had led several framework projects and specializes in Web-based software development and service-oriented architectures in the realm of IBM's Almaden Research Center. Before that he has held research positions at the Computer Systems Group of the University of Waterloo, Canada, and at Princeton University's Computer Science Department. Email: marcusfontoura@sbcglobal.net.

 



  Carlos Lucena received the BSc degree from the Pontifical Catholic University of Rio de Janeiro (PUC-Rio), Brazil, in 1965, the MMath degree in computer science from the University of Waterloo, Canada, in 1969, and the PhD degree in computer science from the University of California at Los Angeles in 1974. He has been a full professor in the Departamento de Informatica at PUC-Rio since 1982. His current research interests include software design and formal methods in software engineering. He is member of the editorial board of the International Journal on Formal Aspects of Computing. Email: lucena@inf.puc-rio.br.

Cite this column as follows: Cortés M., Fontoura M., Lucena C. “A Rule-Based Approach to Framework Evolution”, in Journal of Object Technology, vol. 5, no. 1, January-February 2006, pp.83-103, http://www.jot.fm/issues/issue_2006_01/article3


Previous article

Next article