Refactorings to Evolve Reusable Object-Oriented Software

 

Lance Tokuda

University of Texas at Austin

TAY 3.104C, Austin, TX 78712

Tel: (512) 471-9711, fax: (512) 471-7866

Email: unicron@cs.utexas.edu

URL: http://www.cs.utexas.edu/users/unicron/research.html

 

Abstract

One barrier to software reuse is the cost of creating reusable software artifacts. Gamma's design patterns and Pree's meta patterns aid in the production of reusable object-oriented frameworks. Refactorings are behavior-preserving program transformations which can safely automate the introduction of many patterns in evolving applications. The purpose of this paper is to promote refactorings as a tool for evolving reusable software architectures.

Keywords: Refactorings, object-orientation, design patterns, hot-spot meta patterns

Workshop Goals: Information-exchange, networking

Working Groups: object-oriented components, tool support for reuse

 

1 Background

Object-oriented designers benefit from patterns research when creating reusable architectures. Gamma's design patterns capture recurring relationships between classes, objects, methods, etc. that define preferred solutions to common object-oriented design problems [Gam95]. Pree's hot-spot meta patterns are based on the identification of aspects of a software program which are likely to change from application to application (i.e. hot-spots) [Pre95]. Architectures using abstract classes and template methods are prescribed to promote reusability. Two problems with patterns are 1) the cost integrating patterns in evolving architectures and 2) the threat of creating an overly complex and inefficient architecture.

 

2 Position

The evolution of object-oriented software into reusable frameworks can be viewed as a program transformation. Many common transformations can be automated with refactorings (behavior-preserving program transformations). Refactorings reduce implementation and testing costs and allow architectures to evolve on an if-needed basis.

 

3 Approach

A refactoring is a parameterized behavior-preserving program transformation that automatically updates an application's design and underlying source code. A refactoring is typically a very simple transformation, one that has a straightforward (but not necessarily trivial) impact on application source code. An example is inherit[Base, Derived], which establishes a superclass-subclass relationship between two classes, Base and Derived, that were previously unrelated. From the perspective of an object-oriented class diagram, inherit merely adds an inheritance relationship between the Base and Derived classes, but it also checks enabling conditions to determine if the change can be made safely and it alters the application's source code to reflect this change. Applying refactorings is superior to hand-coding similar changes because it allow a designer to evolve the architecture of an existing body of code at the level of a class diagram leaving the code-level details to automation.

3.1 Design Patterns

Design patterns capture expert solutions to many common object-oriented design problems: creation of compatible components, adapting a class to a different interface, subclassing versus subtyping, isolating third party interfaces, etc. Patterns have been discovered in a wide variety of toolkits including Smalltalk Collections [Gol84], ET++ [Wei88], and InterViews [Lin92]. Refactorings have been shown to directly implement the Command, Composite, Decorator, Factory Method, Iterator, and Singleton design patterns [Tok95, Tok98a, Tok98b].

While design patterns are useful when included in an initial software design, they are often applied in the maintenance phase of the software lifecycle [Gam93]. For example, the original designer may receive new requirements imposed on a framework by a related product. Alternatively, patterns may lead to extra levels of indirection and complexity inappropriate for the original application using the framework. A number of patterns can be viewed as automatable program transformations applied to an evolving design. Examples for the following Gamma patterns have been documented: Abstract Factory, Adapter, Bridge, Builder, Strategy, Template Method, and Visitor [Tok95, Rob97, Tok98a].

Gamma et. al. note that a common design pattern pitfall is overenthusiasm: "Patterns have costs (indirection, complexity) therefore [one should] design to be as flexible as needed, not as flexible as possible." Refactorings can restructure existing implementations to make them more flexible, dynamic, and reusable, however, their ability to affect algorithms is limited. Patterns such as Chain of Responsibility and Memento require that algorithms be designed with knowledge about the patterns employed. These patterns are thus considered fundamental to a software architecture because there is no refactoring enabled evolutionary path which leads to their use. Refactorings allow a designer to focus on fundamental patterns when creating a new software architecture. Patterns supported through refactorings can be added on an if-needed basis to the current or future architecture at minimal cost.

3.2 Hot-Spot Meta Patterns

The hot-spot-driven-approach [Pre94] identifies which aspects of a framework are likely to differ from application to application. These aspects are called hot-spots. When a data hot-spot is identified, abstract classes are introduced. When a functional hot-spot is identified, extra methods and classes are introduced.

For the case of differing data, refactorings have repeatedly demonstrated the ability to create abstract classes [Opd92, Tok95, Rob97, Tok98b]. For the case of differing functionality, solutions based on template and hook methods are prescribed to provide the needed behavior. A template method provides the skeleton for a behavior. A hook method is called by the template method and can be tailored to provide different behaviors. Pree identifies seven meta patterns for template and hook methods: unification, 1:1 connection, 1:N connection, 1:1 recursive connection, 1:N recursive connection, 1:1 recursive unification, and 1:N recursive unification [Pre94].

Refactorings automate the introduction of six of these meta patterns in evolving architectures [Tok98a]. We consider the 1:N connection composition to be fundamental to an architecture. For this pattern, a template object is linked to a collection of hook objects. This implies that the template method has knowledge about how to use multiple hook methods and thus cannot be derived from the 1:1 connection composition in which the template method is coded for a single hook method.

The hot-spot-driven-approach provide a comprehensive method for evolving designs to manage change in both data and functionality. Pree notes that "the seven composition meta patterns repeatedly occur in frameworks." Thus, we expect an ongoing need to add meta patterns to evolving architectures. The addition of meta patterns is currently a manual process. Conditions are checked to ensure that a pattern can be added safely, lines of affected source code are identified, changes are coded, the system is tested to check for errors, any errors are fixed and the system is retested. Retesting continues until the expected likelihood of an error is sufficiently low. Refactorings automate the transition between designs granting architects the freedom to create simple frameworks and add patterns as needed when hot-spots are identified.

 

4 Comparison

Griswold developed behavior-preserving transformations for structured programs written in Scheme [Gri91]. The goal of this system was to assist in the restructuring of functionally decomposed software. Software architectures developed using the classic structured software design methodology [You79] are difficult to restructure because nodes of the structure chart which define the program pass both data and control information. The presence of control information makes it difficult to relocate subtrees of the structure chart. As a result, most transformations are limited to the level of a function or a block of code.

Object-oriented software architectures offer greater possibilities for restructuring. Bergstein defined a small set of object-preserving class transformations which can be applied to class diagrams [Ber91]. Lieberherr implemented these transformations in the Demeter object-oriented software environment [Lie91]. Example transformations are deleting useless subclasses and moving instance variables between a superclass and a subclass. Bergstein's transformations are object preserving so they cannot add, delete, or move methods or instance variables exported by a class.

Banerjee and Kim identified a set of schema transformations which accounted for many changes to evolving object-oriented database schema [Ban87]. Opdyke defined a parallel set of behavior-preserving transformations for object-oriented applications based on the work by Banerjee and Kim, the design principles of Johnson and Foote [Joh88], and the design history of the UIUC Choices software system [May89]. These transformations were termed refactorings. Roberts developed the Smalltalk Refactory Browser which implements many of these refactorings [Rob97].

Tokuda and Batory proposed additional refactorings to support design patterns as targets states for software restructuring efforts [Tok95]. Refactorings are shown to support the addition of design patterns to object-oriented applications [Tok95, Rob97]. Winsen used refactorings to make design patterns more explicit [Win96]. [Tok98b] demonstrated that refactorings can automate significant architectural changes when applied to real applications.

A number of tools instantiate a design pattern and insert it into existing source code [Bud96, Kim96, Flo97]. Instantiations are not necessarily refactorings, so testing of any changes may be required. Florijn and Meijers check invariants governing a pattern and repairs violations when possible. Refactorings do not have this pattern-level knowledge.

 

References

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

[Ber91] P. Bergstein. Object-Preserving Class Transformations. In Proceedings of OOPSLA '91, 1991.

[Bud96] F. J. Budinsky et.al., Automatic Code Generation from Design Patterns. In IBM Systems Journal, Volume 35, No. 2, 1996.

[Flo97] G. Florijn, M. Meijers, and P. van Winsen. Tool Support for Object-Oriented Patterns. In Proceedings, ECOOP '97, pages 472-495, Springer-Verlag, 1997.

[Gamma 93] E. Gamma et. al. Design Patterns: Abstraction and Reuse of Object-Oriented Design. In Proceedings, ECOOP '93, pages 406-421, Springer-Verlag, 1993.

[Gam95] E. Gamma et.al. Design Patterns Elements of Reusable Object-Oriented Software. Addison-Wesley, Reading, Massachusetts, 1995.

[Gol84] A. Goldberg. Smalltalk-80: The Interactive Programming Environment. Addison-Wesley, Reading, Massachusetts, 1984.

[Gri91] W. Griswold. Program Restructuring as an Aid to Software Maintenance. Ph.D. thesis. University of Washington. August 1991.

[Joh88] R. Johnson and B. Foote. Designing Reusable Classes. In Journal of Object-Oriented Programming, pages 22-35, June/July 1988.

[Kim96] J. Kim and K. Benner. An Experience Using Design Patterns: Lessons Learned and Tool Support, Theory and Practice of Object Systems, Volume 2, No. 1, pages 61-74, 1996.

[Lie91] K. Lieberherr, W. Hursch, and C. Xiao. Object-Extending Class Transformations. Technical report, College of Computer Science, Northeastern University, 360 Huntington Ave., Boston, Massachusetts, 1991.

[Lin92] M. Linton. Encapsulating a C++ Library. In Proceedings of the 1992 USENIX C++ Conference, pages 57- 66, Portland, Oregon, August 1992.

[May89] P. Maydany et.al. A Class Hierarchy for Building Stream-Oriented File Systems. In Proceedings of ECOOP '89, Nottingham, UK, July 1989.

[Opd92] W. F. Opdyke. Refactoring Object-Oriented Frameworks. Ph.D. thesis, University of Illinois, 1992.

[Pre95] W. Pree and H. Sikora. Application of Design Patterns in Commercial Domains. OOPSLA '95 Tutorial 11, Austin, Texas, October 1995.

[Tok95] L. Tokuda and D. Batory. Automated Software Evolution via Design Pattern Transformations. In Proceedings of the 3rd International Symposium on Applied Corporate Computing?, Monterrey, Mexico, October 1995.

[Tok98a] L. Tokuda and D. Batory. Automating Three Modes of Object-Oriented Software Evolution. Submitted to COOTS '99.

[Tok98b] L. Tokuda and D. Batory. Evolving Object-Oriented Architectures with Refactorings. Submitted to ICSE '99.

[Wei88] A. Weinand, E. Gamma, and R. Marty. ET++ -- An Object-Oriented Application Framework in C++. In Object-Oriented Programming Systems, Languages, and Applications Conference, pages 46-57, San Diego, California, September 1988.

[You79] E. Yourdon and L. Constantine. Structured Design. Prentice Hall, 1979.

 

Biography

Lance Tokuda(unicron@cs.utexas.edu) Department of Computer Sciences, University of Texas at Austin, http://www.cs.utexas.edu/users/unicron/research.html. I am currently a Ph.D. candidate at the University of Texas working with Don Batory. My current research interest is in transferring refactoring technology to mainstream C++ and Java environments. A discussion of issues can be found in Evolving Object-Oriented Architectures with Refactorings [Tok9b].