UBC Theses and Dissertations

UBC Theses Logo

UBC Theses and Dissertations

Role-based refactoring of crosscutting concerns Hannemann, Jan 2005

Your browser doesn't seem to have a PDF viewer, please download the PDF to view this item.

Item Metadata

Download

Media
831-ubc_2006-130016.pdf [ 5.87MB ]
Metadata
JSON: 831-1.0051755.json
JSON-LD: 831-1.0051755-ld.json
RDF/XML (Pretty): 831-1.0051755-rdf.xml
RDF/JSON: 831-1.0051755-rdf.json
Turtle: 831-1.0051755-turtle.txt
N-Triples: 831-1.0051755-rdf-ntriples.txt
Original Record: 831-1.0051755-source.json
Full Text
831-1.0051755-fulltext.txt
Citation
831-1.0051755.ris

Full Text

Role-Based Refactoring of Crosscutting Concerns by Jan Hannemann  M.Sc, Georgia Institute of Technology, USA, 1999 M.Sc. (Diplom), Universitat Osnabriick, Germany, 1999  A THESIS SUBMITTED IN PARTIAL F U L F I L M E N T OF T H E REQUIREMENTS FOR T H E D E G R E E OF Doctor of Philosophy in The Faculty of Graduate Studies (Computer Science)  The University Of British Columbia November 2005 © Jan Hannemann 2005  ii  Abstract Improving the structure of code can help developers work with a software system more efficiently and more consistently. Aspect-oriented programming (AOP) offers additional ways to structure software by providing explicit means to modularize crosscutting concerns (CCCs) in modularity units called aspects. With the advent of AOP, a new kind of structural improvement of software needs to be considered: the refactoring of non-modularized CCCs into aspects. Refactorings have shown to be helpful for object-oriented software development and maintenance, but their application to aspect-oriented software is not yet well understood. In particular, since refactorings of non-modularized crosscutting concerns involve multiple program elements with potentially complicated relationships, they are considerably more complex than traditional refactorings; the lack of tool support to help plan, reason about and execute C C C refactorings impedes the improvement of code modularity. The thesis of this research is that the refactoring of crosscutting concerns can be supported by a role-based concern model. In this model, crosscutting concerns are described in terms of abstract roles, and instructions for refactoring the concerns are written in terms of those roles. To apply a refactoring, a developer maps a subset of the roles to concrete program elements; a tool can then help complete the mapping of roles to the existing program. Refactoring instructions are then applied to manipulate and modularize the concrete elements corresponding to the crosscutting concern. The abstract nature of such a role-based concern model allows the definition of a refactoring description separately from concrete systems it may be applied to, and allows using a single description to refactor multiple instances of the same concern. To aid developers in restructuring the implementation of crosscutting concerns using aspect-oriented programming, we introduce in this dissertation a refactoring approach and proof-of-concept tool founded on our role-based concern model. We show that abstract descriptions of crosscutting concerns can be applied to previously existing software and we describe the potential for expressing and executing a variety of new C C C refactorings.  iii  Contents Abstract  ii  Contents  iii  List of Tables  vi  List of Figures  vii  List of Abbreviations Acknowledgements 1  Introduction 1.1  1.2 1.3  Refactoring 1.1.1 Traditional Refactorings 1:1.2 Aspect-Oriented Refactorings Role-Based Refactoring Overview of the Dissertation  ix x 1 4 4 4 8 12  2  Design Pattern Implementations in Java and AspectJ 2.1 Established Challenges 2.2 Study Format 2.3 Results 2.3.1 Example: The Observer Pattern 2.3.2 Other GoF Patterns 2.4 Analysis 2.4.1 General Improvements 2.4.2 Specific Improvements 2.4.3 Crosscutting Structure of Design Patterns 2.5 Summary  14 15 16 16 16 23 27 27 29 31 33  3  Role-Based Refactoring 3.1 Workflow 3.2 Describing Crosscutting Concerns 3.3 Describing Refactorings 3.4 Mapping Role Elements 3.5 Impact Analysis 3.6 Executing Refactorings  35 37 37 39 39 40 41  Contents  3.7 3.8  4  Tool Support for Role-Based Refactoring  44 44 46 47 49 49 52 52 53 55 55 56 58 58 59 59 62  4.5 4.6 4.7  The Refactoring Engine 4.1.1 Representing Crosscutting Concerns 4.1.2 Refactoring Primitives 4.1.3 Interference of Refactoring Primitives 4.1.4 Implementation of C C C Refactoring Instructions 4.1.5 Representing Aspect-Oriented Program Constructs Auto-Mapping Support Support for Impact Analyses Example 4.4.1 Mapping 4.4.2 Impact Analysis 4.4.3 Executing the Changes 4.4.4 Remarks Tool Calibration Extending the Framework Summary  Evaluation  63  5.1 5.2  63 63 64 71 73 73 74 79  5.3  5.4  6  41 42  4.1  4.2 4.3 4.4  5  Example Summary  iv  Methodology Study 1: Design Pattern Implementations in JHotDraw 5.2.1 Results 5.2.2 Other Patterns in JHotDraw Study 2: Other Crosscutting Concerns 5.3.1 Logging 5.3.2 Laddad's AOP Refactoring Examples Summary  Discussion  81  6.1 6.2  81 81 82 84 86 88 88 89 90 90 91  6.3  Benefits Limitations 6.2.1 Approach 6.2.2 Supporting Technology 6.2.3 Tool Future Work 6.3.1 Refactorings for other Crosscutting Concerns 6.3.2 Improvements of the Refactoring Tool 6.3.3 Automatic Generation of Refactoring Instructions 6.3.4 Exploratory Generation of Role-Based Refactorings 6.3.5 Extensions of the Role-Based Concern Model  Contents  7  v  Related Work 7.1 Refactoring • • 7.1.1 Composite Refactorings 7.1.2 Analyses for Ensuring the Behavior-Preservation of ObjectOriented Refactorings 7.1.3 Aspect-Oriented Refactorings 7.2 Concern Modeling 7.3 Aspects and Roles 7.4 Aspects and Design Patterns  93 94 96 97 97  8  Conclusions  99  A  Aspect-Oriented Terminology  B  Refactoring Primitives  102  B.l B.2 B.3 B.4  102 102 103 104  Aspect Creation Other Creational Primitives Transformational Primitives Destructive Refactorings  Bibliography  92 92 92  101  105  vi  List of Tables 2.1  Design Patterns, desirable properties of their AspectT implementations, and usage of roles  28  3.1  Role Elements and their Relationships  38  4.1 4.2  Conceptual refactoring steps and their implementation ( O B S E R V E R ) Sample weights for name fragments for role elements  5.1  Role mappings for the DrawingView — FigureSelectionListener instance of the O B S E R V E R pattern Role mappings for the Drawing — DrawingChangeListener instance  65  of the O B S E R V E R pattern  67  5.2 5.3 5.4 5.5 5.6 5.7  .  51 54  Role mappings for the Clipboard instance of the S I N G L E T O N pattern . 68 Role mappings for the Iconkit instance of the S I N G L E T O N pattern . . 68 Role mappings for the CompositeFigure instance of the C O M P O S I T E pattern 70 Role mappings for the AbstractFigure instance of the T E M P L A T E M E T H O D pattern 71 Role mappings for the AbstractLineDecoration instance of the T E M P L A T E M E T H O D pattern  72  vii  List of Figures 1.1 1.2 1.3 1.4 1.5 1.6 1.7 2.1  2.2  2.3  2.4  3.1  3.2  3.3  4.1 4.2  Tangling and scattering of a concern Refactoring of a non-modularized C C C into an aspect (schematic) . . Source code fragment demonstrating logging of deductions in a banking system The role-based refactoring approach (schematic) The Chain of Responsibility design pattern structure according to [28], including methods for setting up the chain The object structure for the sample system Principal role elements comprising a single crosscutting concern . . . A simple graphical figure element system that uses the O B S E R V E R pattern in Java. The assignment of Subject and Observer roles are indicated using U M L stereotypes [73]. Underlined methods contain code necessary to implement this instance of the pattern The structure of an instance of the O B S E R V E R pattern in AspecU. Subject and Observer roles crosscut classes, and the changes of interest (the s u b j e c t C h a n g e ( . . ) pointcut) crosscuts methods in various classes Dependencies and code distribution in typical instances of the M E D I A T O R pattern. The AspectJ implementation removes cyclic dependencies and localizes the pattern code Crosscutting caused by pattern composition. A second pattern instance introduces additional crosscutting The partial structure of an object-oriented instance of the O B S E R V E R pattern in the JHotDraw framework. The mapping of role elements to program elements is indicated using U M L stereotypes [73] Role elements in the O B S E R V E R CCC. Role types are represented as squares, role methods as rounded squares and role fields as hexagons. The structure reflects the pull variant of the pattern [28] Based on an initial mapping (solid arrow), further mappings can be inferred (dashed arrows) The C C C refactoring tool architecture. Existing software used is shown in grey Concern structure description of the Observer C C C as used by the refactoring tool  2 3 5 9 10 10 11  17  22  31 32  36  38 40  45 46  List of Figures  4.3 4.4 4.5 4.6  viii  Pre-processing of buffer modifications Structure of the O B S E R V E R C C C as presented by the refactoring tool. Mapping the Observer role to the D i s p l a y interface After mapping Subject to Point, the automapper determines candidates for mapping the attach(Observer) role method based on a structural and lexical analysis of methods of the Point class 4.7 The completed mappings for the O B S E R V E R C C C instance in the figure package example 4.8 A n impact analysis detects that an existing aspect is advising a changing program element 4.9 Concern structure description of a Logging C C C 4.10 Refactoring instructions for the Logging C C C  50 55 56  5.1  Concern structure of the S I N G L E T O N C C C  67  5.2  Concern structure of the E X T R A C T C O N C E R N I M P L E M E T A T I O N C C C ,  applied to an instance of the C O M P O S I T E pattern  57 57 58 60 61  69  5.3  Concern structure of the T E M P L A T E M E T H O D C C C  70  5.4  Concern structure of the L O G G I N G C C C  73  5.5  Concern structure of the E X T R A C T I N T E R F A C E I M P L E M E N T A T I O N C C C 75  5.6  The Extract Method Calls Refactoring as shown in [51]  5.7  Concern structure of the E X T R A C T M E T H O D C A L L S C C C  5.8  Argument trickle between caller() and callee(), taken from [51]. A n argument gets passed through the call stack but is only used within the callee() method 78  5.9  Concern structure of the R E P L A C E A R G U M E N T T R I C K L E W I T H W O R M -  6.1  76 76  HOLE CCC  78  The programming models of Eclipse and AJDT and their relationships (schematic)  86  List of Abbreviations AO AOP AST ccc GoF IA OO OOP  Aspect-Oriented Aspect-Oriented Programming Abstract Syntax Tree Crosscutting Concern Gang-of-Four, the authors of [28] Impact Analysis Object-Oriented Object-Oriented Programming  X  Acknowledgements I would like to recognize the people who contributed to this dissertation in various ways: First and foremost, I would like to express my deepest gratitude to my parents Marga and Jiirgen Hannemann, who were a constant source of encouragement and motivation. Without their support, this work would not have been possible. My co-supervisors, Gail Murphy and Gregor Kiczales, have provided me with invaluable technical and moral support. Our many thought-provoking conversations we have shaped my thinking about research and the various aspects of academic life. I am very grateful for Gregor's introduction to and guidance with the exciting area of aspect-oriented research, and I am deeply indebted to Gail for her consistently outstanding advice and encouragement. Our Software Practices Lab provided a stimulating envioronment to conduct this research, and I would like to extend my thanks to all its members for the exciting discussions, useful feedback, and fun times. I am grateful to have had the opportunity to work with such outstanding people. In particular, I would like to like to thank Mik Kersten for his input on AspectJ- and AJDT-related questions, and Christopher Dutchyn, who never tired of my requests for clarifications on obscure aspects of programming language theory. My gratitude and deep appreciation go to Brian de Alwis who not only helped with the intricacies of realizing this document in LaTeX, but whose friendship and wisdom (and our shared appreciation for good beer and fine cheeses) have helped to make my stay in Vancouver so enjoyable. Thank you all. —Jan  1  Chapter 1  Introduction Good modularity improves the quality of software. It facilitates independent development of components [19], improves comprehensibility [22], eases verification [85], and facilitates extensibility and evolution [69]. The value of modularity is even quantifiable [5]. Developing software requires working with a number of concerns, or considerations a developer might have about the implementation of a software system. For a secure online shopping site, for example, typical concerns would include the authentication of customers, adding an item to the shopping cart, verifying credit card information, as well as many others. In software with good modularity, each concern is implemented in only one module, and each module implements only a small number of concerns. This structure helps the developer manage complexity. To deal with any one concern they only have to look at one module, and to understand any one module they only have to think about a small number of concerns. Unfortunately, some concerns inherently do not fit into the structures that existing modularity mechanisms support. When a concern does not fit, its implementation cuts across the system's modules. The implementation of such crosscutting concerns (CCCs) is scattered and tangled, which is illustrated schematically in Figure 1.1. This SeeSoft-like view [24] shows the code in terms of its modularity units (such as classes), presented as rectangles. The lines of code within these units pertaining to the implementation of a concern are shown as grey areas. Tangling occurs when the code pertaining to multiple concerns (shown in different shades of grey) is interleaved within a single modularity unit. Scattering occurs when code related to a single concern appears in multiple modularity units. These phenomena often occur together: a scattered implementation is usually tangled with other concerns in the affected modules. The authentication concern mentioned above, for instance, would likely be tangled with the main business logic of the application, and scattered across multiple modularity units. Non-modularized crosscutting concerns can affect multiple modules and result in code that is hard to understand and maintain. Other examples of crosscutting concerns are data persistence [70], quality of service [80], and policy enforcement [50]. Many applications also have a number of specific crosscutting concerns, including implementations of design patterns such as O B S E R V E R and C O M P O S I T E [28], synchronization strategies and resource sharing. Crosscutting concerns can be modularized using aspect-oriented programming (AOP) [46]. AOP is a relatively new programming paradigm that offers additional 1  'For an overview of aspect-oriented terminology, please refer to Appendix A  Chapter I. Introduction  (a) tangling  2  (b) scattering  Figure 1.1: Tangling and scattering of a concern  ways to structure software by providing mechanisms to explicitly modularize CCCs in modularity units called aspects. To transform a non-modularized C C C into a modular aspect, developers need to systematically restructure their software. This can happen, for example, when adopting AOP in an object-oriented legacy system, or when CCCs were not apparent during the design of an AO system and were not properly modularized. Systematic restructuring of software to improve its internal structure while preserving its external behavior is called refactoring [26, 32, 33, 67]. Refactorings in the traditional sense are small program transformations that change a single program element, such as a method or a field, or a single localized set of these elements, such as consecutive statements or code blocks. The transformation applied to support the refactoring includes updating references to these elements, for example adjusting call sites to a renamed method. Examples of traditional refactorings are change variable name or move member variable to superclass [67]. Multiple of these low-level refactorings can be combined into composite refactorings, such as convert code segment to function [67]. Refactorings of crosscutting concerns differ from traditional refactorings in that they target multiple scattered and tangled program elements. Conceptually, a C C C refactoring replaces the scattered and tangled implementation with an equivalent aspect, as shown schematically in Figure 1.2. In this dissertation, we describe and evaluate the first semi-automated refactoring approach to help programmers transform scattered implementations of crosscutting  Figure 1.2: Refactoring of a non-modularized C C C into an aspect (schematic)  concerns into modular implementations in an AOP language. Integral to the approach is an abstraction of the target crosscutting concern. Thesis: A role-based concern model enables the semi-automatic refactoring of crosscutting concerns. A role in this context abstracts part of the functionality represented by the concern. For example, a role-based representation of a synchronization concern could have roles for aquiring and releasing a lock. In a software system utilizing synchronization, one or more concrete program elements (here: methods) can play the role of the aquireLock() role method. Our approach is based on the observation that roles can describe crosscutting behavior [35, 43, 53, 54, 79] and that CCCs that have been modularized conceptually by roles are amenable to modular implementation using an AOP language [38]. In our approach, a C C C refactoring consists of a description of the roles within a C C C and refactoring instructions in terms of these (abstract) roles. To invoke the refactoring, a developer maps the roles to concrete program elements in the scattered implementation. The refactoring instructions are then applied to the mapped elements to transform the program, converting it to a modular AOP implementation. Our approach focuses on preservation of intent over preservation of behavior, in the sense that the transformation preserves the overall requirements of the system, but may change the semantics of the program locally. Such cases are identified by impact analyses of the proposed changes and accepted or rejected by the developer. In section 1.1 we describe in more detail the context of this work, providing a brief overview of traditional and aspect-oriented refactoring. In section 1.2 we present our role-based refactoring approach. Section 1.3 provides an overview of the organization of this dissertation and outlines how its parts will address the thesis claim.  Chapter I. Introduction  1.1  4  Refactoring  Any useful software system requires constant evolution and change [8]. Often those changes require that the software be re-modularized, so that the system becomes easier to understand, extend, or maintain [32, 33]. To address this ongoing need, researchers and developers have developed the practice of refactoring. As described in [32, 33, 67, 71], refactorings are parameterized transformations of a system's source code intended to improve a system's structure with regards to informally expressed goals, such as maintainability, changeability, readability, performance, or memory demands. Traditional refactorings are generally behaviour preserving [67]. Modern software development environments include built-in support for semi-automated refactorings [20, 91]. To distinguish aspect-oriented refactorings from traditional refactorings, and to differentiate between individual approaches to aspect-oriented refactoring, we will use the simple AspectT [45, 89] example shown in Figure 1.3. It shows part of a class for a banking system that focuses on handling deductions from an account. In the method d e d u c t ( i n t ) , race conditions are prevented by acquiring a lock before the actual deduction is executed, which happens in method d o l t ( i n t ) . After that, the lock is released. If the balance is not sufficiently high, an exception is raised. Further, an aspect logs all successful deductions.  1.1.1  Traditional Refactorings  We use the term traditional refactorings to refer to parameterized, behavior-preserving transformations of mostly object-oriented systems . They generally target single program elements and can often be automated [33]. Despite the limited number of elements targeted, they may cause program-wide changes. For example, a rename method refactoring [26] requires all call sites to the targeted method to be updated. Renaming the d e d u c t ( i n t ) method in the example system represents a traditional refactoring. More complex traditional refactorings are composite refactorings (or "big refactorings" [26]), which consist of a series of low-level refactorings. Typical examples perform operations such as simplifying conditionals or creating an abstract superclass. The scope of such refactorings is usually focused on single program elements or small sets of non-scattered program elements and their associated references. 2  1.1.2  Aspect-Oriented Refactorings  Aspect-oriented refactorings differ from traditional refactorings in that they involve AOP constructs, either as the targeted elements or in the resulting code. They can be divided into three distinct types: 1. Aspect-aware O O Refactorings, which are extensions of traditional objectoriented refactorings, ensuring that they do not break A O programming constructs. 2  Although refactorings are not limited to O O systems, the majority of research targets object-oriented  refactorings.  Chapter I. Introduction  public  class  Account  5  {  p u b l i c v o i d d e d u c t ( i n t amount) throws I n s u f f i c i e n t F u n d s E x c e p t i o n a c q u i r e L o c k ( t h i s ); dolt (amount); releaseLock (this);  {  } private void d o i t ( i n t amount) throws I n s u f f i c i e n t F u n d s E x c e p t i o n { if (amount > b a l a n c e ) { throw new I n s u f f i c i e n t F u n d s E x c e p t i o n ) . . . ) ; } else { balance = b a l a n c e - amount; transactions++;  }  }  }  public  aspect TransactionLogger  {  p o i n t c u t d e d u c t i o n ( A c c o u n t a c c t , int c a l l ( v o i d A c c o u n t . d o l t ( i n t ) ) && t a r g e t ( a c c t ) && args (amount);  amount):  a f t e r ( A c c o u n t a c c t , int amount) r e t u r n i n g ; d e d u c t i o n ( a c c t , amount) { log(amount + " deducted from " + a c c t . g e t l d ( ) ) ; }  Figure 1.3: Source code fragment demonstrating logging of deductions in a banking system.  Chapter 1. Introduction  6  2. New Aspect-Oriented Refactorings, which target AOP constructs. 3. Refactorings of Crosscutting Concerns, which are complex refactorings of non-modularized CCCs into aspects. The focus of this work is on refactorings of CCCs. To distinguish these from the other refactorings, we will briefly describe all three kinds of aspect-oriented refactorings.  Aspect-aware Object-Oriented Refactorings Known OO refactorings must be adjusted to account for new AOP constructs. For instance, applying a Rename Method refactoring [26] to the (poorly named) d o l t ( i n t ) method requires updates to references of that construct not only in OO code elements, but also in AOP constructs, such as the d e d u c t i o n ) . . ) pointcut. Applying a refactoring to inline the d o l t ( i n t ) method is another example of an aspect-oriented version of an OO refactoring, as the join points [40, 57] identified by the pointcut cease to exist. Making OO refactorings aspect-aware is the focus of several research projects, for example [34, 42, 86]. 3  New Aspect-Oriented Refactorings The new aspect-oriented programming constructs allow for a number of new refactorings. Many of these parallel existing OO refactorings, for example renaming or inlining a pointcut and advice body. With respect to the kind of refactorings that can be applied to them, pointcuts can be compared to methods and aspects to classes. It is straightforward to envision the meaning of refactorings such as Add Parameter, Pull Up Method, or Push Down Method [26] to a pointcut declaration. Similarly, equivalents of Collapse Hierarchy, Extract Super/Subclass, or Move Class may be conceived for aspects [62]. The new programming constructs in AOP languages also allow for a set of new refactorings that have no OO equivalents, such as the merging or splitting of advice and/or pointcuts. For example, imagine an additional pair of pointcut and advice in the banking system for logging deposits of money to an account. The pointcuts, the advice, or both could be merged with the ones for logging deductions. Several researchers have proposed new refactorings for AOP constructs, for example [42, 61, 62]. Finally, there are low-level object-to-aspect program transformations that move small OO code fragments to aspects by replacing them with A O equivalents. For example, the Replace Implements with Declare Parents refactoring [62] moves an i m p l e m e n t s declaration to an aspect by replacing it with the equivalent AspectJ construct d e c l a r e p a r e n t s . Another example would be to replace the explicit call to a q u i r e L o c k ( . . ) at the beginning of d e d u c t ( i n t ) (see Figure 1.3) with a corresponding pointcut and advice pair. All of these types of AO-refactorings are similar in scope to traditional refactorings and do not address the refactoring of CCCs directly. They usually comprise low-level transformation steps in a C C C refactoring. 3  Analoguous to AspectJ notation, we use"(..)" after a pointcut or method name to indicate that the  construct has zero or more arguments.  Chapter 1. Introduction  1  Refactorings of Crosscutting Concerns Refactorings of CCCs transform scattered implementations of crosscutting concerns into a modularized form (generally an aspect), which is schematically shown in Figure 1.2. For instance, replacing all code pertaining to logging account transactions in the example banking system with an equivalent, modular AO implementation would constitute a C C C refactoring. Non-modularized CCCs consist of multiple related program elements. These relationships can be either explicit through code-level dependencies, such as method calls, subtyping, or contains relationships, or implicit, such as a developer's decision to include them in the concern. We will refer to the set of all program elements that make up a concern's implementation as the concern extent. These elements and their relationships form the concern structure. Refactorings of CCCs are challenging for a number of reasons. First, given that program elements comprising a C C C may not be directly related programmatically, it can be difficult to describe the concern extent based on these properties. For example, in the case of serialization or file I/O in general, the code elements implementing read operations need not be directly linked to those for write operations. Second, since non-modularized crosscutting concerns have scattered and tangled implementations, separating concern code from non-concern code can be hard. Currently, this is done by hand (for informal refactoring descriptions) or through aspect mining approaches, which are limited in their own ways [15]. If the concern extent is not correctly identified, the resulting refactoring will be incomplete. Third, for C C C refactorings there is sometimes a trade-off between behavior preservation and preservation of intent. Consider, for instance, inlining of the d o l t ( i n t ) method in the banking system shown in Figure 1.3. This refactoring would require changes to the d e d u c t i o n ( . . ) pointcut since the pointcut references that method. The intent of the pointcut is to capture all deductions. To preserve the original behavior, we could define the logging to happen before the next program statement is executed (i.e., before the call to r e l e a s e L o c k ( . . ) ) . Alternatively, we could decide that the logging should happen at the last statement of the original, inlined method, where the t r a n s a c t i o n s field gets incremented. Both approaches fail to capture the original intent of the pointcut and make it less readable and self-explanatory. To maintain readability of our pointcut, we could instead specify that logging should take place after the balance field is modified in method d e d u c t ( i n t ) . This would require accepting a minor behavior variation, which, while being against the fundamental principle of refactoring, would keep the pointcut readable, and the intent of the pointcut intact. Finally, choices in the application of the refactoring and the space of possible aspect-oriented implementations raise the need for user interaction as part of the refactoring process. The proposed inlining of the d o l t ( i n t ) method can have at least three possible resolutions with respect to the d e d u c t i o n ( . . ) pointcut as shown above. The decision to choose one alternative over another is hardly automatable. A l though it is conceivable that a tool can just pick one possibility and provide reasoning for later review (e.g., using Java metadata annotations), a complex refactoring may require multiple choices, each of which can influence subsequent refactoring steps. Current research in this area can be divided into three approaches: informal de-  Chapter I. Introduction  8  scriptions of C C C refactorings, approaches that combine aspect mining and low-level AOP refactorings, and approaches that employ concern models. • Informal descriptions — Laddad investigated a number of C C C refactorings and described the required transformation steps that extract scattered implementations into aspects [49]. The descriptions are similarly structured as the refactoring instructions according to Fowler [26], but the refactorings are currently not supported by a tool and must be applied manually. • Combined mining and refactoring approaches — Binkley et al. have proposed an approach to refactoring CCCs in which they incorporate an aspectmining* technique to recognize the scattered and tangled code comprising a C C C ; once recognized, the concern code is modularized using a series of lowlevel aspect-oriented refactorings that are suggested by their refactoring tool [9]. Currently their approach relies on a manual identification of concern code by a developer, and their approach does not yet produce aspect code. The approach focuses on the specific problem of extracting code fragments into aspects, such as the Extract Beginning refactoring that replaces a code block at the start of methods with appropriate b e f o r e advice [9]. In comparison to the approach described in this thesis, Binkley's approach does not consider the structure of the concern being transformed, and the refactoring is a series of individual code extractions. As a result, the aspect code they propose to generate has little structure. • Approaches using concern models — Our earlier work is the only approach to date that uses a model for the concern to be refactored [37]. We employ concern graphs [72] to model the concerns and help plan refactorings, and discuss the role of developer interaction in providing tool support for refactoring scattered code to aspects. However, concern graphs do not include any abstraction to differentiate between individual concrete program elements, thus limiting the description of complex refactorings. Work on C C C refactorings, including this dissertation, focuses on transformations of object-oriented concern implementation into aspects. This is due to the fact that AOP offers additional modularity mechanisms on top of 0 0 , thus allowing for the modularization of formerly non-modularizable crosscutting concerns. A typical application of such OO-to-AO C C C refactorings is the adaption of a legacy O O system to utilize aspects.  1.2  Role-Based Refactoring  To help developers conceptualize, plan and execute refactorings of crosscutting concerns into modular aspects, we have developed a role-based refactoring approach [39]. In role-based refactoring, a crosscutting concern is described as a set of interrelated role 4  Aspect-mining encompasses semi-automated analyses of software to identify candidate code fragments  for extraction to aspects [74]  Chapter 1. Introduction  9  CCC Refactoring Description Refactoring instructions Abstract C C C description u i l l i roll- i l i ' i i i r i i l s  ={5}=  1. 2. 3. 4.  Create... Replace... Replace... Remove...  Abstract  Concrete  Original program; CCC not modularized  Refactored program; CCC modularized  Figure 1.4: The role-based refactoring approach (schematic)  elements that abstract the functionality of the individual program elements comprising the concern. C C C refactorings are defined in terms of these role elements, effectively separating the C C C refactoring description from concrete implementations. Figure 1.4 depicts the approach. The objective is to refactor a scattered and tangled implementation of a C C C (A) into a modular aspect (B). First, the developer chooses a C C C refactoring description from the library of C C C refactorings. This abstract description consists of two parts: a role-based concern description (C) and a set of refactoring instructions (D) in terms of these roles. Applying these instructions to the elements of the concern results in a modular implementation (E). To apply the refactoring to a concrete system, the role elements are mapped onto corresponding program elements in the target system (F). The (abstract) refactoring instructions are applied to the mapped program elements (G), resulting in the desired modularized implementation (B). We illustrate the approach with a simple example. Consider a software system with a graphical user interface, for example a drawing program, that provides contextsensitive help for its widgets: whenever the F l key is pressed, the widget under the current mouse position is asked to provide information about itself. In order to avoid having to specify this information for every single widget, the developer used a C H A I N O F R E S P O N S I B I L I T Y [28] pattern, a typical object-oriented solution. In this approach, widgets are organized in a logical chain (i.e., each widget  Chapter 1. Introduction  1  successor  Handler  Client  10  handleRequesl(Request) setSuccessor(Handler)  5  ConcreteHandleM  ConcreteHandler2  handleRequest(Requesl) setSuccessor(Handler)  handleRequest(Request) selSuccessor(Handler)  Figure 1.5: The Chain of Responsibility design pattern structure according to [28], including methods for setting up the chain  F1 Control (Client) aRequestHandler  Button successor  ButtonBar successor  Application successor  Figure 1.6: The object structure for the sample system  has a successor), and widgets can either choose to either answer a request for contextsensitive help, or pass the request on to its successor in the chain. For example, a B u t t o n could pass the request on to its containing widget, a B u t t o n B a r , which could in turn pass it on to its successor, which might be the main application class itself. The C H A I N O F R E S P O N S I B I L I T Y pattern structure is shown in Figure 1.5 (plus methods for specifying successors, which are used for setting up the call chain). For the application mentioned above, the structure might look like Figure 1.6. The implementation of the concern "context-sensitive-help" is non-modularized and crosscuts various modules in the system. In an aspect-oriented implementation [38], it is possible to encapsulate the C H A I N O F R E S P O N S I B I L I T Y logic into an aspect, modularizing the crosscutting structure. If a modular implementation of this concern is desired, a C C C refactoring is required to transform the original implementation into an aspect. The concept of role-based refactoring is based on the observations that (1) crosscutting concerns have structure to them, and that (2) this structure can be leveraged in the refactoring process. For example, all methods playing the role of handleRequest(..) would require the same set of low-level AO-refactorings. When considering a scattered implementation of a non-modularized concern (see Figure 1.1 (b)), it is important to note that its code fragments can be categorized according to which part of the concern's principal functionality they implement, or, which role they play within the concern. Figure 1.7 shows a sample implementation of the object-oriented Chain of Responsibility pattern. For this particular concern the role elements are a role field  Chapter I. Introduction  11  Plays the role of: Handler  Plays the role of: successor  Plays the role of: handleRequest( Request)  Plays the role of: setSuccessor( Handler)  Plays the role of: Request  Figure 1.7: Principal role elements comprising a single crosscutting concern successor, two role methods handleRequest(..) and setSuccessor(..), and the role types Handler (not shown) and Request. Different shades of grey identify code segments corresponding to the role elements comprising the concern. We differentiate three different kinds of role elements: role fields, like successor, role methods, such as handleRequest(Request), and role types, like Request. Role-based refactoring assumes that all code fragments playing a particular role need to be refactored in a similar fashion, allowing us to describe refactorings in terms of the role elements comprising the concern, and not in terms of concrete program elements. A role-based C C C refactoring description consists of the following elements: 1. Concern description — The C C C in question is described in terms of its role elements and structure. The structure of a C C C is determined by the relationships between its role elements, such as contains relationships (between types and methods and fields, for example) and method call relationships. 2. Refactoring instructions — Refactoring instructions are defined in terms of the role elements in the concern description. These instructions consist of a composite of traditional and aspect-oriented refactorings. For example, one step could entail replacing all methods playing the role of the handleRequest(Request) method with corresponding methods on an aspect. The application of a C C C refactoring comprises the following three steps: 1. Refactoring selection — First, a C C C refactoring description is chosen from the library of C C C refactorings. Alternatively, a new C C C refactoring description is created and added to the library.  Chapter 1. Introduction  12  2. Mapping of roles — Next, the role elements are mapped onto concrete program elements in the target system to be refactored. Tool support can leverage the concern structure to identify the concern extent, i.e., the program elements pertaining to its implementation. 3. Refactoring execution — The program is transformed by applying the abstract refactoring instructions to the concrete program elements mapped to the role elements. Since the refactoring description is based on the concern structure and not tied to a particular implementation, role-based C C C refactorings can be developed independently from concrete concern implementations.  1.3  Overview of the Dissertation  In the remainder of this dissertation we present our role-based approach and demonstrate how it can be used to support the refactoring of non-modularized crosscutting concerns into aspects. Chapter 2 investigates the underlying assumption of this work that refactorings of non-modularized crosscutting concerns yield modularity benefits for at least a useful set of crosscutting concerns. The chapter presents a study comparing design pattern implementations (as sample concerns) in Java and Aspect! with respect to their modularity properties. It investigates the 23 Gang-of-Four (GoF) design patterns presented by Gamma et. al. [28]. The study shows that for most of the investigated CCCs an aspect-oriented implementation entails modularity benefits, and that OO and AO implementations of crosscutting concerns can have complex structural differences, rendering a transformation from OO to AO non-straightforward. In Chapter 3, we employ the concept of roles to model crosscutting concerns and their refactorings and present the resulting role-based refactoring approach. The approach is general and language-independent. More specifically, the concern model and mapping mechanism are language independent, while refactoring instructions are losely tied to the programming language used. The approach consists of three parts: first, a role-based concern model that allows specification of the principal elements of a crosscutting concern in terms of their roles within the concern, and the relationships between these elements. Second, a mapping between the role elements and the program elements implementing them. Andfinally,a model for describing aspect-oriented refactorings in terms of role elements identified in the concern description. Chapter 4 presents a proof-of-concept implementation of our role-based approach that supports the semi-automated refactoring of crosscutting concerns in form of a refactoring tool. The tool is an instantiation of the approach for Java and Aspect! as representative object-oriented and aspect-oriented languages, respectively. It implements the role-based concern model, mapping facilities and the expression of rolebased refactorings. For the description of C C C refactorings, we introduce a library of refactoring primitives. The tool itself is realized as a plugin for the Eclipse IDE [20, 91]. Its implementation and application to code examples with non-modularized crosscutting concerns constitute the basis for validating the thesis claim.  Chapter 1. Introduction  13  In Chapter 5 we evaluate our approach by applying the tool to refactor a variety of non-modularized crosscutting concerns into aspects, investigating how the tool performs on a non-trivial software system, and by studying the effort involved in developing new C C C refactorings. This chapter shows that our role-based concern model enables the semi-automated refactoring of crosscutting concerns. Chapter 6 discusses open issues pertaining to the main facets of our approach and tool and outlines future work. In Chapter 7 we address related work, putting our work into perspective and highlighting its novelty. Finally, Chapter 8 reviews the thesis of this dissertation and summarizes our findings. This dissertation makes four contributions to the field of software engineering. First, it demonstrates through a refactoring tool for Java and Aspect! that a role-based approach can semi-automate C C C refactorings. Second, the role-based model for describing crosscutting concerns may form the basis for other operations that need to capture or analyze CCCs, such as documenting a crosscutting concern or identifying inconsistencies in its implementation. Third, the thesis includes a description of a set of aspect-oriented refactoring primitives. Finally, we describe and evaluate aspectoriented implementations of common design patterns, which developers may use independently of our refactoring approach.  14  Chapter 2  Design Pattern Implementations in Java and AspectJ This dissertation is based on the underlying assumption that the transformation of nonmodularized crosscutting concerns into aspects is useful. We explore this assumption in a study that investigates implementations for a particular — and often crosscutting — kind of concern: design pattern implementations. Design patterns offer flexible solutions to common software development problems. Each pattern is comprised of a number of parts, including purpose/intent, applicability, solution structure, and sample implementations. A number of the Gang-of-Four (GoF) patterns [28] involve crosscutting structures in the relationship between roles in the pattern and classes in an actual implementation [17, 18]. In the O B S E R V E R pattern, for example, all operations that change a Subject must trigger notifications of its Observers. In other words, the act of notification crosscuts one or more operations in each Subject in the pattern. In the C H A I N O F R E S P O N S I B I L I T Y pattern, all Handlers need to be able to accept requests and to either handle them or forward them to the successor in the chain. This event handling mechanism crosscuts the classes playing the Handler role. When the GoF patterns were first identified, the sample implementations were geared to the current state of the art in object-oriented languages. Other work [66, 78] has shown that implementation language affects pattern implementation, so it seems natural to explore the effect of aspect-oriented programming techniques [46] on the implementation of the GoF patterns. In our study of the GoF patterns, we maintain the purpose, intent, and applicability of 23 well-known patterns, and allow only the solution structure and implementation to change. Thus, the focus of this study is not to discover new patterns, but simply to work out how implementations of the GoF patterns can be handled using a new implementation technique. We compared object-oriented and aspect-oriented implementations of sample systems for each of the 23 GoF design patterns. Our results show that using AspectJ improves the modularity of implementations of many GoF patterns. In some cases this is reflected in a new solution structure with fewer or different participants, in other cases, the structure remains the same, only the implementation changes. The degree of improvement in implementation modularity varies, with the greatest improvement coming when the pattern solution structure involves crosscutting of some form as indicated by the usage of roles, for example one object playing multiple roles, many objects playing one role, or an object playing roles in multiple pattern instances.  Chapter 2. Design Pattern Implementations in Java and Aspect!  15  Patterns with crosscutting structure between roles and participant classes see the most improvement. The improvement comes primarily from modularizing the implementation of the pattern. This is directly reflected in the implementation being textually localized. A n integral part of achieving this is to remove code-level dependencies between the participant classes and the implementation of the pattern. Using Aspect!, we modularized the implementation of 17 of the patterns, while the other 6 can already be modularly expressed using object-oriented techniques. For 12 of the patterns, the aspect-oriented modularity enabled a core part of the implementation to be abstracted into reusable code. For 14, it enabled transparent composition of pattern instances, so that multiple patterns can have shared participants. For the 17 modularized patterns, all pattern code from some or all participants was moved into the pattern aspect, allowing those participants to be (un)pluggable with respect to the pattern. These results — 74% of GoF patterns implemented in a more modular way, and 52% reusable — suggest that there is merit in replacing object-oriented design pattern implementations with aspect-oriented ones arising from improved modularity.  2.1  Established Challenges  Numerous authors have identified challenges that arise when patterns are concretized in a particular software system, as outlined below. The three most important challenges are related to implementation, documentation, and composition: Design pattern implementation usually has a number of undesirable related effects. Because patterns influence the system structure and their implementations are influenced by it [25], pattern implementations are often tailored to the instance of use, which can lead to them "disappearing into the code" [25] and losing their modularity [76]. This makes it hard to distinguish between the pattern, the concrete instance and the object model involved [55]. Adding or removing a pattern to/from a system is often an invasive change that is difficult to reverse [14]. Consequently, while a design pattern description is reusable, its implementations usually are not [76], The invasive nature of pattern code, and its scattering and tangling with other code creates documentation problems [76]. If multiple patterns are used in a system, it can become difficult to trace particular instances of a design pattern, especially if classes are involved in more than one pattern, as is the case with pattern overlay/composition [1]. Pattern composition causes more than just documentation problems. It is inherently difficult to reason about systems with multiple patterns involving the same classes, since the composition creates large clusters of mutually dependent classes [76]. This is an important topic because some design patterns explicitly use others patterns in their solution.  Chapter 2. Design Pattern Implementations in Java and Aspect!  2.2  16  Study Format  The findings presented in this chapter are based on a comparative analysis of Java and Aspect! implementations of the GoF design patterns. For each of the 23 GoF patterns we created a sample system that makes use of the pattern, and implemented the example in both Java and Aspect!. The Java implementations correspond to the sample C++ implementations in the GoF book, with minor adjustments to account for the differences between C++ and Java, such as the lack of multiple inheritance, etc. Most patterns have a number of implementation variants and alternatives. If a pattern offered more than one possible implementation, we picked the one that appeared to be the most generally applicable. The Aspect! implementations were developed iteratively. The Aspect! constructs allowed a number of different implementations, usually with varying tradeoffs. Our goal was to investigate the design space of clearly defined patterns. We ended up creating a total of 57 different implementations, which ranged from 1 to 7 per pattern. Some of the tradeoffs and design decisions are discussed in Section 2.3.  2.3  Results  This section presents a comparison of the Aspect! and Java implementations of concrete instances of the GoF design patterns. Section 2.3.1 is a detailed discussion of the O B S E R V E R pattern. We use this discussion to present properties common to most of the Aspect! solutions. The remaining patterns are presented by building on the concepts developed in Section 2.3.1.  2.3.1  Example: The Observer Pattern  The intent of the O B S E R V E R pattern is to "define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically" [28]. Object-oriented implementations of the O B S E R V E R pattern, such as the sample code in the GoF book (p. 300-303), usually add a field to all potential Subjects, that stores a list of Observers interested in that particular Subject. When a Subject wants to report a state change to its Observers, it calls its own notify() method, which in turn calls an updute(..) method on all Observers in the list. Consider a concrete example of the O B S E R V E R pattern in the context of a simple figure package as shown in Figure 2.1. In such a system the O B S E R V E R pattern would be used to cause mutating operations on figure elements to update the D i s p l a y . As shown, code for implementing this pattern is spread across the classes. All participants have to know about their role in the pattern and consequently have pattern code in them. Adding or removing a role from a class requires changes to that class. For example, changing the notification mechanism, such as switching between push and pull models [28], requires changes in all participating classes.  Chapter 2. Design Pattern Implementations in Java and AspectJ  17  «Observer»  Display uptlateO display(String)  Figure  ±4  «Subject»  Figure Element addObsen>er( Obser\'er) removeObserver( Obser\<er) notifyO  1 « S u b j e c t » Point gctX():int gctY():int gclColor(): Color addObscrvcr(Observer) rcmovcObservcrfObservcri notifyO sctXfinO sclYfinO sctColor(Color)  « S u b j e c t » Line getPI():Point getP2(): Point gclColor():Color addObservertOhserverl removeObserverf Observer! notifyO setPlfPoinO setP2(PoinO setColor{Color)  Figure 2.1: A simple graphicalfigureelement system that uses the O B S E R V E R pattern in Java. The assignment of Subject and Observer roles are indicated using U M L stereotypes [73]. Underlined methods contain code necessary to implement this instance of the pattern.  The Abstracted Observer Pattern In the structure of the O B S E R V E R pattern, some parts are common to all potential instantiations of the pattern, and other parts are specific to each instantiation. The parts common to all instantiations are: 1. The existence of Subject and Observer roles, i.e., the fact that some classes act as Observer and some as Subject 2. Maintenance of a mapping from Subjects to Observers 3. The general update logic: Subject changes trigger Observer updates The parts specific to each instantiation of the pattern are: 4. Which classes can be Subjects and which can be Observers 5. A set of changes of interest on the Subjects that trigger updates on the Observers 6. The specific means of updating each kind of Observer when the update logic requires it  Chapter 2. Design Pattern Implementations in Java and AspectJ  18  Listing 2.1: The generalized ObserverProtocol aspect i  public  abstract  protected protected  3 4  aspect  interface interface  ObserverProtocol Subject Observer  { {  {  } }  5  6  private  WeakHashMap p e r S u b j e c t O b s e r v e r s ;  7  protected L i s t g e t O b s e r v e r s ( S u b j e c t s ) { if ( p e r S u b j e c t O b s e r v e r s == n u l l ) { p e r S u b j e c t O b s e r v e r s = new WeakHashMap ( ) ;  8 9 10  } L i s t o b s e r v e r s = ( L i s t ) p e r S u b j e c t O b s e r v e r s . get ( s ) ; if ( o b s e r v e r s == n u l l ) { o b s e r v e r s = new L i n k e d L i s t ( ) ; p e r S u b j e c t O b s e r v e r s . put ( s , o b s e r v e r s ) ; }  12 13 14 15 n  return  observers;  }  19  public void a d d O b s e r v e r ( S u b j e c t g e t O b s e r v e r s ( s ) . add ( o ) ;  20 21  s,Observer  o){  } 23  public void r e m o v e O b s e r v e r ( S u b j e c t getObservers ( s ) . remove(o);  24 25  s,Observer  o){  } 27  2s  abstract  protected  pointcut  abstract  p r o t e c t e d void  subjectChange(Subject  s);  29  30  updateObserver(Subject  s , Observer  o);  31  after (Subject s ) : subjectChange(s) { I t e r a t o r i t e r = g e t O b s e r v e r s ( s ) . i t e r a t o r (); while ( i t e r . h a s N e x t () ) { u p d a t e O b s e r v e r ( s , ( ( O b s e r v e r ) i t e r . next ( ) ) ) ;  32 33 34 35 36 38 37  } }  }  We developed AspectJ code that reflects this separation of reusable and instancespecific parts. A n abstract aspect encapsulates the generalizable parts (1-3), while one concrete extension of the aspect for each instance of the pattern fills in the specific parts (4-6). The reusable ObserverProtocol aspect is shown in Listing 2.1. 5  The Subject and Observer roles The roles are realized as protected inner interfaces named Subject and Observer (Figure 2.1, line 3-4). Their main purpose is to allow correct typing of Subjects and Observers in the context of the pattern implementation, such as in methods like addObserver ( . . ). Concrete extensions of the O b s e r v e r P r o t o c o l aspect assign the roles to particular classes. These interfaces are protected because they will only be used by ObserverProt o c o l and its concrete extensions. No code outside the aspect and extensions needs to handle objects in terms of these roles. 5  A l l examples and the code generated by our refactoring tool (Chapter 4) use AspectJ 1.2.1. The recent  AspectJ 1.5 milestone builds (which support Java 5) would allow for a slightly more elegant implementation. Concretely, we could employ generic versions of the internally used abstract data types to avoid type casts.  Chapter 2. Design Pattern Implementations in Java and Aspect]  19  These interfaces are empty because the pattern defines no methods on the Subject or Observer roles. The methods that would typically be defined on the Subject and Observer are instead defined on the aspect itself. For patterns that were abstractable we had to decide where to put the role interfaces. Two locations are possible: Either as a protected interface inside the abstract aspect or as a separate public interface. We made this decision based on whether the role interface introduces client-accessed functionality, i.e., exposes functionality to clients (as for S T R A T E G Y , I T E R A T O R , etc.)  or not (as in the O B S E R V E R case). If the role  has no client-accessible functionality, it will only be referenced from within pattern aspects. For that reason, we placed it in the abstract aspect. In the other case, we made the interface public. The Subject-Observer Mapping Implementation of the mapping in the Aspect! code is localized to the O b s e r v e r P r o t o c o l aspect. It is realized using a weak hash map of linked lists to store the Observers for each Subject (line 6). As each pattern instance is represented by a concrete subaspect of O b s e r v e r P r o t o c o l , each instance will have its own mapping. Changes to the Subject-Observer mappings can be realized via the public a d d O b s e r v e r ( . . ) and r e m o v e O b s e r v e r ( . . ) methods (line 20-26) that concrete subaspects inherit. To have a D i s p l a y object D become the Observer of a P o i n t Subject P, clients call these methods on the appropriate subaspect (e.g., C o l o r O b server): ColorObserver.aspectOf().addObserver(P,  D);  The g e t O b s e r v e r s ( . . ) method is only used internally. It creates the proper secondary data structures (linked lists) on demand (line 8-18). Note that in this implementation the Subject-Observer mapping data structure is centralized in each concrete extension. All concrete aspects that subclass the abstract pattern aspect will automatically have an individual copy of the field, following the structure presented in [28]. This can cause bottlenecks in some situations. These can be fixed, on a per patterninstance basis, by overriding g e t O b s e r v e r s (. .) with a method that uses a more decentralized data structure. Generally, whenever a pattern solution requires a mapping between participants, as in the case of the s u c c e s s o r field of handlers in C H A I N O F R E S P O N S I B I L I T Y , and the pattern implementation is abstractable, we can either define a field on the participant, or keep the mapping in a central data structure in the abstract aspect as in this example. Whichever approach is chosen, the point of access to the data structure is the instance-specific aspect, so that different instances of the pattern involving the same participants are possible and will not become confused. The Update Logic In the reusable aspect, the update logic implements the general concept that Subjects can change in ways that require all their observing objects to be updated. This implementation does not define exactly what constitutes a change, or how Observers should be updated. The general update logic consists of three parts: The changes of interest depict conceptual operations, a set of points in program execution, at which a Subject should update its Observers (to notify them of changes  Chapter 2. Design Pattern Implementations in Java and Aspect!  20  to its state). In AspectJ, sets of such points are identified with pointcut constructs. In the reusable aspect, we only know there are modifications of interest, but since they are instance-specific, we do not know what they are. Therefore, we define an abstract pointcut named subjectChange ( . . ) that is to be concretized by instance-specific subaspects (line 28). In the reusable part we only know that the Observers will have to be updated in the context of the pattern, but cannot predict how that is best achieved. We define an abstract update method updateObserver (Subject) that will be concretized for each pattern instance (line 30). That way, each instance of the O B S E R V E R pattern can choose its own update mechanism. Finally, the reusable aspect implements the update logic in terms of the generalizable implementation parts mentioned above. This logic is contained in the after advice (line 32-37). This after advice says: whenever execution reaches a join point matched by the subj ectChange ( . . ) pointcut, update all Observers of the appropriate Subject afterwards.  Pattern-Instance-Specific Concrete Aspects Each concrete subaspect of ObserverProtocol defines one particular kind of observing relationship, in other words a single pattern instance. Within that kind of relationship, there can be any number of Subjects, each with any number of Observers. The subaspect defines three things: • The classes that play the roles of Subject and Observer. This is done using the d e c l a r e parents construct, which adds superclasses or super-interfaces to a class, to assign the roles defined in the abstract aspect. • The conceptual operations on the Subject that require updating the Observers. This is done by concretizing the subj ectChange ( . . ) pointcut. • How to update the Observers. This is done by concretizing updateObserv e r (Subject) . The choice between push or pull model for updates is no longer necessary as we have access to both the Subject and the Observer at this point and can customize the updates. The d e c l a r e parents construct is part of the AspectJ open class mechanism that allows aspects to modify existing classes without changing their code. This open class mechanism can attach fields, methods, or — as in this case — interfaces to existing classes. Listing 2.2 shows two different instances of the O B S E R V E R pattern involving the classes Point, Line, and Display. In both instances, Point and L i n e play the role of Subject, and D i s p l a y plays the role of Observer. The first observes color changes, and the second observes coordinate changes. Particular classes can play one or both of the Subject and Observer roles, either in the same pattern instance or separate pattern instances. Listing 2.3 shows a third pattern instance in which D i s p l a y acts as Subject and Observer at the same time.  Chapter 2. Design Pattern Implementations in Java and AspectJ  Listing 2.2: Two different Observer instances i  public  aspect  declare declare declare  3 4 5  ColorObserver  parents: parents: parents:  Point Line Display  extends  ObserverProtocol  implements implements implements  {  Subject; Subject; Observer;  6  protected p o i n t c u t s u b j e c t C h a n g e ( S u b j e c t s ) : ( c a l l (void P o i n t . s e t C o l o r ( C o l o r ) ) || c a l l ( v o i d Line.setColor(Color)) ) && t a r g e t ( s ) ;  7 « 9 10  protected void u p d a t e O b s e r v e r ( S u b j e c t s , O b s e r v e r (( D i s p l a y ) o ) . d i s p l a y ( " C o l o r c h a n g e ( o r " + s ) ;  n 12 '3 ,4 15  }  i6  public  o)  {  }  aspect  CoordinateObserver  extends  ObserverProtocol  {  17  declare declare declare  is 19 20  parents: parents: parents:  Point Line Display  implements implements implements  Subject; Subject; Observer;  21  protected p o i n t c u t s u b j e c t C h a n g e ( S u b j e c t s ) : ( c a l l ( v o i d P o i n t . setX( int)) || c a l l ( v o i d P o i n t . s e t Y ( i n t ) ) || c a l l ( v o i d L i n e . s e t P 1 ( P o i n t ) ) || c a l l ( v o i d L i n e . s e t P 2 ( P o i n t ) ) ) && t a r g e t ( s ) ;  22 23 24 25 26 27  p r o t e c t e d void u p d a t e O b s e r v e r ( S u b j e c t s , O b s e r v e r o ) { (( D i s p l a y ) o ) . d i s p l a y ( " C o o r d i n a t e c h a n g e f o r " + s ) ;  28 29 30 3.  } }  Listing 2.3: The same class can be Subject and Observer i  public  aspect  declare declare  3 4  DisplayObserver  parents: parents:  Display Display  extends  implements implements  ObserverProtocol  {  Subject; Observer;  5  protected p o i n t c u t s u b j e c t C h a n g e ( S u b j e c t s ) : c a l l ( v o i d D i s p l a y . d i s p l a y ( S t r i n g )) && t a r g e t ( s ) ;  6 7 8  protected void u p d a t e O b s e r v e r ( S u b j e c t s , O b s e r v e r (( D i s p l a y ) o ) . r e f r e s h ( ) ; (( D i s p l a y ) o ) . l o g ( " D i s p l a y u p d a t e d by " + s ) ;  9 10 n >2 '3  } }  o)  {  21  Chapter 2. Design Pattern Implementations in Java and AspectJ  22  ColorObserver Subject  Observer  (^^subJectChange^^) |!  \ \ Point  /  Line  Display  Figure 2.2: The structure of an instance of the O B S E R V E R pattern in AspectJ. Subject and Observer roles crosscut classes, and the changes of interest (the subjectChange ( . . ) pointcut) crosscuts methods in various classes  In the AspectJ version all code pertaining to the relationship between Observers and Subjects is moved into an aspect, which changes the dependencies between the modules. Figure 2.2 shows the structure for this case.  Properties of this Implementation This implementation of the O B S E R V E R pattern has the following closely related modularity properties: • Locality — A l l the code that implements the O B S E R V E R pattern is contained in one abstract and one concrete aspect, none of it is in the participant classes. The participant classes are entirely free of the pattern context, and as a consequence there is no coupling between the participants. Potential changes to each O B S E R V E R pattern instance are confined to one place. • Reusability — The core pattern code is abstracted and reusable. The implementation of ObserverProtocol is generalizing the overall pattern behavior. The abstract aspect can be reused and shared across multiple O B S E R V E R pattern instances. For each pattern instance, we only need to define one concrete aspect. • Composition transparency — Because a pattern participant's implementation is not coupled to the pattern, if a Subject or Observer takes part in multiple observing relationships their code does not become more complicated and the pattern instances are not confused. Each instance of the pattern can be reasoned about independently. • (Un)pluggability — Because Subjects and Observers need not be aware of their role in any pattern instance, it is possible to switch between using a pattern and not using it in the system.  Chapter 2. Design Pattern Implementations in Java and AspectJ  23  Note that the OO and the AO versions of the patterns very considerably structurally. Similar observations can be made for the other patterns as well, indicating that a potential C C C refactoring that replaces an 0 0 implementation with an aspect can be complex.  2.3.2  Other GoF Patterns  In the following we describe the remaining 22 GoF patterns and how the AspectJ implementation is different from a pure Java version. The patterns are grouped by common features, either of the pattern structures or their AspectJ implementations.  Composite, Command, Mediator, Chain of Responsibility: Roles Only Used Within the Pattern Aspect Similar to the O B S E R V E R pattern, these patterns introduce roles that need no clientaccessible interface and are only used within the pattern. In AspectJ such roles are realized with empty (protected) interfaces. The types they introduce are used within the pattern protocol. One abstract aspect for each pattern defines the roles and attaches default implementations where possible. See Listing 2.4 for parts of the abstract C o m p o s i t i o n P r o t o c o l aspect. For patterns involving particular conceptual operations, the abstract pattern aspect introduces an abstract pointcut to be concretized for each instance of the pattern, which captures the join points that should trigger important events, such as the execution of a Command in the C O M M A N D pattern. As in the O B S E R V E R example, advice (after, before, or around) is responsible for calling the appropriate methods. In the C O M P O S I T E case, to allow walking the tree structure inherent to the pattern, we define facilities to have a visitor traverse and/or change the structure. These visitors are defined in the concrete aspect. See Listing 2.5 for an example of how statistics can be collected from the composite structure. In this example we show an instance of the C O M P O S I T E pattern modeling a file system. Directories are Composites, and files are Leafs. The example shows how to calculate the disk space needed for the file system, assuming that F i l e objects have a size field. Again, clients use a public method on the aspect to access the new functionality. Appropriate methods on the participants are introduced privately and are visible only by the aspect.  Singleton, Prototype, Memento, Iterator, Flyweight: Aspects as Object Factories These patterns administrate access to specific object instances. All of them offer factory methods to clients and share a create-on-demand strategy. The patterns have abstracted, reusable implementations in AspectJ, with code for the factory in the aspect. In the AspectJ implementations, the factory methods are either parameterized methods on the abstract aspect or methods attached to the participants. If the former approach is used, multiple instances of the pattern compose transparently, even if all factory methods have the same names. The S I N G L E T O N case is special in that we can turn the original constructor into the factory method using around advice and returning the unique object on all constructor calls.  Chapter 2. Design Pattern Implementations in Java and AspectJ  24  Listing 2.4: Part of the abstract Composite pattern implementation i  public  abstract  aspect  CompositionProtocol  {  2  protected protected protected  3 4 5  interface interface interface  Component {} C o m p o s i t e extends Component Leaf extends Component  {} {}  6  private  7  WeakHashMap p e r C o m p o n e n t C h i l d r e n  = new WeakHashMap ( ) ;  8  p r i v a t e V e c t o r g e t C h i l d r e n (Component s ) { Vector c h i l d r e n ; c h i l d r e n = (Vector) perComponentChildren . g e t ( s ) ; if ( c h i l d r e n == n u l l ) { c h i l d r e n = new V e c t o r ( ) ; p e r C o m p o n e n t C h i l d r e n . put ( s , c h i l d r e n ) ;  9 10 11 12 13 H  "  }  return  i6  children;  } 18  p u b l i c void a d d C h i l d ( C o m p o s i t e c o m p o s i t e , Component c o m p o n e n t ) g e t C h i l d r e n ( c o m p o s i t e ). a d d ( c o m p o n e n t ) ;  19 20  } 22 23  p u b l i c void r e m o v e C h i l d ( C o m p o s i t e c o m p o s i t e , g e t C h i l d r e n ( c o m p o s i t e ). r e m o v e ( c o m p o n e n t ) ;  24' 25  }  26 27  p u b l i c E n u m e r a t i o n g e t A I I C h i l d r e n (Component c ) return g e t C h i l d r e n ( c ) . e l e m e n t s ( ) ;  28 29  }  30 31  protected interface F u n c t i o n V i s i t o r p u b l i c O b j e c t d o l t (Component c ) ;  32  }  {  Component c o m p o n e n t )  {  {  {  33  protected  r e c u r s e F u n c t i o n (Component c , F u n c t i o n V i s i t o r fv ) { V e c t o r r e s u l t s = new V e c t o r ( ) ; f o r ( E n u m e r a t i o n enum = g e t A I I C h i l d r e n ( c ) ; e n u m . h a s M o r e E l e m e n t s ( ) ; Component c h i l d ; c h i l d = (Component)enum. nextEIement ( ) ; r e s u l t s . a d d ( fv . d o l t ( c h i l d ) ) ;  34 35 36 37 38 39 40  }  return  42 43  44  }  }  static  Enumeration  r e s u l t s . elements ();  )  {  Chapter 2. Design Pattern Implementations in Java and AspectJ  Listing 2.5: Part of a i  public aspect  COMPOSITION  FileSystemComposite  25  pattern instance aspect  extends C o m p o s i t e P r o t o c o l  {  2  declare declare  3 4  parents: parents:  Directory File  implements C o m p o s i t e ; implements L e a f ;  5  p u b l i c int s i z e O n D i s k ( C o m p o n e n t return c . s i z e O n D i s k ( ) ; }  6 7  c)  {  9  p r i v a t e a b s t r a c t int C o m p o n e n t . s i z e O n D i s k ( ) ;  io ii  p r i v a t e int D i r e c t o r y . s i z e O n D i s k ( ) { // Assume directories have no relevant int d i s k S i z e = 0 ;  12 13 H  size  of  their  own  15  16 17 is  E n u m e r a t i o n enum = S a m p l e C o m p o s i t e . a s p e c t O f ( ) . g e t A I I C h i I d r e n ( t h i s ); while (enum. h a s M o r e E l e m e n t s ()) { d i s k S i z e += ( ( C o m p o n e n t ) e n u m . n e x t E l e m e n t ( ) ) . s i z e O n D i s k ( ) ;  20  } return  }  diskSize;  22  p r i v a t e int F i l e . s i z e O n D i s k () return s i z e ;  23 24 25 26  }  {  }  Parameterized factory methods can alternatively be implemented according to Nordberg's factory example [65]: the factory method is empty (returns null or a default object). Other return values are provided by around advice on that method. If the arguments are appropriate, the advice creates a new matching object; otherwise it just proceeds with the regular execution. This allows us extend the factory (in terms of new products) without changing its code. Participants no longer need to have pattern code in them; the otherwise close coupling between an original object and its representation or accessor ( M E M E N T O , ITERATOR) is removed from the participants.  Adapter, Decorator, Strategy, Visitor, Proxy: Language Constructs Using AspectJ, the implementation of some patterns completely disappears, because AspectJ language constructs implement them directly. This applies to these patterns in varying degrees. The A D A P T E R and V I S I T O R patterns can be realized by extending the interface of the Adaptee (via AspecU's open class mechanism). D E C O R A T O R , S T R A T E G Y and P R O X Y have alternate implementations based on attaching advice (as outlined for D E C O R A T O R in [65]).  While simpler and more modular, the approaches have inherent limitations. The advice-based implementation of D E C O R A T O R loses its dynamic manipulation properties (dynamic reordering of Decorators) and is thus less flexible. The interface augmentation for Adapter cannot be realized in this manner when we want to replace an existing method with another one that has the same name and arguments but a different return type.  Chapter 2. Design Pattern Implementations in Java and AspectJ  26  Protection or delegation proxies can be implemented to be reusable using the above approach, but some applications of the P R O X Y pattern require the Proxy and the Subject to be two distinct objects (as is the case for remote and virtual proxies). In these cases the Java and AspectJ implementations are identical.  Abstract Factory, Factory Method, Template Method, Builder, Bridge: Multiple Inheritance These patterns are structurally similar: inheritance is used to distinguish different, but related, implementations. As this is already nicely realized in OO, these patterns could not be given more reusable implementations. However, with AspectJ it is possible to replace the abstract classes mentioned in the GoF solution by interfaces without losing the ability to attach (default) implementations to their methods. With Java, we cannot use interfaces if we want to define a default implementation for methods that are part of the pattern code. In that respect, AspectJ's open class mechanism effectively provides a limited form of multiple inheritance. Besides that, B U I L D E R and B R I D G E have the following additional implementation considerations. For B U I L D E R , an aspect can intercept calls to the creation methods and replace them with alternate implementations using around advice (see S T R A T E G Y above). For B R I D G E , a decoupling of Abstraction and Implementor can be achieved by using polymorphic advice as suggested by Nordberg [88]. While this approach reduces the coupling between the participants, it is less flexible with respect to dynamically changing Implementors.  State, Interpreter: Scattering Contained These patterns introduce tight coupling between their participants. In the AspectJ implementations, parts of the scattered code can be modularized. In the S T A T E pattern, the crosscutting code for state transitions can be modularized in an aspect using (mainly) after advice. Although the I N T E R P R E T E R pattern implementation is not modularized, extensions to the pattern that augment or change the behavior of the system without can be modularly implemented by attaching methods to the participants using the open class mechanism.  Facade: no benefit from AspectJ implementation For this pattern, the AspectJ approach is not structurally different from the Java implementation. F A C A D E provides a unified interface to a set of interfaces to a subsystem, to make the subsystem easier to use. This example mainly requires namespace management and good coding style. On the other hand, AspectJ's d e c l a r e w a r n i n g and d e c l a r e e r r o r constructs provide simple means to impose a global policy for handling violations of the F A C A D E principle (accesses to the protected subsystem that bypass the Facade interface).  Chapter 2. Design Pattern Implementations in Java and AspectJ  2.4 Analysis In this section, we present an analysis of the previously observed benefits of implementing patterns with AspectJ. The analysis is broken into three parts: • The general improvements observed in many pattern re-implementations. • The specific improvements associated with particular patterns. • The origins of crosscutting structure in patterns, and a demonstration that observed improvements correlate with the presence of crosscutting structure in the pattern.  2.4.1  General Improvements  For a number of patterns, the AspectJ implementations manifest several closely related modularity benefits: locality, reusability, dependency inversion, transparent composability, and (un)pluggability. Attempting to say which of these is primary is difficult, instead we simply describe them and discuss some of their interrelationships. The AspectJ implementations of 17 of the 23 GoF patterns were localized. For 12 of these, the locality enables a core part of the implementation to be abstracted into reusable code. In 14 of the 17 we observed transparent composability of pattern instances, so that multiple patterns can have shared participants (see Table 2.1). The improvements in the AspectJ implementations are primarily due to inverting dependencies, so that pattern code depends on participants, not the other way around. This is directly related to locality: all dependencies between patterns and participants are localized in the pattern code. An object or class that is oblivious of its role in a pattern can be used in different contexts (such as outside the pattern) without modifications or redundant code, thereby increasing the reusability of participants. If participants do not need to have pattern-specific code, they can be readily removed from or added to a particular pattern instance, making the participants (un)pluggable. To benefit from this, the participants must have a meaning outside the pattern implementation. For example, the participants in a C H A I N O F R E S P O N S I B I L I T Y pattern often have other responsibilities in the application they are in (as widgets in the GUI example in GoF), while Strategy objects in the S T R A T E G Y pattern usually just encapsulate an algorithm. The locality also means that existing classes can be incorporated into a pattern instance without the need to adapt them; all the changes are made in the pattern instance. This makes the pattern implementations themselves relatively (un)pluggable. Since pattern locality implies that all code fragments pertaining to the implementation of a pattern are in one place, it also facilitates to impose global policies related to a design pattern, such as adding thread safety, logging facilities or performance optimizations. For example, in the C H A I N O F R E S P O N S I B I L I T Y case, the policy that determines what happens to requests that reach the end of the chain without being answered is contained to a single point within the aspect instead of being spread across  27  Chapter 2. Design Pattern Implementations in Java and AspectJ  28  Table 2.1: Design Patterns, desirable properties of their AspectJ implementations, and usage of roles Pattern Name Facade Abstract Facotry  Locality"  Modularity Properties Composition Transparency Reusability  (Un)pluggability  Same implementation for Java and AspectJ no  no  no  no  Bridge Builder Factory Method  no no  no no  no no  no no  no  no  no  no  Interpreter  Kinds of Roles Defining Superimposed Roles Roles b  Facade Factory Product Abstraction Implementor Builder, (Director) Product Creator Context Expression  -  no  no  n/a  no  Template Method Adapter State  (yes) yes (yes)  no no no  no yes n/a  (yes) yes (yes)  Decorator Proxy Visitor  yes (yes) (yes)  no no yes  yes (yes) yes  yes (yes) (yes)  (AbstractClass) Target, Adapter State Component Decorator (Proxy) Visitor  Command  (yes)  yes  yes  yes  Command  Composite Iterator Flyweight Memento Strategy  yes yes yes yes yes  yes yes yes yes yes  yes yes yes yes yes  (yes) yes yes yes yes  (Component) (Iterator) Factory Memento Strategy  (ConcreteClass) Adaptee Context ConcreteComponent (Proxy) Element Commanding Receiver Composite Leaf Aggregate Flyweight Originator Context  Mediator Chain of Respons. Prototype Singleton  yes  yes  yes  yes  -  (Mediator) Colleague  yes yes yes  yes yes yes  yes (yes) n/a  yes yes yes  -  Observer  yes  yes  yes  yes  -  -  Handler Prototype Singleton Subject Observer  " Locality: "(yes)" means that the pattern is localized in terms of its superimposed roles but the implementation of the remaining defining role is still done using multiple classes (e.g., Stores for the STATE pattern). In general, (yes) for a desirable property means that some restrictions apply. * Defining and superimposed roles were not always easy to differentiate. If the distinction was not clear, the role names are shown in parentheses in either or both categories  Chapter 2. Design Pattern Implementations in Java and AspectJ  29  the various Handler types. In the O B S E R V E R case, a conceivable performance optimization is to de-centralize the mapping between Subjects and Observers (see Section 2.3.1 above), which can also be achieved by changing solely the aspect. In essence, we observe typical advantages generally associated with localized concerns with regards to future changes and program evolution. In particular, the problematic case of pattern composition and overlay [1, 25, 55, 76] becomes better structured (and easier to reason about) when pattern instances are defined in separate modular units. In addition to code-level benefits, the modularity of the design pattern implementation also results in an inherent documentation benefit. As mentioned in [1, 76], the mere existence of classes that exclusively contain pattern code serve as records of what patterns are being used. In the AspectJ cases, we observe two additional improvements. First, all code related to a particular pattern instance is contained in a single module (which defines participants, assigns roles, etc.). This means that the entire description of a pattern instance is localized and does not "get lost" [76] or "degenerate" [25] in the system. Secondly, with the current AspectJ IDE support, all references, advised methods etc. are hyperlinks that allow a developer an overview of the assignment of roles and where the conceptual operations of interest are. In 12 cases we were able to develop reusable pattern implementations. This happened by generalizing the roles, pattern code, communication protocols, and relevant conceptual operations in an abstract reusable aspect. For any concrete instance of the pattern, the developer defines the participants (assigns roles) and fills in instancespecific code. Changes to communication protocols or methods that are part of the abstract classes or interfaces involved do not require adjusting all participants. If we can reuse generalized pattern code and localize the code for a particular pattern instance, multiple instances of the same pattern in one application are not easily confused (composition transparency). The same participating object or class can even assume different roles in different instances of the same pattern (see the O B S E R V E R example above). This solves a common problem with having multiple instances of a design pattern in one application.  2.4.2  Specific Improvements  The Singleton case The AspectJ version of the pattern implementation opened up two new design options that are not possible in Java: First, is Singleton an inherited property, or do we have an inheritance anomaly? Second, do we want a devoted factory method to provide the Singleton instance, or do we want the constructor to return it whenever it is called? We decided to implement the Singleton property as inherited, but provided facilities to exclude specific subclasses from the pattern's constructor protection if desired. For the second, we decided that using the constructor instead of a devoted factory method was beneficial. The factory, if desired, can then be implemented either directly in the class, or as a transparently composed aspect.  Chapter 2. Design Pattern Implementations in Java and AspectJ  30  Multiple Inheritance and Java As originally presented, some of the GoF patterns make use of multiple-inheritance in their proposed implementation, for example the class version of the A D A P T E R pattern. For many patterns, the roles that participants play within the patterns are realized as abstract classes in Java. Participant classes inherit interfaces and default implementations from these abstract classes. But if the participant classes have functionality outside the pattern context (such as GUI widgets as Subjects or Observers in the O B S E R V E R pattern), they are usually already part of an inheritance hierarchy. Since Java lacks multiple inheritance, implementation in these cases can be somewhat awkward: In Java, if a participant has to inherit both its role and its other functionality, then one of the supertypes has to be realized as an interface. Unfortunately, interfaces in Java cannot contain code, making it impossible to attach default implementations of methods, for example. The open class mechanism in AspectJ provides us with a more flexible way of implementing these patterns, as it allows to attach both interfaces and implementations (code) to existing classes. Note that this does not solve the problems typically associated with multiple inheritance, such as as the ambiguties that arise when names of members of multiple supertypes collide, or, more specifically, the "diamond" problem [13]. Should such naming collisions occur, they are detected by the AspectJ compiler and need to be resolved by the developer.  Breaking Cyclic Dependencies Some design patterns regulate complex interactions between sets of objects. In objectoriented implementations these classes are tightly coupled and mutually dependent. One example of a design pattern that introduces cyclic dependencies is M E D I A T O R , a variation of the O B S E R V E R pattern that is often used in UI programming. Here, changes to Colleagues (e.g., widgets) trigger updates in the Mediator object. The Mediator, on the other hand, might update some or all of the Colleagues as a reaction to this. A typical structure for this pattern is shown in Figure 2.3 (a). Inheritance relationships (the Mediator and Colleague interface) are not shown. The pattern introduces cyclic dependencies between Mediator and Colleagues (denoted by arrows pointing in opposite directions). The pattern code (for updates, etc.) is distributed both over the Mediator and all Colleagues. In the AspectJ implementation shown in Figure 2.3 (b), the indirection introduced by the ConcreteMediator aspect removes the cyclic dependencies. The aspect defines the participants, assigns the roles and identifies which points in the execution trigger updates. Colleagues do not have to have any pattern-related code in them, they are "freed" of the pattern. Changes to the pattern (for example, the notification interface) are limited to a single module: the aspect. Again, an abstract aspect (here: MediatorProtocol) implements generalizable parts of the pattern.  Chapter 2. Design Pattern Implementations in Java and AspectJ  Colleague 1 (code)  31  MediatorPattern (code)  Colleague 4 (code)  7T Concrete Mediator (code)  | Concrete Mediator (code)  Colleague 1 Colleague 2 (code)  Colleague 3 (code)  (a) Object-oriented  Colleague 2  Colleague 4  Colleague 3  (b) Aspect-oriented  Figure 2.3: Dependencies and code distribution in typical instances of the M E D I A T O R pattern. The AspectJ implementation removes cyclic dependencies and localizes the pattern code  2.4.3 Crosscutting Structure of Design Patterns This section identifies the origins of crosscutting structure in the patterns, shows that the observed benefits of using AspectJ in a pattern implementation correlate with crosscutting in the pattern, and illustrates how the usage of roles within the pattern is indicative for their crosscutting nature. Roles define the behavior and functionality of participants in a pattern. Examples of such roles are Component, Leaf and Composite for the C O M P O S I T E pattern, Subject and Observer for the O B S E R V E R pattern, or Abstract- and ConcreteFactory for the A B S T R A C T F A C T O R Y pattern. Crosscutting in pattern structure is caused by different kinds of roles and their interaction with participant classes. In some patterns, the roles are defining: the participants have no functionality outside the pattern. That is, the roles define the participants completely. Objects that play the Faqade role, for example, provide a unified interface to a subsystem and usually have no other behavior of their own. Defining roles often include a client-accessible interface. In other patterns, the roles are superimposed: they are assigned to classes that have functionality and responsibility outside the pattern. In the O B S E R V E R pattern for example, the classes that play Subject and Observer roles do more than just fulfilling the pattern requirements. In a GUI context, Subjects could be widgets, for example. In other words, classes with superimposed roles have behavior outside the pattern context. The Subject role is thus only an augmentation of the already existing class. Superimposed roles usually do not have a client-accessible interface. In object-oriented programming, defining roles are often realized by subclassing an abstract superclass to achieve different but related behaviors; superimposed roles are often interfaces that specify behavior and responsibilities.  Chapter 2. Design Pattern Implementations in Java and AspectJ  32  ColorObscrvcr  (a) Classes playing multiple roles  (b) Mapping conceptual operations  Figure 2.4: Crosscutting caused by pattern composition. A second pattern instance introduces additional crosscutting  Roles and Crosscutting Superimposed roles lead to three different kinds of crosscutting among patterns and participants: • Roles can crosscut participant classes. That is, for one role, there can be n classes, and one class can have n roles; i.e., the Subject role as shown in Figure 2.4 (a). • Conceptual operations of interest (operations that trigger an Observer update) can crosscut methods in one or more classes. That is, for one conceptual operation there can be n methods, and one method can be in n conceptual operations; i.e., the s u b j e c t C h a n g e ( . . ) operations triggering an Observer update as shown in Figure 2.4 (b). • Roles from multiple patterns can crosscut each other with respect to classes and/or methods. That is, two or more classes that pattern A sees as part of one role, pattern B may see as in more than one role, and vice versa. The same is true for conceptual operations; i.e., the Subject role and s u b j e c t C h a n g e ( . . ) operations as shown in Figure 2.4 (a). Table 2.1 shows that the types of roles a pattern introduces and the observed benefits of an AspectJ implementation are correlated. The design patterns can be divided into three groups: those with only defining roles, those with both kinds of roles and those with only superimposed roles. The table shows that while the AspectJ implementations of the patterns infirstgroup show no improvements , patterns from the last group show improvements in all modularity benefit categories we identified. For patterns that have both kinds of roles, the results are dependent on the particular pattern. Given that AspectJ is intended to modularize crosscutting structure, this result should not be surprising. It says that patterns that involve primarily crosscutting structure are well modularized in an AspectJ implementation. (Note that AspectJ does not remove the crosscutting of the pattern, but rather provides mechanisms to modularize that structure.) 6  6  M i n o r improvements as outlined in Section 2.3 are not shown.  Chapter 2. Design Pattern Implementations in Java and AspectJ  Defining and Superimposed Roles The tight correlation between pattern roles, the crosscutting a pattern introduces, and the observed benefits of an AspectJ implementation suggest that the types of roles used within a pattern indicate whether a pattern implementation is crosscutting or not. With defining roles, each unit of abstraction (class) represents a single concept, meaning that the functionality of a class corresponds to its role in the pattern. Inheritance is used to distinguish between related but different implementations. In such a case, transparency and pluggability are not useful properties, as each participant is inherently useful only within one particular pattern instance. With superimposed behavior, the situation is different. Participants have their own responsibilities and justification outside the pattern context. If we force one such class into the pattern context, we have — at the very least — two concerns represented by one module of abstraction (class): the original functionality and the pattern-specific behavior. The resulting tangling and oftentimes code duplication can cause problems as the modularity is compromised. For these patterns and their implementations, a clean modularization of the pattern functionality and the original functionalities of the participants is desirable. In an AspectJ implementation it is usually possible to modularize the abstracted pattern behavior and have one aspect per pattern instance assign roles, conceptual operations, and fill in instance-specific code. Since the participants do have a meaning outside the pattern context, they are not inherently restricted to a single role or even a single pattern instance. This model appears to be accurate for those GoF patterns that have only defining or only superimposed roles. For others, the expected benefits seem to depend on the number of participants implementing a particular kind of role. Superimposed roles that map to multiple participants, such as Element in V I S I T O R , or Composite or Leaf in C O M P O S I T E , indicate potential for modularization, even if the pattern also includes defining roles.  2.5 Summary Improvements from using AspectJ in pattern implementations are directly correlated to the presence of crosscutting structure in the patterns. This crosscutting structure arises in patterns that superimpose behavior on their participants as indicated by the usage of roles within the pattern. In such patterns the roles can crosscut participant classes, and conceptual operations can crosscut methods (and constructors). Multiple such patterns can also crosscut each other with respect to shared participants. The improvements manifest themselves as a set of properties related to modularity. The pattern implementations are more localized, and in a number of cases are reusable. Because the AspectJ solutions better align dependencies in the code with dependencies in the solution structure, AspectJ implementations of the patterns are sometimes also composable. Localizing pattern implementation provides inherent code comprehensibility benefits: the existence of a single named unit of pattern code makes the presence and structure of the pattern more explicit. In addition, it provides an anchor for improved  33  Chapter 2. Design Pattern Implementations in Java and AspectJ  documentation of the code. Our results suggest that replacing object-oriented C C C implementations with aspects is beneficial for a set of useful and widely used concerns, due to improved modularity in the AspectJ implementations. Structurally the OO and AO version often vary considerably (as in the O B S E R V E R case, for example), rendering such transformations non-trivial. A subset of the OOP/AOP design pattern implementation pairs we developed provides the basis for an initial set of C C C refactorings we investigate. The next chapter introduces our role-based approach to C C C refactorings and illustrate how C C C refactorings, such as the transformation from an OO design pattern implementation to an aspect, are expressed using our role-based concern model.  34  35  Chapter 3  Role-Based Refactoring We now present a role-based approach to refactoring crosscutting concerns (CCCs). Our approach helps a developer transform a scattered implementation of a C C C into an equivalent, but modular, AOP implementation. In the previous chapter, roles were used to describe the behavior of types within a design pattern C C C . To model crosscutting concerns and their refactorings, we extend this concept to distinguish between the individual elements contributing to the implementation of a crosscutting concern. We differentiate between role types, role methods and role fields, which we collectively refer to as role elements. Role elements can be related to each other. We refer to these relations as role relations. Examples include contains relations between a role type and role methods, or a calls relation between two role methods. 7  Refactoring instructions are defined in terms of the role elements of the target concern. Together, a concern description and its refactoring instructions comprise a C C C refactoring description. Role elements and relations abstractly define the structure of the C C C without tying it to a concrete implementation. Thus, the use of roles allows a C C C refactoring to be defined separately from the concrete systems to which it may be applied, allowing the collection and reuse of existing refactoring instructions in a C C C refactoring library. To apply a C C C refactoring, the developer maps role elements to concrete program elements. Then, refactoring instructions are applied, changing the mapped program elements. References to affected program elements, such as calls to changed methods, are updated accordingly, so that the refactoring can affect non-mapped program elements as well. Our role-based approach is based on the observation that, for a given C C C , certain sets of program elements need to be refactored in the same principal way. For example, in a concrete instance of the OBSERVER pattern we can have multiple types playing the Subject role, all of which likely provide implementations for the attach(Observer) role method. Each of these concrete methods requires the same treatment in the transformation to an aspect-oriented implementation: being replaced with the addObserver (. . ) aspect method. We use a concrete example of a C C C refactoring to illustrate the approach. In this example, an instance of the OBSERVER pattern in the open source graphical editing framework JHotDraw [92] is refactored into an aspect. In this particular instance, the class DrawingView class acts as a Subject, and F i g u r e S e l e c t i o n L i s t e n e r acts as an Observer. The structure of the concern implementation and the mapping of role elements is shown in Figure 3.1. We use the notion of types to collectively refer to both interfaces and classes.  Chapter 3. Role-Based Refactoring  36  «Subject»  Drawing View «attach(Observer)» addFigureSelectionLis tener(FSL) «detach(Observer)» removeFigureSelcetionListener(FSL) «notify()» firaSelectionChangedQ  «Subject»  «Subject»  NullDrawingView  StandardDrawingView «attach(Obser ver)» addFigureSelectionListener(FSL) «detach(Observer)» removeFigureSelcetionListenerfFSL) «notlfy()» fire$electionChanged()  «Observer»  FigureSelectionListener «upda te(Sub]0Ct)» figureSelction Changad(Dra wing View)  i «Observer»  «Observer»  DrawingEditor  AbstractCommand  «updale(Subject)» figureSelctionChanged(DrawingView)  «update(Subject)» figureSelctionChanged(DrawingViaw)  Figure 3.1: The partial structure of an object-oriented instance of the O B S E R V E R pattern in the JHotDraw framework. The mapping of role elements to program elements is indicated using U M L stereotypes [73].  Chapter 3. Role-Based Refactoring  37  3.1 Workflow Applying a role-based refactoring to a C C C involves four steps: 1. Selecting a C C C refactoring. The developer chooses a refactoring from a library of C C C refactorings, or creates a new refactoring and adds it to the library. A C C C refactoring includes an abstract description of the concern it targets, and a set of refactoring instructions to produce a modular AOP implementation. Due to their abstract nature, such refactorings can be applied to multiple instances of the target concern. In the JHotDraw example, the developer chooses the O B S E R V E R design pattern C C C refactoring. 2. Stating a mapping. The role elements in the description of the C C C are mapped to the program elements of the scattered implementation. A C C C refactoring tool can help the developer map role elements. In the example, the developer might map the Subject role type to DrawingView and the Observer role type to F i g u r e S e l e c t i o n L i s t e n e r . Based on these initial mappings, the tool could then suggest further mappings, such as from update(Subject) to selectionChanged (DrawingView), that the developer can accept or reject. 3. Planning the refactoring. The C C C refactoring tool analyzes the planned refactoring steps as they would apply to the target system to identify choices in the refactoring process, and to provide the developer with associated tradeoffs. For example, the tool would warn the developer if an introduced method is accidentally matched by an existing pointcut. The developer decides how to resolve these cases. 4. Execution. Once the refactoring has been planned, the tool transforms the code according to the refactoring instructions, incorporating the decisions made in the planning step. The execution of the refactoring may result in the creation of new program elements, such as a new aspect to contain the modularized O B S E R V E R pattern, as well as changes to the existing code, such as the replacement of object methods with aspect methods or the removal of obsolete interfaces.  3.2  Describing Crosscutting Concerns  Conceptually, we differentiate between a concrete C C C and its abstract description. A concrete C C C is the actual implementation of the concern, while an abstract C C C generalizes the structure of concrete CCCs. For example, in the JHotDraw framework, there are multiple cases where the O B S E R V E R pattern has been used. These are multiple concrete scattered O B S E R V E R C C C S . All of them have a similar structure, which is captured in the abstract O B S E R V E R C C C . Each C C C refactoring in the library includes an abstract description of the concern it targets in terms of its role elements and role relations. Role elements are named to differentiate between program elements of the same kind (types, methods, orfields)that  Chapter 3. Role-Based Refactoring  38  Table 3.1: Role Elements and their Relationships Possible Relationships with other Role Elements Method Field Role Element Type contains contains Type returns, hasArgument calls Method Field hasType Subject  Observer  observers  aggregates.  " update(Subject)  hasArgument...--' attach(Observer) hasArgument..--' detach(Observer)  notifyO  calls  Figure 3.2: Role elements in the O B S E R V E R C C C . Role types are represented as squares, role methods as rounded squares and role fields as hexagons. The structure reflects the pull variant of the pattern [28]  fulfill different functions within the concern, for example between attach(Observer) and notifyO, both of which are role methods in the O B S E R V E R C C C . Role relations are directed, binary relationships between role elements, such as the calls role relation between notifyO and update(Subject). Table 3.1 depicts relations between kinds of role elements we have found useful in the C C C refactorings we have considered. The kinds of role elements and role relations used in C C C refactoring may need to be extended as more CCCs are considered; for example, role relations describing that types extend types may be needed. A crosscutting concern description is thus effectively a graph in which role elements are nodes and role relations are edges. For instance, the structure of the Observer C C C is shown in Figure 3.2. Note that the distinction between Subject as an interface and Subject as a concrete type — as suggested by the GoF design pattern description — is an implementation issue and not a conceptual one; hence it is not reflected in the CCC description. Given the spectrum of implementation variants for CCCs, an important question is how to deal with potentially varying concern structures, such as known implementation variants for design patterns. Chapter 6 discusses this issue in detail.  Chapter 3. Role-Based Refactoring  3.3  39  Describing Refactorings  To execute a C C C refactoring, a set of transformation steps needs to be defined that transforms the code base and modularizes the scattered concern. These transformations are captured in the C C C refactoring instructions. C C C refactoring instructions consist of an ordered set of refactoring primitives, which are composite refactorings that are parameterized in terms of role elements. For example, one step in the O B S E R V E R C C C refactoring instructions consists of applying the replace object method with aspect method refactoring primitive to the original attach(Observer) methods. This primitive is itself composed of multiple other refactoring primitives, including steps to update call sites to the original method and to adjust import statements of the involved types.  3.4  Mapping Role Elements  Applying a C C C refactoring requires a mapping from the abstract C C C description to program elements in a code base that comprise a concrete C C C implementation. The set of mappings is a partial binary relation associating each role element with zero or more program elements. The process of mapping role elements to program elements is aided by the approach. Based on initial partial mapping information provided by the developer, a comparison of the structure of the abstract C C C and a static analysis of the type hierarchy and call graph structure of the target software can be used to suggest additional mappings. For instance, if a developer has mapped the Subject.attach(Observer) role method onto a d d F i g u r e S e l e c t i o n L i s t e n e r ( . . ) on DrawingView, a tool can straightforwardly infer a mapping of the Subject role type to DrawingView based on the contains role relation between Subject and attach(Observer). Similarly, the tool can suggest mapping the Observer role type to F i g u r e S e l e c t i o n L i s t e n e r based on the hasArgument relation between attach(Observer) and Observer. Figure 3.3 shows the initial and derived mappings. The mapping algorithm can be applied iteratively using derived mappings as the basis for further inferences. A comparison of the structure in the abstract C C C and the program structure can also reveal potentially incorrect mappings, and suggest alternative mappings that match the abstract C C C structure more closely. For example, it can be detected whether the concrete methods that a role method is mapped to have the wrong argument or enclosing type, or whether the implementation is missing parts of the structure of the C C C . In both cases, the developer can be presented with the current mapping and the mapped elements that do not match the structure of the C C C description. Potential alternatives are evaluated based on the fit of the C C C description and the structure of the mapped elements. Structural information inherent in the C C C description provides an initial ranking (the mapping with the fewest deviations has the best fit; all role element relationships are considered equally important for this purpose). Note that the algorithms for completing and checking partial mappings are not tied to a specific concern, but rather work on any abstract CCCs expressed in terms of role elements and  Chapter 3. Role-Based Refactoring  Subject  —  obsei'.i-  •  40  DrawlngView  ^addFigureSelectionListener(FigureSelectionListener)  attach(Observcr)  removeFigureSelcetionListener( FigureSelectionListener)  detach(Observer)  fireSeiection Changed()  notifyO  Observer  update (Subject)  - •  FigureSelectionListener  figureSelctionChanged(DrawingView)  Figure 3.3: Based on an initial mapping (solid arrow), further mappings can be inferred (dashed arrows)  their relationships. To further facilitate the mapping process, it is possible to augment the abstract C C C description with non-structural information about the role elements, such as lexical or semantic information, as described in Chapter 4. In summary, a comparison of the program's AST and the abstract concern structure can aid in finding scattered program elements directly corresponding to role elements. Program elements related to the concern, such as call sites for a mapped method, need not be explicitly identified and are automatically updated when the code is transformed (see Section 3.6).  3.5  Impact Analysis  Impact analyses are static program analyses that can be utilized to assess the impact of a planned change to the code base. Whenever an impact analysis discovers a decision to be made by the programmer, it can initiate a dialog with the developer, presenting the associated information to allow a decision to be reached. Four pieces of information can be presented to the developer: the situation, the alternatives, the associated tradeoffs, and a recommendation. This is analogous to the way refactorings support is provided by current IDEs such as Eclipse, except that the analyses need to consider AOP elements, and the involved tests tend to be more complex as multiple planned refactoring steps have to be considered together. The aspect-oriented refactoring steps comprising a C C C refactoring can adversely affect other parts of the target system. For example, the dynamic behavior of a system using i n s t a n c e o f tests can change if a refactoring introduces additional interfaces via d e c l a r e p a r e n t s statements. Similarly, a changing or newly created program element can be matched by an exsiting pointcut, causing associated advice to no long apply or to apply in the wrong circumstances. A partial list of the implications that changes to an aspect-oriented code base can have is presented in [36].  Chapter 3. Role-Based Refactoring  41  C C C refactorings add an additional level of complexity as they consist of a series of individual refactoring steps, which can potentially interfere with each other. For example, a refactoring step can modify or delete a program element that is referred to in a subsequent refactoring. Effectively, analyzing a CCC refactoring means analyzing the pre- and postconditions for each refactoring step sequentially, while taking into account how each step affects the target program. Static analysis can usually conservatively determine whether a proposed transformation of an aspect-oriented system may have an adverse effect, but determining the precise effect on the behavior of the system is often difficult [36]. If we take into account that some changes in behavior are acceptable if the intent of the concern is preserved, and that automated analysis techniques fail to capture and test intent, presenting the case as a decision point to the developer is often the only tractable option. Section 4.3 describes the impact analyses we implemented for our tool.  3.6  Executing Refactorings  Once the refactoring has been planned and all of the associated decision points in its application have been resolved, a supporting tool can perform the code manipulations. The tool follows the refactoring description, performing refactoring instructions on all concrete program elements which are mapped to role elements that the instructions refer to. Other, non-mapped program elements that reference changing portions of the program are updated accordingly.  3.7 Example To illustrate the kinds of steps involved in refactoring a CCC, we use the example from the beginning of this chapter to describe the steps involved in transforming an object-oriented instance of the O B S E R V E R pattern in JHotDraw into an aspect-oriented version. The refactoring instructions we use for the example assume a library aspect that abstracts commonalities of the O B S E R V E R pattern from [38]. Listing 2.1 shows the structure of the abstract library aspect for the O B S E R V E R case. The library aspect contains most of the pattern functionality, including facilities for the addition and removal of observers per subject, and the notification logic that triggers observer updates when a change of interest occurs. As outlined in Chapter 2, for a concrete instance of the pattern, a developer only needs to subclass this aspect, specify which types act as Subjects and Observers, concretize the sub j e c t C h a n g e (. . ) pointcut to specify what constitutes a change of interest, and override the u p d a t e ( . . ) method to define the update behavior. The required refactoring steps for the general O B S E R V E R C C C refactoring are described below. For brevity, instructions for removal of program elements rendered obsolete by the modifications (empty interfaces, unused variables, etc.) are omitted. The aspect-oriented refactorings named are described in Appendix B. 1. Create a new aspect to modularize the CCC and assign it a name selected by the developer, extending the existing O b s e r v e r P r o t o c o l library aspect using  Chapter 3. Role-Based Refactoring  42  the create subaspect refactoring. 2. Add d e c l a r e p a r e n t s statements to the new aspect to programmatically assign the internal S u b j e c t and O b s e r v e r interfaces. This is realized using the add internal interface refactoring with the role types Subject and Observer as parameters. 3. Replace the existing methods for adding, removing, and updating observers with the provided aspect methods. The refactoring replace object method with aspect method is applied to attach{Observer), detach(Observer), and update(Subject). 4. Replace the update logic by using the replace method call with pointcut and advice refactoring applied to the notifyO role method. Applying the same refactoring to another instance of the O B S E R V E R C C C would not require changing the refactoring steps, but only the mappings of role elements to program elements. As long as the new instance of the pattern has the required structure, the same C C C refactoring can be applied. Varying names of concrete program elements comprising the concern implemenration do not pose a problem due to the abstractness of the underlying role-based concern model.  3.8 Summary Transforming a scattered implementation of a crosscutting concern into a modular A O P implementation requires many changes to the code. In this chapter we have introduced an approach for refactoring CCCs based on roles. The roles allow the abstract description of the C C C ; without this abstraction, each time a similar scattered implementation of a C C C appears in the code for a system, a refactoring would have to be built from scratch. The applicability of a role-based refactoring is determined by the structure of the target concern implementation and not the names of the program elements comprising it. Creating a concern description and associated refactoring instructions requires expert knowledge of the targeted concern. In Section 6.3 we consider approaches to create these descriptions automatically during program investigation, but this is future work. In the case of design pattern C C C reactorings, the concern structures generally match the design pattern structures as defined in [28], except for the lack of differentiation between interfaces and classes in the role-based model. Developing refactoring instructions is similarly straightforward if the desired aspect-oriented structure is known, as is the case for the investigated design pattern CCCs. In describing the approach, we focused on a specific kind of C C C refactorings: refactorings of non-modularized crosscutting concerns into aspects. The main application we envision is the stepwise adaption of A O P for an O O system. In order for the approach to express refactorings of exisiting A O P implementations, the concern model would have to be extended to include aspect-oriented role elements, such as pointcuts and advice, as well as appropriate role relations. Such an extension of the role-based refactoring approach is future work.  Chapter 3. Role-Based Refactoring  43  In the following two chapters, we will show that the approach can be realized in a refactoring tool and we will use our tool to transform instances of different nonmodularized CCCs into aspects to show that the approach is not limited to design pattern CCCs, and that it is viable for refactoring non-trivial code.  44  Chapter 4  Tool Support for Role-Based Refactoring We have developed a tool for the role-based refactoring of crosscutting concerns and realized it as a plugin for the Eclipse IDE. Our tool consists of three main modules: a refactoring engine that is responsible for performing code transformations, the automapper, which aids the developer in completing mappings of role elements to program elements, and the impact analysis module, which provides a series of refactoring checks to identify potential problems with a planned refactoring. Figure 4.1 shows an overview of the architecture of the tool. The tool relies on different forms of representation of the target program, which are derived from the program source via existing tools, primarily the Eclipse [91] program models. Further, a database of program facts is used by the automapper module and two AspectJ Development Tools (AJDT) [87] program models are used in impact analyses involving aspect-oriented program elements (not shown). The two Eclipse program models consist of an abstract syntax tree (AST) representation and the Java Development Tools (JDT) model. We mostly rely on the JDT model in our tool as it provides a suitable and easily accessible interface to obtain information about program elements. The AST representation is used for certain searches within the refactoring engine. A JavaDB database of program facts is employed by the automapper module. It contains information derived from the Eclipse A S T that complements the Eclipse models. Solely for the purpose of impact analysis involving aspect-oriented program elements, we use the two program models generated by the AJDT. These two representations are analogous to Eclipse's AST and JDT model, but contain aspect-specific information. 8  4.1  The Refactoring Engine  The refactoring engine is responsible for planning and executing the C C C refactorings. For a given C C C refactoring, it maintains a representation of the concern structure and the mapping between role elements and program elements. Refactorings are executed — after consultation with the impact analysis module to identify and resolve potential problems with the planned refactoring — by executing the refactoring instructions on the mapped program elements to create the target concern structure. This includes 8  JavaDB is part of the F E A T tool [72].  Chapter 4. Tool Support for Role-Based Refactoring  45  Figure 4.1: The C C C refactoring tool architecture. Existing software used is shown in grey  creating aspects, modifying or removing original program elements, and updating references to them. These changes to the target system are of the form of buffer manipulations to the affected compilation units, in other words text changes to the Java files. We chose the realization as buffer manipulation over AST manipulations because several of the components we use, specifically AJDT and JDT, were in development during the development of our tool and their APIs were not stable. Future versions of our tool could utilize these models better and realize changes as transformations of the target program's AST instead (see Section 6.2.2), which would facilitate the generation of intermediate ASTs (i.e., between individual refactoring steps) and help manage the consistency of changes (see Section 4.1.3). Individual program transformations steps are analyzed with respect to their impact on the rest of the system to detect potential deviations in system behavior caused by them. Since some behavioral changes are acceptable if the intent of the tageted concern is preserved, these cases are presented to and resolved by the developer, as outlined in Section 4.3. In a few cases, the developer may have to adjust the created code slightly, for example when an object method is replaced with an aspect method, as this may affect the scoping of statements within the original method. Such cases are realized by providing appropriate in-code suggestions. In the example of the method replacement, the suggestion for the new method body would consist of the body of the original method in commented form. Similarly, post-refactoring review of the generated code is required  Chapter 4. Tool Support for Role-Based Refactoring  1 2 3 4 5 6 7 « 9 10 n 12 13 14 15 16 17 is 19 20 21 22 23 24 25 26 27 28 29 30 31 32  46  < C o n c e r n D e s c r i p t i o n name="Observer CCC"> <RoleType> < T y p e N a m e > S u b j e c t </TypeName> <RoleMethod> < M e t h o d N a m e > a t t a c h </MethodName> <Argument> < A r g u m e n t N a m e > O b s e r v e r </ArgumentName> </Argument> </RoleMethod> <RoleMethod> <MethodName>detach </MethodName> <Argument> < A r g u m e n t N a m e > O b s e r v e r </ArgumentName> </Argument> </RoleMethod> <RoleMethod> < M e t h o d N a m e > n o t i f y </MethodName> </RoleMethod> <RoleField> < F i e l d N a m e > o b s e r v e r s </FieldName> </RoleField> </RoleType> <RoleType> <TypeName>Observer</TypeName> <RoleMethod> <MethodName>update </MethodName> <Argument> < A r g u m e n t N a m e > S u b j e c t </ArgumentName> </Argument> </RoleMethod> </RoleType> </ConcernDescription>  Figure 4.2: Concern structure description of the Observer C C C as used by the refactoring tool.  if a refactoring replaces multiple mapped program elements with a single construct, as is the case in the C H A I N O F R E S P O N S I B I L I T Y C C C refactoring, where the various handlefRequest) methods are aggregated in two aspect methods. In these cases, the tool suggests for the bodies of the aspect methods the bodies of all of the original handler methods in commented form. If a post-refactoring review is required, the behavior of the original system is generally not preserved until the developer makes the proper adjustments. These adjustments usually have a granularity of statements rather than types or methods and are aided by code suggestions generated by the refactoring engine.  4.1.1  Representing Crosscutting Concerns  We express concern descriptions using an Extensible Markup Language (XML) [10] representation of the role elements and role relations. A typical description of a concern structure is shown in Figure 4.2. Conceptually, this description results in a structure as shown in Figure 3.2.  Chapter 4. Tool Support for Role-Based Refactoring  4.1.2  47  Refactoring Primitives  Instructions for CCCs refactorings consist of a series of calls to a library of refactoring primitives. These primitives are aspect-oriented composite refactorings. A complete list of implemented refactoring primitives can be found in Appendix B. All primitives are realized as subtypes of Eclipse's abstract R e f a c t o r i n g class. For our purposes, two methods are of interest: c h e c k l n i t i a l C o n d i t i o n s ( . . ) and createChange (). The former checks that the supplied parameters (role elements) contain appropriate mappings and performs a refactoring-specific analysis of the targeted code to decide whether the refactoring can be applied as planned. The latter creates a Change object that contains the required program transformation steps. We implemented several refactoring primitives, which can be divided into three categories: creational, transformational, and destructive program transformations. Creational Primitives These primitives create aspect-oriented programming constructs such as aspects, pointcuts, and advice. Primitives in this category are parameterized to reflect the wide variety of possible manifestations of the associated programming constructs. Due to the complexities involved with creating these constructs, the actual implementations of these refactorings are broken down into various specialized cases. For example, the Create Pointcut refactoring encompasses cases such as creating a PC matching a set of method calls, creating joint PCs from two existing PCs, and creating PCs capturing executions of all methods in a particular type. The following list is an overview of the creational refactoring primitives. • Create Aspect - creates a new stand-alone aspect to hold the modularized implementation of the target C C C . • Create Subaspect - creates an aspect as a subaspect of an existing abstract library aspect. • Create Aspect from Library Aspect - as above, but copies the library aspect structure and results in a stand-alone aspect. • Create Advice - creates an advice for a given aspect. • Create Pointcut - creates a pointcut for a given aspect. • Create Inter-Type Declaration - creates a method orfieldITD. Aspect creation differs from other refactoring primitives in that it happens before other refactoring steps are even planned. This is vital to ensure that the program elements of the newly created aspect are available in the Eclipse A S T and JST program representations. For example, the O B S E R V E R refactoring refers to the change () pointcut, which is generated as part of the aspect creation, in subsequent refactoring steps. By creating the aspect before other planning refactoring steps, it can be compiled and appears in the Eclipse program models we rely on.  Chapter 4. Tool Support for Role-Based Refactoring  48  Transformational Primitives Refactorings in this category manipulate existing programming constructs. Typical examples include low-level refactorings such as moving members from classes to aspects (replacing them with inter-type declarations) or changing imports of a class or aspect, and high-level transformations, such as replacing an abstract class with an interface and aspect-supplied inter-type declarations. • Change Abstract Class to Interface - replaces an abstract class with an interface and appropriate inter-type declarations. • Change Accessibility Modifier - changes the accessibility modifier (public, private, etc.) of a member. • Change Variable Type - changes the type of a variable. • Change Imports - adjusts the imports of a type. • Move Object Member to Aspect - replaces an object member with an equivalent inter-type declaration. • Remove Argument - removes an argument from a method. • Replace Method - replaces a method with another method and updates the call sites. • Replace Object Method with Aspect Method - replaces an instance method with a (static) aspect method.  Destructive Refactorings Destructive refactorings remove program elements such as methods, fields and types. They are mainly used to dispose of elements that the refactoring renders obsolete, for example the observersfieldon Subjects in the O B S E R V E R C C C that is not required in the aspect-oriented version of the pattern. These refactorings — as opposed to the ones mentioned before — have rather straightforward implementations. • Remove Type - removes a type from the system. • Remove Member - removes a member. • Remove Method Calls - deletes all call sites to a particular method. • Remove Field References - deletes all references to a given field.  Chapter 4. Tool Support for Role-Based Refactoring  4.1.3  49  Interference of Refactoring Primitives  All refactoring primitives, except for those that create aspects, are implemented as source code buffer modifications of existing types. The affected regions of the code are determined from querying the affected JDT program elements. Unfortunately, since the program models do not get updated during the refactoring, it is possible that one refactoring step invalidates subsequent refactorings of the same source/buffer. It is conceivable that a future version of the refactoring tool could compute the affected code area dynamically based on previous changes, thereby avoiding these invalidations. Currently however, changes can interfere with each other. This is the case when a refactoring step replaces a region of the buffer with a region of different length, and a subsequent step affects a region in the buffer with a higher offset. It is further possible that one change affects a region of code that lies with the region of another change. For example a Remove Method change can target a method that contains a field reference targeted by a Remove Field Reference refactoring. Clearly, only the former is necessary. If both of these overlapping changes are applied, the buffer becomes inconsistent. We address these potential problems by analyzing the proposed changes before they are applied. During the sorting process, the tree-like structure of changes associate with a C C C refactoring is replaced with a flat list of refactoring steps, sorted in descending order by the affected compilation unit and the offset of the affected buffer region. This ensures that for each refactoring step, all subsequent steps affect either an untouched region of the same buffer or a different buffer altogether, eliminating the danger of destructive interference between refactoring steps. In all investigated cases, overlapping changes occur either when statements within a method are changed and the method is marked for deletion, or two or more changes affect the same region in the same way (duplicate changes). These cases can therefore be resolved by removing the contained changes. Figure 4.3 show this process schematically. The composite change is initially unsorted and contains overlapping changes (a). After processing the change, overlapping regions are resolved and the changes are sorted in ascending offset order to avoid inconsistent buffer modifications (b). If changes were realized as direct AST mutations instead of buffer modifications, overlapping changes are also possible, but easier to resolve. In case of the method and field reference overlap as described above, the two changes would not create inconsistencies; the end result is the program AST without the subtree representing the method, regardless which refactoring is applied first.  4.1.4  Implementation of CCC Refactoring Instructions  Implementing C C C refactoring instructions requires translating the necessary refactoring steps into calls to the refactoring primitives provided by the tool. In essence, every conceptual refactoring step translates into a call to the appropriate parameterized primitive. Consider for example the refactoring of the Observer instance in JHotDraw from the previous chapter. Table 4.1 shows the principal refactoring steps identified in Section 3.7 (left column) and their implementation as a C C C refactoring in our tool (right). The right column shows the entire code for the C C C refactoring. Only consistency checks for potentially invalid mappings are omitted.  Chapter 4. Tool Support for Role-Based Refactoring  All Changes  All Changes Change A  Change C  Change B  Change E  Change C  Change A  Change D Change E  (a) before  (b) after  Figure 4.3: Pre-processing of buffer modifications  50  Table 4.1: Conceptual refactoring steps and their implementation ( O B S E R V E R ) Refactoring Step  Implementation  Create new aspect  IType  conereteAspect  =  createSubaspect(newAspectName,  findType(abstractAspectName), getTypes{"Observer")[0].getPackageFragment(), Specify role names for internal interfaces  new  String[]  {"Subject",  "Observer"},  Specify corresponding internal interface names  new  String!]  {"Subject",  "Observer"});  Replace Object Methods with Aspect Methods  addChange(ReplaceObjectMethodsWithAspectMethods.create(getMethods("attach"), findMethod(concreteAspect, "addObserver"), concreteAspect)),addChange(ReplaceObjectMethodsWithAspectMethods.create(getMethods("detach") findMethod(concreteAspect,  ,  "removeObserver"),  c o n c r e t e A s p e c t ) ) ,addChange(SuggestMethodBody.create(getMethod("update"), findMethodfconcreteAspect, Create pointcut capturing calls to notify()  " u p d a t e O b s e r v e r " ) ) ) ,-  addChange(CreatePointcutRefactoring.create(findCallsToMethods(getMethods("notify")), findMethodlnType(concreteAspect, new  IType[]  new  String[]  null, Remove notifyi) and calls to it  "subjectChange"),  findType{"Subject"), "s",  null));  addChange(RemoveMethodCallsRefactoring.create(getMethods("notify"))); addChange(MethodDeletionChange.create(getMethods("notify")));  Chapter 4. Tool Support for Role-Based Refactoring  52  Implementations of the C C C refactorings we investigated can be found in the appendix. We realized a total of 11 GoF design pattern (see Section 4.5) refactorings and 4 non-pattern refactorings (see Section 5.3). Our C C C refactoring instructions, including the instructions for non-pattern concerns (Chapter 5), range from three ( E X T R A C T I N T E R F A C E , S I N G L E T O N ) to eight ( W O R M H O L E ) calls to the tool's refactoring primitives, with an average of 5.4 calls.  4.1.5  Representing Aspect-Oriented Program Constructs  The refactoring engine relies in large parts on the Eclipse program models: the A S T and JDT. Unfortunately, neither of them includes facilities to express aspect-oriented programming constructs. Since we did not want to restrict the tool to pure OO code, we needed to create a means to include these concstructs in the AST and JDT models . We achieved this by masking all aspect-oriented program elements at the beginning of a refactoring using comments. After the refactoring is completed, these masked sections are translated back into aspect-oriented code. For example, the abstract c h a n g e ( . . ) pointcut of the reusable aspect-oriented O B S E R V E R implementation is represented as follows: 9  //  <ASPECT>protected abstract  //  <CLASS>  protected //  abstract  void  pointcut  subjectChange{Subject  subjectChange{Subject  s);</ASPECT>  s);  </CLASS>  The <CLASS> portion provides an object-oriented stand-in for the pointcut. The Eclipse parser parses it as a method and provides an appropriate representation to which the refactoring instructions can refer. After the refactoring, this section is replaced with the <ASPECT> portion: protected  abstract  pointcut  subjectChange(Subject  s);  Masking always produces a valid Java program. This approach, while inelegant, works for the investigated refactorings. We expect that, as AJDT matures and opens up the interface for accessing its program representations, future implementations of our role-based refactoring approach will be able to use the AJDT exclusively. This would alleviate the need for masking AOP constructs.  4.2  Auto-Mapping Support  The AutoMapper module facilitates the mapping of role elements onto concrete program elements, according to the algorithm outlined in Section 3.4. Based on one or more initial mappings provided by the developer, the automapper attempts to match A n alternative we considered was using A J D T program models exclusively instead of the Eclipse A S T / J D T for our refactoring engine. This turned out to be problematic, due to the constant flux of their internal implementation and, at least in the beginning of the development of our tool, their incompleteness. 9  Chapter 4. Tool Support for Role-Based Refactoring  53  the C C C structure with the structure of the target program. The program structure used comprises hierarchical relationships derived from the ASTs and method call relationships as provided by the JavaDB program facts database. This structural analysis generates candidate program elements for unmapped roles. Ambiguities can arise when multiple concrete program elements qualify for a mapping to a single role element. We will illustrate this on the example of the O B S E R V E R pattern instance. Assuming that an initial mapping exists for the role types Subject and Observer, we will consider the case of deriving mapping candidates for the role method attach(Observer) on Subject. Based on structural information alone, the algorithm will suggest all program elements p £ P that fulfill the following requirements: 1. p is a method 2. p is a member of the type(s) Subject 3. p has an argument that matches the type Observer In this case, two role elements have the same set of associated requirements: the attach(Observer) and detach(Observer) role methods on Subject are identical from the perspective of structural automapping. Consequently, the concrete program elements implementing the two methods will both appear as candidates for either role method mappings. To rank multiple candidates for a single role, we use lexical information about the role elements stored in the abstract C C C descriptions. Lexical information constitutes a set of name fragments (currently substrings) that are likely to be used for concrete program elements playing a particular role. For example, it is more likely that a concrete implementation of the role method attach(Observer) has a name containing either "add" or "attach", than "remove", or "detach". Some of the lexical rules used to automap this C C C are shown in Table 4.2. The weights of each matching rule are summed to determine the score of the mapping candidate. We assigned the weights based on our subjective expectations of the likelihood that the rule would be indicative. Table 4.2 shows weights for three role elements. The auto-mapping process is iterative, so if the developer accepts one or more suggestions, subsequent steps take these new mappings into account. Other kinds of support for automapping are conceivable, we will address two promising ideas as future work in Section 6.2.1.  4.3  Support for Impact Analyses  The Impact Analysis (IA) module aims to identify the effect of a planned refactoring on the rest of the system, and to resolve potential problems with the developer. The module generates appropriate dialogues with the developer when it (conservatively) determines that a planned change may affect the behavior of the target system. Resolving such potential problems can affect the refactoring workflow, usually by undoing a transformation step or aborting the refactoring if inconsistencies are detected.  Chapter 4. Tool Support for Role-Based Refactoring  54  Table 4.2: Sample weights for name fragments for role elements Role Element Name Fragment Weight attach( Observer) "add" 2 attach( Observer) "attach" 3 attach( Observer) "remove" -2 attach( Observer) "detach" -3 attach( Observer) "observer" 1 attach( Observer) "listener" 1 notifyO "notify" 3 1 notifyO "change" "observer" 1 notifyO notifyO "listener" 1 Observer "observer" 3 Observer "listener" 3  To illustrate the concept of impact analyses, we implemented a number of sample analyses. It was not our goal to provide an exhaustive set of analyses for our tool. Instead, we aimed to explore how impact analyses fit into the C C C refactoring workflow. We differentiate between pre-condition checks that are specific to the individual refactorings (primitives or C C C refactorings) and global checks that can apply to multiple program transformations. Pre-condition checks operate on the program elements passed to the refactoring object and ensure that the refactoring can be properly executed. If a pre-condition is not met, the refactoring will either not be executed or will require developer confirmation, depending on the severity of the problem. For example, in the move object member to aspect refactoring, static object members can not be replaced with an intertype declaration, and appropriate enabling refactorings are non-obvious, so the refactoring fails. If the chosen member was protected instead, the tool would offer the developer the choice to change the accessibility of the member (and related members in the inheritance hierarchy) to public. This would allow the refactoring to proceed, but as it affects the semantics of the program, developer confirmation is required. Note that in the case of composite refactorings, pre-condition checks can be redundant . 10  Global impact analyses apply to multiple refactorings. These analyses are not part of the individual refactoring descriptions but are instead realized separately as aspects to avoid a scattered implementation, since the analyses need to collect information about the system and planned refactoring from various places in the workflow. One example for an impact analysis in this category determines if a method is manipulated in a way that might affect pointcuts that refer to it. Should this be the case, the transformation can affect the system's behavior and the developer can choose to abort the refactoring, or proceed if it does not affect the intent of the original implementation. The required information about pointcut matches is extracted from the AJDT program models. The implementation as aspects has the further benefit that costly impact analKniesel presents a possible approach that could be utilized to address the redundancy of precondition checks of composite refactorings [47] 10  Chapter 4. Tool Support for Role-Based Refactoring  K Ou'l na  a ^  =  55  •  Observer:  1  - % update(Subject): void  !  Q %  Subject ^3 attach(Observer): void "fe detach(Observer): void *b notify(): void • a r  observers  Figure 4.4: Structure of the O B S E R V E R C C C as presented by the refactoring tool.  yses can be easily removed from or added to the tool as desired. We do currently not have a universal analysis framework that provides implementations of complex program analyses, such as those affecting the type structure (e.g., see [81]). The development of such a framework and additional impact analyses, in particular dependency analyses for individual refactoring steps, such as through Conditional Transformations [47], are future work.  4.4 Example In the following, we illustrate the operation of our role-based refactoring tool by using it to refactor an instance of the O B S E R V E R pattern in the figure package described in 2.3.1. We assume that the developer using the tool is aware that changes to FigureElements trigger updates of the Display, and accordingly chooses the O B S E R V E R C C C refactoring. The O B S E R V E R C C C structure is shown in Figure 3.2.  4.4.1  Mapping  The tool presents a tree view of the role elements comprising the O B S E R V E R concern. The hierarchy reflects the contains relationships between role elements; other relationships, such as calls or hasArgument are not shown. Figure 4.4 depicts the structure of the O B S E R V E R concern as presented to the developer. The developer provides an initial mapping of Subject to FigureElement and Observer to Display, based on his knowledge of the system. Mappings are realized by selecting a role element and assigning a concrete program element to it. Figure 4.5 illustrates this for the Observer i—• D i s p l a y mapping. Proposed mappings are checked by the tool to ensure mapped program elements are of the proper kind (i.e., a role type can only be mapped to interfaces and classes, not methods and fields). After providing these two initial mappings, the automapping facilities of the refactoring tool are used to complete the mappings. First, subtypes of FigureElement are trivially identified as further candidates for Subject, and mapped manually by  56  Chapter 4. Tool Support for Role-Based Refactoring  Hierarchy! Navigator |'  •cn.  &AOR Refectory £3 \ p u t l i n e j \ ^  1PI ® Observer CCC  v i >Rgure Package [cascade.cs.ubc.ca] P-:-ff!§src ... . ;.tl \$ ca.ubc.cs.spl.aspectPatterns.library i S -{^ figurePackage • I • i.'j D splayitivo 1.2 (ASCII-kkv) H Q New r a. neme • I-'eP Display Open ; © display^ Open With updote(Opon Typo Hierarchy i. . i±i~ Figure.java-1 . L+i'Ul FigureElemer* CCCR: Map to Selected Role f+ in Line java 1.3 WJJ Main.java 1.S Debug E - g j MonitorObser Team te*L$ Point.java 1.1 •  fi|  update(Subject): void Subject % attach(Observer): void 1> detach(Observer): void ~~ \ notifyf): void . ^ p - ^ r - bservers El  F3 .  0  Figure 4.5: Mapping the Observer role to the D i s p l a y interface.  the developer. In the next automapping iteration initiated by the developer, candidates for the role methods and role fields are identified. For example, to determine candidates for the attach(Observer) method, the automapper identifies two methods with matching signature: the methods addChangeObserver ( . . ) and removeChangeObserver (. . ) (both declared in the FigureElement interface, and defined in P o i n t and Line) match the structural analysis. The automapper differentiates them based on the lexical analysis outlined in section 4.2. The analysis for the attach(Observer) mapping to methods on Point, for example, is shown in Figure 4.6. The automapping facilities correctly ranks candidate method addChangeObserver ( . . ) highest, and the developer selects the appropriate mapping by browsing to the suggested code element and mapping it manually. Mappings for attach(Observer) to methods on FigureElement are resolved the same way. Candidates for detach(Observer), notifyO and update(Subject) are identified in a similar fashion, but for each of these only one candidate method exists, so a lexical analysis is not required. The observers role field is not identified automatically as the automapping facilities do not currently handle aggregate types. The completed mappings are shown in Figure 4.7.  4.4.2  Impact Analysis  To illustrate the concept of impact analysis, we use the example of an impact analysis warning the developer when a method scheduled for deletion is advised by an existing aspect in the system. To show this, we created an aspect that advises the P o i n t . addChangeObserver ( . . ) method. Since all methods attach(Observer) is mapped to are deleted in the course of an O B S E R V E R refactoring, the appropriate impact analysis produces a warning before the refactoring is executed, as shown in  Chapter 4. Tool Support for Role-Based Refactoring  i i 3 4 5 s 7 8 9 10 n 12 13 14 15  57  Processing role element: attach (Observer): void » > Candidates after structural inference: C a n d i d a t e f o r a t t a c h : r e m o v e C h a n g e O b s e r v e r ( l e x i c a l : 0) C a n d i d a t e f o r a t t a c h : a d d C h a n g e O b s e r v e r ( l e x i c a l : 0) Candidate is removeChangeObserver Testing 6 lexical r u l e s . . . C o n t a i n s : " r e m o v e " , new s c o r e i s - 2 C o n t a i n s : " o b s e r v e r " , new s c o r e i s — 1 Candidate is addChangeObserver Testing 6 lexical r u l e s . . . C o n t a i n s : " a d d " , new s c o r e i s 2 C o n t a i n s : " o b s e r v e r " , new s c o r e i s 3 » > C a n d i d a t e s a f t e r l e x i c a l and s e m a n t i c i n f e r e n c e : C a n d i d a t e f o r a t t a c h : r e m o v e C h a n g e O b s e r v e r ( l e x i c a l : —1) C a n d i d a t e f o r a t t a c h : a d d C h a n g e O b s e r v e r ( l e x i c a l : 3)  Figure 4.6: After mapping Subject to P o i n t , the automapper determines candidates for mapping the attach(Observer) role method based on a structural and lexical analysis of methods of the P o i n t class.  Observer Display  h©  .  ! B%  update(Subject): void  |  © Display.update(..): void  :  1  S ; ^ Subject .  • :; •••© FigureElement Line  h©  Print  0 l=A  . '  attach(Obseryer): void FigureElement.addObserver(.;): void  ; ! ; © : Point,addObserver(.:): void | :  L ;  © Line.addObserver(..):void  :-• t< d r i t n d X C c s e r v o - ; void I • . ! & FigureElement.removeObserver(::): void ! ;© Point.removeObserver(!.): void. .!'  1  © Line.removeObserver(..)::void notify(): void  :  j  | & FigureElement.notifyObservers(..): void .  .. |...  a Point.notifyObservers(..): void  I  & Line. notifyObservers(..): void  :  .  . B~-"A observers o Point.observers • » : Line, observers  Figure 4.7: The completed mappings for the O B S E R V E R C C C instance in the figure package example.  Chapter 4. Tool Support for Role-Based Refactoring  •  58  { 9 \ A proposed change will deists a method that is advised by an existing aspect. Affected program element: Point.addChangeObserver(ChangeObserver) Do you wish to proceed with the CCC refactoring?  Yes  No  Figure 4.8: A n impact analysis detects that an existing aspect is advising a changing program element.  Figure 4.8. The developer can choose to abort the refactoring or proceed with its execution. In this particular case, we decide to proceed and ignore the impact on the behavior of the system.  4.4.3  Executing the Changes  The refactoring creates the aspect capturing the O B S E R V E R concern from a library aspect (see [38]) and performs the required changes to the original concern implementation. If the developer wishes to review the changes, Eclipse's undo support can be utilized to review changes for each individual affected compilation unit.  4.4.4  Remarks  The purpose of our proof-of-concept tool is to show the feasibility of semi-automated support for C C C refactorings. User studies will be needed to identify how to structure the dialogues between tool and developer more efficiently. Some of these interactions have alternative realizations. As an example, an earlier version of our tool mapped program elements identified by the impact analysis automatically instead of involving the developer explicitly. We found that performing the mappings per hand according to the automapping suggestions helps the developer to understand the targeted concern implementation, but future versions of the tool may offer support for either or both automapping realizations. Similarly, future versions can conceivably offer more options for the developer when dealing with the results of an impact analysis. Instead of just aborting or proceeding with the refactoring, the tool could offer the option to browse the affected code, or to mark it for later review.  Chapter 4. Tool Support for Role-Based Refactoring  4.5  59  Tool Calibration  To derive a set of useful refactoring primitives, we developed seven principal C C C refactorings for 11 of the design pattern CCCs identified in Chapter 2: • Chain of Responsibility • Composite • Mediator • Memento • Observer • Singleton • Template Method, Abstract Factory, Factory Method, Builder, Bridge  11  The design patterns were chosen based on an estimation of the frequency of their usage in real-world software (Observer, Composite, Singleton, Abstract Factory, Factory Method, Template Method) and on the quality of their aspect-oriented implementations (Chain of Responsibility, Composite, Mediator, Memento, Observer, Singleton) according to [38]. Note that some patterns fall into both categories. The similarity of the refactoring processes also led to the inclusion of Builder and Bridge. The tool properly performed the C C C refactorings for all 11 C C C refactoring examples we investigated (one for each design pattern refactoring implemented; the systems are from our previous work [38]) and the automapping feature successfully identified correct candidate mappings given a seed mapping in all cases. Chapter 5 includes an analysis of how the calibrated tool performed during the refactoring of design pattern CCCs in a non-trivial software system. 12  4.6  Extending the Framework  Our tool provides a framework for defining and executing role-based refactorings. To calibrate and evaluate the approach, we created a library of C C C refactorings, most of which are design pattern refactorings. If developers need to create additional refactoring descriptions within this framework, they need to provide the following information: 1. Concern description: this is a description of the concern structure consisting of role elements and role relations in X M L format similar to Listing 4.2. Optionally, this structural information can be augmented by lexical information as discussed in Section 4.2. "These design pattern C C C s required virtually the same refactoring instructions. While their A O implementations naturally differ, the same general ideas for the transformation of the concern structures apply for all of them [38]. 12  According  sign  Patterns  to  personal  Discussion  communication mailing  list  at  with the  John  Vlissides  University  http://lists.cs.uiuc.edu/mailman/listinfo/patterns-discussion  of  and Illinois  a  survey  on  the  De-  at Urbana-Champaign:  Chapter 4. Tool Support for Role-Based Refactoring  1 2 3 4 5 6 7 g 9 10 n 12 13 14 15  60  < C o n c e r n D e s c r i p t i o n name="Logging CCC"> <RoleType> <TypeName>Logger</TypeName> <RoleMethod> < M e t h o d N a m e > l o g E n t r y M e t h o d </MethodName> </RoleMethod> <RoleMethod> < M e t h o d N a m e > l o g E x i t M e t h o d </MethodName> </RoleMethod> </RoleType> <RoleField> <FieldName>logger </FieldName> <FieldType>Logger</FieldType> </RoleField> </ConcernDescription>  Figure 4.9: Concern structure description of a Logging C C C . 2. Refactoring instructions: this involves creating a new subclass of our framework's extension point CCCRef a c t o r ing. This abstract class provides default implementations for C C C refactorings, such as facilities for accessing concrete program elements that a particular role element is mapped to. Developers need to overwrite its createChange ( . . ) method. Within that method, library refactoring primitives are called. 3. New elementary refactorings: if the C C C refactoring requires program transformation steps not captured by existing elementary refactorings, the developer can create these by extending Eclipse's abstract class R e f a c t o r i n g . As a concrete example, consider adding a refactoring for a simple logging C C C , which is described in detail in Section 5.3.1. First, we define the C C C structure, which consists of a Logger role type with two methods logEntryMethod(..) and logExitMethod(..) that are called by clients. Clients have a role field of type Logger. The concern definition is shown in Figure 4.9. Optional lexical information could define "log" as a likely name fragment for all role elements and additionally "before" and "start" for logEntryMethod(..) and "after" and "end" for logExitMethod(..). The next step is to define the refactoring instructions. This involves subclassing CCCRef a c t o r i n g and defining the refactoring instructions in terms of refactoring primitives referring to role elements. In this particular case, we need the following refactoring primitives: 1. Create Aspect (to capture the modularized implementation) 2. Create Pointcut PI (based on call sites of logEntryMethod(..)) 3. Create Pointcut P2 (based on call sites of logExitMethod(..)) 4. Create Advice (stating that before P I , logEntryMethod() is called) 5. Create Advice (stating that after P2, logExitMethodQ is called) 6. Remove Method Calls (removing calls to methods to which logEntryMethodQ is mapped)  Chapter 4. Tool Support for Role-Based Refactoring  i  public  3 4 5 6 7  //  C h a n g e c r e a t e C h a n g e (..)  throws  CoreException ,  ...  61  {  create empty aspect with two masked PCs IType a s p e c t = A s p e c t F a c t o r y . c r e a t e { "MyLoggingAspect" , g e t T y p e ( " L o g g e r " ) . g e t P a c k a g e F r a g m e n t () , new S t r i n g ! ] { " m e t h o d E n t r y O " , " m e t h o d E x i t ( ) " } ) ;  // PC  placeholder  8  addChange(CreatePointcutRefactoring .create ( findCallsToMethods(getMethods("logEntryMethod")) getPC(aspect, "methodEntry"), new I T y p e [] {}, new S t r i n g [] {}, null , null));  9 10 11 12 13 14 is  ,  16  addChange ( C r e a t e P o i n t c u t R e f a c t o r i n g . c r e a t e ( findCallsToMethods(getMethods("logExitMethod")) , getPC(aspect, "methodExit"), new I T y p e [] {} , new S t r i n g [ ] { }, null , null));  n is 19 20 21  22 23 24  25 26 27 28  addChange ( C r e a t e A d v i c e R e f a c t o r i n g . c r e a t e ( a s p e c t , "before", getPC(aspect, "methodEntry"), getMethodCallStatements(getMethods("logEntryMethod")) ,  .  true));  29  addChange(CreateAdviceRefactoring . create (aspect, "after", getPC(aspect, "methodExit"), g e t M e t h o d C a l l S t a t e m e n t s ( g e t M e t h o d s ( " l o g E x i t M e t h o d " ) ) , true ));  30 31 32 33 34  addChange ( R e m o v e M e t h o d C a l l s R e f a c t o r i n g . c r e a t e ( g e t M e t h o d s (" l o g E n t r y M e t h o d " ) ) ) ;  35 36 37  addChange ( R e m o v e M e t h o d C a l l s Refactoring . c r e a t e ( getMethods("logExitMethod")));  38 39 40  return  4i 42  change;  }  Figure 4.10: Refactoring instructions for the Logging C C C .  7. Remove Method Calls (removing calls to methods to which logExitMethod() is mapped) 8. Remove Member (removing the fields to which logger is mapped) The resulting C C C refactoring instructions are shown in Figure 4.10. No new elementary refactorings were needed. The creation of this particular refactoring took less than 30 minutes. Chapter 5 includes a study providing additional examples of extending our framework with new C C C refactorings.  Chapter 4. Tool Support for Role-Based Refactoring  62  4.7 Summary In this chapter we presented a proof-of-concept implementation of our role-based approach in the form of a refactoring tool for the Eclipse IDE. The tool supports the semi-automation of C C C refactorings. In the following chapter, we will evaluate the approach and tool by applying the tool to refactor C C C instances in a non-trivial software system, and by extending the refactoring framework to capture additional, non-design-pattern C C C refactorings.  63  Chapter 5  Evaluation This chapter describes two case studies we performed to evaluate our refactoring approach. The studies show that the role-based concern model enables the semi-automation of the refactoring of non-modularized crosscutting concerns. In the first study, we apply our approach and tool to transform CCCs in an existing, non-trivial software system. This study was designed to show that role-based refactoring descriptions may be applied in systems built separately from the C C C descriptions. For the second study we created and applied refactoring descriptions for a number of additional CCCs, showing that our approach can be used to describe and execute refactorings of non-design-pattern concerns.  5.1  Methodology  In both studies, we used our approach and tool to refactor CCCs and tested the transformed systems. The tests focused on two criteria: the resulting code had to compile and we tested the code to see if the intent of the target concern was preserved even if the precise behaviour was not preserved. For the first study, the latter involved extensive tests of the affected code. The original intent was derived from the available documentation. In the second study, all investigated systems contained executable tests of the essential C C C functionality that served as a basis for evaluating the preservation of intent. In addition to testing the behavior of the resulting system, we also investigated a number of statistics on the transformation to aid in the discussion of the approach. We studied the completeness of the automapping results and investigated the quality of the resulting code. All refactorings were performed on a Pentium3-700 with 1GB R A M running Eclipse release 3.0.2 under Windows 2000. The tool was used within an Eclipse run-time workbench. Code statistics were collected using the Eclipse Metrics plugin [93] version 1.3.5.  5.2  Study 1: Design Pattern Implementations in JHotDraw  Our first study addresses the questions of whether the approach and tool can be applied to a non-trivial system, and whether a library of C C C descriptions can be applied to a  Chapter 5. Evaluation  64  system that we did not design ourselves. We used JHotDraw [92] release 5.3 as the target system for this study. JHotDraw is a graphical editing framework that encompasses over 15,000 lines of non-commented, non-empty lines of source code in 243 types. The system makes aggressive use of design patterns, predominantly GoF patterns [28]. Originally conceived as a design exercise, it has since then become an open-source framework that is utilized in a wide variety of software projects. This study also allowed us to investigate the impact of concern variance; since design patterns represent only outlines for implementation, actual instances can vary considerably. Because our role-based approach relies on a structural description of the target C C C , such variant implementations can affect its applicability. JHotDraw was not designed around a single pattern as are the design pattern examples used to calibrate our tool, but rather contains a number of tangled pattern instances. As the usage of design patterns is well-documented in source code comments, we identified individual design pattern instances using textual searches over the sources for parts of the GoF pattern names. Once an instance was located, we had to manually explore the code base to determine the exact pattern extent (i.e., all involved code fragments), pattern variance (deviations from the pattern definition as represented in the GoF book [28]), and dependencies of the pattern code elements on the rest of the system. This exploration was essential for determining the correctness both of the mappings suggested by the refactoring tool's automapping feature and the actual code transformations.  5.2.1  Results  We successfully refactored a total of 7 instances of 4 different GoF design patterns in JHotDraw. OBSERVER  Two instances of the O B S E R V E R pattern were refactored in the JHotDraw sources. A third could not be transformed due to structural deviations of the pattern instance from the expected concern structure, as discussed in Sections 5.4 and 6.2.1. The structure for the O B S E R V E R C C C refactoring is shown in Figure 3.2. O B S E R V E R Instance 1: DrawingView — FigureSelectionListener This pattern instance monitors the set of selected figure elements. Changes to this set occur by selecting additional figures or removing a figure from the selection, and trigger the update mechanism. This O B S E R V E R instance deviates subtly from the GoF pattern description and consequently from the concern structure we expected. Unlike in the GoF pattern, the Subject DrawingView does not define an equivalent of notifyO, but leaves that to its implementing types. Only a few subtypes of the Observer F i g u r e S e l e c t i o n L i s t e n e r explicitly implement an update(Subject), most inherit this implementation from a supertype. These deviations did not influence the mapping or refactoring of the concern.  Chapter 5. Evaluation  65  Table 5.1: Role mappings for the DrawingView — FigureSelectionListener instance of the O B S E R V E R pattern  Role Element Subject  Observer  attach(Observer)  detach(Observer)  notifyO update(Subject)  observers  Mapped Program Element DrawingView NullDrawingView StandardDrawingView FigureSelectionListener AbstractCommand + 18 subtypes of Abstract Command DrawingEditor + 12 subtypes of DrawingEditor DrawingView.addFigureSelectionListener(..) NullDrawingView.addFigureSelectionListener(..) StandardDrawingView.addFigureSelectionListener(..) Drawing View.removeFigureSelectionListener(..) NullDrawingView.removeFigureSelectionListener(..) StandardDrawingView.removeFigureSelectionListener(..) StandardDrawingView.fireSelectionChangedO FigureSelectionListener.figureSelectionChanged(..) AbstractCommand.figureSelectionChanged(..) UndoableCommand.figureSelectionChanged(..) DrawingEditor.figureSelectionChanged(..) DrawApplet.figureSelectionChanged(..) DrawApplication.figureSelectionChanged(..) JavaDrawViewer.figureSelectionChanged(..) StandardDrawingView.fSelectionListeners  We derived almost the entire mapping from role elements to program elements using our tool's automapping facilities, based on an initial mapping of DrawingView to Subject and F i g u r e S e l e c t i o n L i s t e n e r to Observer. The automapper suggested the subtypes of these two types for appropriate mappings to their respective roles. The mappings to the role methods attach(Observer), detach(Observer), and update(Subject) were identified based on their signatures, and attach(Observer) and detach{Observer) were properly differentiated based on a lexical analysis (see Section 3.4). notifyO could be mapped based on its "calls" (update(Subject)) relation. The only role-element not mapped by the automapper was the observers field, since the automapper does currently not handle aggregate types. The final mappings are shown in Table 5.1. Note that most types acting as O B S E R V E R inherit the pattern-related methods and field. Therefore, they do not need to change . Strictly speaking, for that same reason they do not even need to be mapped. 13  T h e y can, however, be indirectly affected by the refactoring, for example when calls to the original notifyO methods are updated in the course of the refactoring. 13  Chapter 5. Evaluation  66  Despite the structural differences from the GoF pattern description and the considerable extent of the affected code elements (see Table 5.1) the refactoring was applied without any change to the concern description. The transformation preserved both intent and behavior of the original implementation. OBSERVER Instance 2: Drawing — DrawingChangeListener In this instance, the O B S E R V E R pattern is used to decouple Drawing from its views and to enable multiple views, which implement the DrawingChangeListener interface. The structure of this instance of the pattern deviates noticeably from the GoF pattern description. In this case, the parameter for the updute( Subject) methods is not of type Subject, but a specialized event object. The pattern instance further features multiple (two) notifyQlupdateQ pairs. This represents a particular variant realization of the push model [28] of the O B S E R V E R pattern. While these discrepancies prevent applying our refactoring description to this instance of the pattern as is, we decided to investigate how much effort is involved in making this implementation work with our C C C refactoring. In this case, we required an enabling refactoring that reduced the number of notifyi)lupdate() pairs to one. This enabling refactoring was contained to two types and comprised creating a method update (Drawing) in DrawingChangeListener, and attaching a dispatch logic to one of the two original update methods via an inter-type declaration. Further, an appropriate method n o t i f y ! ) in StandardDrawing was created. The original two notifyO methods were removed and their call sites adjusted to call the new n o t i f y () instead. 14  15  Passing an argument of type Drawing to the new update(Subject) method had the additional benefit that the pattern instance now matched that part of the expected concern structure exactly. Based on an initial mapping of Drawing to Subject and DrawingChangeListener to Observer, the automapper correctly mapped attach(Observer), detach(Observer) and update(Subject) based on their signature and then notify() based on the call relationship. Again, the mapping of the observers field had to be done by hand as in the previous case. The final mappings are shown in Table 5.2. Program elements with a star (*) are the result of the enabling refactoring. After the mappings were complete, the C C C refactoring could be applied without affecting the behavior or intent of the original implementation. SINGLETON  The S I N G L E T O N design pattern has a very simple structure, which is shown in Figure 5.1. We identified two instances of the Singleton pattern in JHotDraw. S I N G L E T O N Instance 1: Clipboard The C l i p b o a r d class represents a global clipboard implementation and can be used to store and retrieve application-specific A n enabling refactoring is an O O or A O refactoring intended to transform a system so that it matches the structure a CCC refactoring expects. 1 4  15  T h i s type provides default implementations for all subtypes of D r a w i n g .  Chapter 5. Evaluation  67  Table 5.2: Role mappings for the Drawing — DrawingChangeListener instance of the O B S E R V E R pattern  Role Element Subject  Observer  attach(Observer) attach(Observer) notifyO update(Subject) observers  Mapped Program Element Drawing StandardDrawing BouncingDrawing DrawingChangeListener DrawingView StandardDrawingView NullDrawingView Drawing.addDrawingChangeListener(..) StandardDrawing.addDrawingChangeListener(..) Drawing.removeDrawingChangeListener(..) StandardDrawing.removeDrawingChangeListener(..) StandardDrawing.notifyO* DrawingChangeListener.update(Drawing) * StandardDrawing.fListeners  Singleton  4  C C  o O  • ([static] uniquelnstance/ ,' returns  •  [static] instance()  Figure 5.1: Concern structure of the SINGLETON C C C  Chapter 5. Evaluation  68  Table 5.3: Role mappings for the Clipboard instance of the SINGLETON pattern Role Element Singleton instance() uniquelnstance  Mapped Program Element Clipboard Clipboard.getClipboardO Clipboard.fgClipboard  Table 5.4: Role mappings for the Iconkit instance of the SINGLETON pattern Role Element Singleton instance() uniquelnstance  Mapped Program Element Iconkit Iconkit.instanceO Iconkit.fglconkit  content. It represents a straightforward instance of the SINGLETON pattern, with a private constructor and public class method g e t C l i p b o a r d () that provides access to the Singleton instance. The automapper could suggest proper mappings for all role elements given a single starting mapping — regardless which initial mapping the developer provides. Based on the "contains" relation, the role type can be mapped given either the field or the method mapping. Starting with the type mapping, mappings for both role field and method can be properly identified based on its type and signature, respectively. The final mappings are shown in Table 5.3. The refactoring preserved both behavior and intent of the original implementation. Instance 2: Iconkit From the JavaDoc comments of the I c o n k i t class: "The Iconki t class supports the sharing of images. It maintains a map of image names and their corresponding images". Interestingly, I c o n k i t is not a proper Singleton according to GoF. Aside from in-code comments, there is no indication that this class' constructor is not to be accessed, and the customary constructor protection (usually using a p r i v a t e modifier) is missing. It does, however, have a static instance() method and uniquelnstance field. The role mapping was straightforward as in the previous example. From any starting mapping, the other two mappings were properly identified. The complete mappings can be found in Table 5.4. Unlike in the C l i p b o a r d case, the constructor for I c o n k i t is parameterized. Since instance() methods generally do not have parameters, our SINGLETON C C C refactoring provides default parameters when replacing of calls to instanceQ with constructor calls. For example, n u l l is passed for any Obj ect or array parameter. Since the aspect-oriented implementation of the pattern circumvents subsequent executions of the constructor after the very first one, this preserves the original behavior of the implementation. Aesthetic issues like this can be addressed by a post-refactoring code SINGLETON  Chapter 5. Evaluation  69  TargetType V3  g 'S3 c  concernField  •j concernMethod()  Figure 5.2: Concern structure of the E X T R A C T C O N C E R N I M P L E M E T A T I O N C C C ,  applied to an instance of the C O M P O S I T E pattern  review if desired. COMPOSITE  Although the C O M P O S I T E pattern is among the more popular GoF patterns (see Section 4.5), has a desirable AOP implementation, and could be refactored for the design pattern examples case, the JHotDraw instance of the pattern is not suitable for our C O M P O S I T E C C C refactoring as is. Instead, we modularized this pattern instance using a different C C C refactoring. C O M P O S I T E Instance 1: CompositeFigure The C o m p o s i t e F i g u r e class is a relatively complex type (258 L O C , 4 7 methods) that provides a variety of default implementations for composite graphical elements. This instance of the C O M P O S I T E pattern deviates considerably from the GoF structure. Most importantly, the concern is, unlike what the GoF pattern suggests, modularized within a single type. The C O M P O S I T E concern is tangled with three other concerns: administration of ordering information for children figures (Z values), basic update functionality for F i g u r e C h a n g e L i s t eners, and facilities for the implementation of quad trees for figures (used to optimize rendering). To alleviate the problem of tangling present in C o m p o s i t e F i g u r e a refactoring is applied that moves members (fields and methods) pertaining to the composition concern (or, alternatively, the other three) to an aspect using inter-type declarations. This is accomplished by the refactoring primitive move object member to aspect. We create a simple C C C structure, consisting of a role type, a role method and a role field, as shown in Figure 5.2. The transformation requires only three calls to the refactoring primitives: one to create the aspect, one to move the methods, and one to move the fields. Our structure-based automapping approach is not designed to suggest mappings based on semantic information and could therefore not differentiate between members that belong to the concern and those that do not. The final mapping is shown in Table 5.5.  The refactoring was executed successfully, effectively extracting the tangled implementation of this C O M P O S I T E instance into an aspect. The creation of this C C C  Chapter 5. Evaluation  70  Table 5.5: Role mappings for the CompositeFigure instance of the COMPOSITE pattern Role Element TargetType concernMethod()  concernField  Mapped Program Element CompositeFigure CompositeFigure.add(..) CompositeFigure.remove(..) CompositeFigure.replace(..) CompositeFigure.draw(..) + 26 other methods on CompositeFigure CompositeFigure.fFigures  ConcreteClass  AbstractClass C  's c o o  • <T requiredField f> •  tempi ateMethod()  Figure 5.3: Concern structure of the  TEMPLATE METHOD  CCC  refactoring took less than 20 minutes. TEMPLATE  METHOD  Both documented instances of the T E M P L A T E M E T H O D pattern in JHotDraw were investigated. The concern structure for this refactoring is shown in Figure 5.3.  Instance 1: AbstractFigure The abstract class A b s t r a c t F i g u r e provides default implementations for the F i g u r e interface and contains a number of template methods. Although the pattern instance adheres to the (simple) GoF pattern structure, the automapper was not helpful in determining the mappings for the refactoring. Currently our concern description does not include information about role methods indicating whether they are a b s t r a c t or not. This makes it impossible for the automapper to suggest the proper methods. An extension of the role-based concern model to include this information would be helpful. On the other hand, based on any mapping for templateMethodf), the correct role type AbstractClass can be trivially deduced. The complete mapping for this refactoring is shown in Table 5.6. TEMPLATE METHOD  The transformation was not straightforward, due to limitations of AspectJ. Since ' AspectJ does not allow the inter-type declaration of constructors or static inter-type declarations on interfaces, the transformation of members with these properties can  Chapter 5. Evaluation  71  Table 5.6: Role mappings for the AbstractFigure instance of the T E M P L A T E M E T H O D pattern Role Element AbstractClass ConcreteClass  templateMethod()  requiredField  Mapped Program Element AbstractFigure CompositeFigure DecoratorFigure AttributeFigure PolyLineFigure AbstractFigure.moveBy(..) AbstractFigure.displayBox(..) AbstractFigure.figures(..) AbstractFigure.size(..) + 28 other non-abstract methods on AbstractFigure AbstractFigure.fListener AbstractFigure.serialVersionUID AbstractFigure.abstractFigureSerializedDataVersion AbstractFigure.int_nZ  not be directly realized. To accommodate for this, we had to perform a minor enabling refactoring and remove the (unused and empty) constructor. Further limitations of inter-type declarations in AspectJ affect protected and private members. The tool handles these cases by automatically adjusting the accessibility modifier of affected types to package protected. Since this can affect the intent of the original implementation, the impact analysis notifies the developer of these changes. In this particular case, three private fields and the protected moveBy ( . . ) method (and its implementation in 11 subtypes) were affected by this change in accessibility. Overall the refactoring affected 32 methods and 4 fields on the A b s t r a c t F i g u r e class and its 4 immediate subtypes. T E M P L A T E M E T H O D Instance 2: AbstractLineDecoration The abstract class A b s t r a c t L i n e D e c o r a t i o n provides a standard implementation decorating lines. The automapping process was limited in the same way as in the previous case, and we performed all mappings by hand. The final mappings are shown in Table 5.7.  We encountered similar issues with accessibility modifiers as mentioned above, with four private fields and one protected method requiring accessibility adjustments during the refactoring.  5.2.2  Other Patterns in JHotDraw  We did not transform all design pattern instances in JHotDraw. Because some pattern implementations vary considerably in structure from their GoF pattern definitions, an application of the C C C refactoring was not possible. In other cases, pattern implemen-  Chapter 5. Evaluation  72  Table 5.7: Role mappings for the AbstractLineDecoration instance of the T E M P L A T E M E T H O D pattern  Role Element AbstractClass  Mapped Program Element AbstractLineDecoration  ConcreteClass templateMethod()  ArrowTip AbstractLineDecoration.draw(..) AbstractLineDecoration.getBorderColor(..) AbstractLineDecoration.setBorderColor(..) AbstractLineDecoration.getFillColor(..) AbstractLineDecoration.sefFillColor(..) AbstractLineDecoration.read(..) AbstractLineDecoration.write(..) AbstractLineDecoration.fFillColor AbstractLineDecoration.fBorderColor; AbstractLineDecoration.serialVersionUID;  requiredField  tations were already sufficiently modularized, rendering a C C C refactoring superfluous.  Decorator The DECORATOR pattern C C C refactoring is not applicable to the instance found in JHotDraw because of a limitation of the aspect-oriented solution. The A O P solution is static with respect to assigning Decorators to Components, while in this particular instance the dynamic composition of decorators is essential.  Prototype The P R O T O T Y P E pattern instance in JHotDraw is a specialized form of the GoF pattern. Since it does not create exact copies, our A O P solution and consequently the C C C refactoring is not applicable.  State and Command We did not refactor the S T A T E and C O M M A N D pattern instances since we have to date not developed appropriate C C C refactorings. The challenge in specifying such refactorings lies in the fact that the non-modularized pattern structure and the A O P solution are structurally so different that it is hard to describe the transformation in terms of the elements of the original concern (role elements). It is likely that a more detailed concern model would have been helpful, as the transformation granularity for this refactoring is not types and members, but blocks and statements. Such a refinement of our model is future work.  Chapter 5. Evaluation  contains  Logger  ; <unspecified typo !  — • logEntryMethodO  —•  73  logger  logExitMethod()  Figure 5.4: Concern structure of the LOGGING C C C  5.3  Study 2: Other Crosscutting Concerns  In this study, we address the applicability of the approach to the refactoring of other non-modularized CCCs, in particular non-design-pattern C C C implementations. We decided to start with an investigation of what appeared to be the most popular example C C C for AOP: logging. Additionally, we investigated a number of examples taken from Laddad's aspect-oriented refactorings suggestions [49, 51] as representative examples of C C C refactorings. For each investigated C C C we developed a sample system featuring that concern. These systems were relatively small, consisting of 46 classes and less than 300 lines of code each. As for the first study, the investigated refactorings create code that compiles correctly and preserves the behavior of the target CCC.  5.3.1 Logging We picked LOGGING as a canonical example that is mentioned throughout the AOP literature (e.g., see repeated discussions in [88]). Since there is no single generally accepted way for logging to be realized, we used a simplified analogon of the structure offered by Java's j a v a . u t i 1. l o g g i n g . L o g g e r class. The concern structure features a role type Logger that provides two methods for logging events at the entry and exit of methods. This is reflected in the role methods logEntryMethod and logExitMethod. The concern structure is shown in Figure 5.4. The refactoring consists of the following steps: 1. An aspect is created to store the logging code 2. An e x e c u t i o n pointcut m e t h o d E n t r y is created to capture all call sites to methods to which logEntryMethodO is mapped. 3. A e x e c u t i o n pointcut m e t h o d E x i t is created to capture all call sites to methods to which logExitMethod() is mapped. 4. b e f o r e advice is created based on the m e t h o d E n t r y pointcut. Its body consists of the bodies of the methods to which logEntryMethodO is mapped as suggestions . 16  Code suggestions are mentioned in Section 4.1.  16  Chapter 5. Evaluation  74  5. a f t e r advice is created based on the m e t h o d E x i t pointcut. Its body consists of the bodies of the methods to which logExitMethod() is mapped as suggestions. 6. Calls to all methods to which logEntryMethod() is mapped are removed. 7. Calls to all methods to which logExitMethodQ is mapped are removed. 8. All methods to which logEntryMethodf) is mapped are removed. 9. All methods to which logExitMethodQ is mapped are removed. The refactoring was described entirely in terms of existing refactoring primitives, and was applied successfully to the example system. Since the concern description lacks structure, the automapping facility suggests partial mappings for the investigated sample system based on a seed mapping: given a mapping for one of the two role methods, the type mapping could be (trivially) derived. Describing this C C C refactoring was straightforward and took about one hour. We reused the four refactoring primitives create pointcut, create advice, textitremove member, and remove method calls and did not devlop any new primitives for this example.  5.3.2  Laddad's AOP Refactoring Examples  Laddad presents a number of OO-to-AO refactorings of crosscutting concerns in [49]. With the exception of the WORMHOLE refactoring, the complexity of these examples is lower than for most of the design pattern refactorings. This means that the concern structures are generally smaller (fewer role elements) and less complex (fewer role relations). The different nature of the concerns in question required the development of two new refactoring primitives and extensions to three existing primitives. Four primitives, such as the move member to aspect primitive, could be reused without changes.  Extract Interface Implementation This refactoring is used when multiple types implementing an interface provide the same basic implementation for one or more of its methods, causing scattered and duplicated code. In the refactoring, such duplicate implementations are removed from types and replaced with inter-type declarations that attach default implementations directly to the interface. Note that this refactoring has an aspect-oriented solution and is not related to the object-oriented extract interface refactoring [28]. The concern structure consists of the role types Interface and Implementation, the role method implementedMethodQ and the role field requiredField, as shown in Figure 5.5. The C C C refactoring proceeds as follows: 1. An aspect is created to store the inter-type declarations code 2. All methods to which implementedMethod() is mapped are replaced with appropriate inter-type declarations on the type to which Interface is mapped.  Chapter 5. Evaluation  Implementation  75  Interface  requiredField  implementedMethodQ  Figure 5.5: Concern structure of the E X T R A C T I N T E R F A C E I M P L E M E N T A T I O N C C C  3. All fields to which requiredField is mapped are replaced with appropriate intertype declarations on the type to which Interface is mapped. This C C C refactoring relies heavily on the move object member to aspect refactoring primitive. We had to adjust the primitive to prevent duplication of inter-type declarations: since the crosscutting in this C C C is comprised of identical implementations of the same interface method, a duplication-unaware refactoring would introduce the extracted code fragments multiple times. This customization was not required before as the type from which a member was removed and the type which the inter-type declaration targets were always the same. In this case, however, the target of the inter-type declaration (the interface) is different. Extending the refactoring primitive consisted of adding an appropriate check. No new refactoring primitives were required for this example. The automapping facilities proved to be of little help due to the generic concern description and the resulting minimal concern structure. Extract Method Calls This refactoring targets implementations where calls to the same single method are scattered in multiple methods in a class. This can occur in security permission checks, class-level logging, or persistence session management, for example. If it is desired to modularize these calls, the solution, similar to the L O G G I N G example, is to advise the caller methods in the class to make the method call. Figure 5.6 illustrates the schematics of this transformation, while Figure 5.7 shows the concern structure. The role-based realization is similar to that of the L O G G I N G concern above. The developer has to decide whether the resulting advice are b e f o r e or a f t e r advice. It is conceivable that a further refinement of the utilized replace method calls with pointcut and advice refactoring primitive could automatically identify the position of the original call statement within their enclosing methods and generate the appropriate advice type, but this is left for future work. The refactoring consists of the following steps: 1. An aspect is created to store the aspect-oriented equivalent of the original method calls. 2. An e x e c u t i o n pointcut m e t h o d C a l l is created to capture all call sites for all methods to which calledMethodQ is mapped.  Chapter 5. Evaluation  Extract method calls.  Refactoringaspect Figure 5.6: The Extract Method Calls Refactoring as shown in [51].  «unspecified type» on  d d  a o a  •4—>  calledMethodQ  Figure 5.7: Concern structure of the E X T R A C T M E T H O D C A L L S C C C  76  Chapter 5. Evaluation  77  3. An advice is created based on the m e t h o d C a l l pointcut. Its body consists of a call to the method to which calledMethod() is mapped as a suggestion. The type of advice (e.g., a f t e r or b e f o r e ) is decided by the developer during the planning phase. 4. Calls to all methods to which methodCallQ is mapped are removed. 5. All methods to which methodCall() is mapped are removed. Note that this refactoring can not preserve the behavior of the original program in a few special cases. For example, if a call to the extracted method occurs within a loop, or if calls occur neither at the beginning or the end of their enclosing method. Note that this is a limitation of the proposed aspect-oriented solution, not our role-based refactoring approach. All these cases can be resolved through appropriate enabling refactorings that expose the affected method calls. We have not yet developed specialized impact analyses to automatically identify these specific problems, but expect their implementation to be straightforward. Automapping is not needed for this case as the concern structure consists of a single role element calledMethodQ, for which we expect only a single mapping. We could have reused the C C C refactoring from the L O G G I N G example that allows a developer to determine the nature of the advice through a mapping to either of the two role methods, but chose to implement a different case for illustrative purposes, where the developer is prompted for a decision during the planning phase. We did not require any new refactoring primitives for this example and were able to reuse create pointcut, create advice, and remove method calls. Replace Argument Trickle by Wormhole Among the investigated non-pattern CCCs, the W O R M H O L E refactoring was clearly the most complex. Its refactoring addresses the problem of argument trickling, that is the passing of arguments through a call stack. Argument trickle can be observed in the implementation of prefetching in operating systems code [16], for example. Other examples include transaction management (where the current transaction is the trickling argument) and authorization (where authorization data is passed). The concept of argument trickle is shown schematically in Figure 5.8. In this concern, a caller() method starts a call chain (consisting of various methods symbolified by the trickle() role method) that eventually reaches callee(). An argument is passed from callerf) to callee(), but is not used by any of the trickle() methods. The proposed solution is to remove the offending argument and provide the required context through a c f low () construct as shown in [49]. The concern structure for our refactoring is shown in Figure 5.9. It consists of the role type Argument and the role methods callerf), trickle() (capturing methods along the trickle chain), and calleeQ. Note that the "unspecified type" notation means that multiple trickle() methods do not have to be methods on the same type, and neither does the callee() method. The following steps describe the refactoring:  Chapter 5. Evaluation  78  Figure 5.8: Argument trickle between caller() and callee(), taken from [51]. A n argument gets passed through the call stack but is only used within the callee() method.  «unspecified  type»  Argument  hasArgument  trickle()  callerQ hasArgument  calleeQ  Figure 5.9: Concern structure of the REPLACE ARGUMENT TRICKLE WITH WORMHOLE C C C  Chapter 5. Evaluation  79  1. A n aspect is created to store the extracted call context 2. The type to which Argument is mapped is removed as a parameter from methods to which caller() is mapped. 3. The argument of the type to which Argument is mapped is removed from all methods to which trickle() is mapped. 4. Calls to methods to which calleeQ is mapped from within any method to which trickle() is mapped are removed (since the callee() will be called by the aspect). 5. A pointcut r e q u e s t is created to capture the context of caller(). 6. A pointcut o p e r a t i o n is created to capture all call sites to the method to which callee() is mapped. 7. A pointcut wormhole is created as a combination of o p e r a t i o n and a c f low of r e q u e s t . 8. A n a f t e r r e t u r n i n g advice is created based on wormhole that calls the method to which callee() is mapped after o p e r a t i o n , supplying the context from r e q u e s t . This transformation reused the remove method calls refactoring and required the addition of a pair of new refactoring primitives to address the task of removing a method argument. Remove method argument affects the method declaration, and remove call argument its call sites. The existing primitive for the creation of pointcuts was extended to support the creation of c f low pointcuts, which were not needed before, and to allow for pointcut definitions that joined other pointcuts (step 7 above). The auto-mapping facilities proved to be of limited help, since it does not take into account that methods in the trickle chain can be on different types. This is a limitation of the current implementation, not of the algorithm itself. As the most complex of the non-pattern C C C refactorings, this one took approximately 5 hours to code and test, including the extensions of the set of existing refactoring primitives.  5.4 Summary The JHotDraw study indicates that the role-based approach supports the semi-automatic refactoring of crosscutting concerns in non-trivial software, and for refactoring descriptions that were developed independently from the target software system. The second study shows that the approach can express non-design-pattern CCCs and support their refactorings. We expected problems, especially in the JHotDraw study, since earlier, informal studies have shown that the investigated design pattern refactorings are complex and error-prone to execute by hand. The actual application of the role-based refactorings turned out to be successful, despite the far-reaching changes involved. On the other  Chapter 5. Evaluation  80  hand, the cases that we did not refactor illustrate the importance of concern structure: if a concrete implementation deviates too much from the expected structure, it becomes necessary to employ enabling refactorings or define alternative refactoring descriptions. This is illustrated by the three O B S E R V E R instances, which show varying degrees of adherence to the GoF design pattern structure. Two instances were successfully refactored, while the third (Figure — FigureChangeListener) is structurally so different from our C C C description that applying the refactoring was not possible. Structural deviations of the concern instance from the expected C C C structure appear to be the primary limitation of our approach. This is discussed in more detail in Chapter 6. Similar limitations can be observed if the original concern and the AO solution are too different, and the refactoring can not be expressed in terms of the role elements of the original concern. This was the case for the S T R A T E G Y and C O M M A N D pattern CCCs. It is likely that role-based refactoring descriptions exist for such cases, but they are not obvious. The non-design-pattern refactorings from the second study could utilize the existing refactoring primitives to a large extent, except for the W O R M H O L E refactoring, which required three changes to the existing primitives. This is not surprising as this is the first C C C for which the solution involved changing method parameters or creating c f low pointcuts. Overall it appears that a library of proven refactoring primitives is conceivable. We expect that, with the study of more C C C refactorings, such a library will converge to a comprehensive set of refactoring primitives. A number of refactorings show similar underlying principles. The T E M P L A T E M E T H O D , L O G G I N G , E X T R A C T C O N C E R N IMPLEMENTATION, E X T R A C T INTERF A C E I M P L E M E N T A T I O N , and E X T R A C T M E T H O D C A L L S all focus on moving a set  of members to an aspect by replacing them with inter-type declarations. This appears to be a common theme in OO-to-AO refactorings. Based on the number of program elements identified by the automapping facilities as part of the concern implementation, it is apparent that automapping was overall more useful for the design pattern CCCs, mostly because those offered more structural information to leverage. The non-pattern concerns, on the other hand, generally required considerably fewer mappings. Role elements often mapped to only one or a small number of program elements. This is not only a result of the smaller scale of the example systems that we targeted in the second study, but for most of these patterns, multiple mappings are not expected. The exception is again the W O R M H O L E case, for which we can expect multiple mappings for the trickleQ role method.  81  Chapter 6  Discussion The previous chapters have shown that our role-based appoach enables the semiautomated refactoring of non-modularized crosscutting concerns into aspects. In this chapter we discuss the benefits and limitations of our approach and associated tool implementation.  6.1  Benefits  Our approach abstracts the complexity associated with refactoring CCCs. Refactorings of crosscutting concerns are composite refactorings that consist of multiple refactoring steps, and target multiple program elements. Our approach allows these refactorings to be planned and executed as a single operation to the developer. This has a number of associated benefits. The role-based approach to describing refactorings aids the execution of a planned refactoring as the developer does not have to conceptualize the system in intermediate refactoring steps, during which the refactoring is only partially finished, reducing the conceptual complexity of dealing with C C C refactorings. It also becomes possible for the developer to undo and reapply a changed/adjusted C C C refactoring without having to go through the various transformations steps by hand. Part of a refactoring description is a definition of the target concern structure in terms of the role abstractions. Our JHotDraw study showed that a comparison of this structure and the structure of the target program aids developers in identifying program elements pertaining to the implementation of the C C C , and thus helps to avoid incomplete refactorings. The approach allows the description of C C C refactorings to be defined separately from a concrete instance, enabling a single refactoring description to apply to multiple instances of the target concern over more than one system.  6.2 Limitations This section outlines the limitations of our approach and tool. For the latter, we distinguish between limitations based on the supporting technologies (AspectJ, AJDT, and the Eclipse platform) and our current implementation.  Chapter 6. Discussion  82  6.2.1 Approach The main limitation of the approach is the dependence on a specified concern structure. The complexity of C C C refactorings also impacts the feasibility of behavior preservation.  Importance of Concern Structure The concern structure, which we define in terms of roles, is integral not only to defining the refactorings, but also helps in mapping role elements to program elements. Potentially problematic are cases where a concrete concern varies structurally from an abstract concern description, and cases where the C C C in question has very little structure to utilize. The abstract description of a C C C is intended to capture the structural essence of several different ways to implement the C C C . However, depending on the C C C , a particular implementation may vary so much from the defined structure that a refactoring is not possible using the role-based refactoring description. It is an open question how flexible the description of an abstract C C C should be to capture the different variants. The JHotDraw variants of the OBSERVER pattern are sufficiently diverse to illustrate some of the range of implementation variants that need to be considered. For example, these instances exhibit these five divergences from the pattern as documented in [28]. 1. Subjects accept only a single Observer. 2. The notify() role implementation appears only in concrete Subjects but not on the Subject interface. 3. Multiple pairs of notifyO and update() methods exist within the same pattern instance. 4. The observers role field implementation is used outside of the pattern context. 5. Non-observer content is stored in the concrete observers role field. Our refactoring description addressed variants 1, 2, and 4. Both variants 3 and 5 can be addressed by appropriate enabling refactorings. It seems reasonable to expect the abstract C C C description to be flexible enough to capture at least variants one and two. Thefifthvariant, on the other hand, has so little in common with the original pattern, that a separate C C C description is necessary to capture it. In the third variant, the Observers provide multiple update(Subject) methods for the same set of Subjects, which is a special case of the push model ([28], pp. 298). Although the structure of the pattern is similar to the C C C pattern description, the associated refactoring instructions do not cover this case, as it is difficult to capture the associations between a varying number of notify()-update() pairs. Since the structure is similar, the refactoring description should be extended to cover this variant. This could be realized by extending the way C C C structures are described to include a tag  Chapter 6. Discussion  83  identifying sets of role elements that need to be treated separately, but in the same principal way. This would require extending the automapping support to differentiate between such different sets, and updating the refactoring instructions. In the fourth variant, references to the observers field from outside the pattern context can be detected by a static analysis; before the field is considered for deletion , dealing with references to it would constitute decision points and a dialogue with the developer would be initiated. In general, cases like this can either be addressed by enabling refactorings (placing the burden on the developer applying the approach), a more expressive role-based refactoring model (placing the burden on the developer creating the refactoring), or by a more intelligent refactoring tool. Ideally, we would like to keep refactoring descriptions simple so that they remain easy to understand. Hence, if enabling refactorings are not an option, it seems better to address as much of the variant implementation within the refactoring engine as possible. Certain common themes in C C C variants are covered this way. For example, not all concrete program elements mapped to a role type like Subject need to provide a declaration or definition of members associated with that role type, such as the notifyO method. This particular case was mentioned above as variant 2. Other variants have to be addressed by enabling refactorings or by explicitly providing multiple C C C descriptions (for example, variant 5 above). It is conceivable that our tool can be extended to provide enabling refactorings in the planning phase that are not committed until the C C C refactoring is committed, and that can be undone as part of undoing the C C C refactoring. This would allow C C C refactoring descriptions to target a wider set of variant concern instances. 17  The existence of multiple C C C refactoring descriptions for variants of the same C C C raises the question of how a developer picks the proper description to match an implementation. We expect such a selection can be aided by the refactoring tool through a comparison of automapping results, which detects deviations of the expected concern structure and the structure of the actual implementation. More experience with a broader base of CCCs as they occur in different kinds of systems is needed to better extrapolate commonalities with respect to implementation alternatives. Concern structure is also relevant for tool support for mapping role elements to program elements. Since our approach for automapping is based on a structural comparison of the concern and the program, it works better when more structural information (number of role elements and role relations) for a concern exists. If a concern has little structure, automapping is less useful, but then the automapping support is also needed less. Consider the LOGGING concern: the concern itself has little structure, and even though the calls to the logging facilities can be spread throughout the system, the only mapping required is one type and one or two methods. All call sites to the method(s) that need to be updated are identified automatically as part of the refactoring. Although the investigated non-design-pattern refactorings were performed on sample systems and not real-world software, they do show that the role-based refactoring approach is not limited to design pattern applications. Unfortunately, Laddad's refac1 7  T h e refactoring renders the observers field obsolete, as the newly created aspect takes over the respon-  sibility of maintaining a mapping between Subjects and their  Observers.  Chapter 6. Discussion  84  toring examples [49] represent the only at least partially formalized non-pattern C C C refactorings available. A larger set of CCC/AOP-solution pairs would help to extrapolate our findings further. Based on our experiences with the design pattern refactorings, we expect our non-pattern C C C refactorings to be applicable to larger software systems as well, but verification of this conjecture is left for future work.  Preservation of Behavior vs. Preservation of Intent As mentioned in Section 1.1.2, some transformations may result in minor behavior variations to the code base, which we consider to be acceptable if the original intent of the concern is preserved. An intent-preserving refactoring preserves the overall requirements of the system, but may change the semantics of the program locally. Impact analysis points out potnetial behavior variations before refactoring instructions are executed, and developers can usually avoid behavior implications by adjusting or relaxing the original C C C implementation before executing the refactoring instructions . There is a tradeoff: these n o n - C C C refactorings require knowledge of the problem and additional effort, while otherwise the behavior of the system might vary slightly. A further investigation of cases that do not preserve behavior is left for future work. 18  A related problem is represented by complex transformation steps pertaining to a C C C refactoring that can not be automated and require developer interaction or postrefactoring review. For example, in the C H A I N O F R E S P O N S I B I L I T Y pattern, concrete instances of the role method handlef Request) contain code that does two things: deciding whether to handle a request (or to pass it along in the chain), and actually handling it. In the aspect-oriented version of the pattern, this is broken down into two meth-  ods: acceptRequest (Request) and handleRequest (Request). Since it is difficult to automatically determine how to split the original method, the current realization only creates the appropriate method bodies, and leaves the original code as a (commented out) suggestion in each of them.  6.2.2  Supporting Technology  Three supporting technologies were utilized in the implementation of our refactoring tool: The program models of the Eclipse IDE, the AOP language AspectJ, and AJDT, a realization of support for AspectJ in the Eclipse environment. AspectJ The AspectJ language imposes limitations on certain refactoring primitives. For example, a number of the refactorings involve (among other refactoring steps) replacing members that pertain to the implementation of the target C C C with inter-type declarations, effectively moving their code into an aspect. Since AspectJ does not support the inter-type declaration of protected members, targeting a protected member leaves the developer with three options: either to use package protection for the new IDT, which 18  Since such enabling refactorings occur before the application of the C C C refactoring, impact analyses  will take these changes into account.  Chapter 6. Discussion  85  requires the aspect to be in same package as all subtypes of the type in question (this might not be possible), to change the access modifier to public, which offers even less protection for the member, or to employ an enabling refactoring to adjust the visibility of the member. A similar problem arises when private members are replaced with inter-type declarations: a private member is not equivalent to a private inter-type declaration; the former is only visible within the type, while the latter is only visible within the aspect. This situation can also be resolved through enabling refactorings. This can occur, for example, in the T E M P L A T E M E T H O D and E X T R A C T I N T E R F A C E  IMPLEMENTA-  T I O N refactorings, where concrete members are replaced with inter-type declarations. Generally, these particular transformations are semantics-preserving, but since they can expose program elements by changing their accessibility, the developer needs to consider the implications on the system. Since a tool can not decide whether such a change preserves the intent of the C C C , these refactorings can only be semi-automated and require developer interaction. In addition to these limitations, AspectJ does also not allow the inter-type declaration of static members and constructors, which can matter in the case of the T E M P L A T E M E T H O D refactoring where an abstract class is replaced with an interface and appropriate inter-type declarations.  AJDT When manipulating a crosscutting Java program in the AJDT/Eclipse environment, a number of internal representations of the program must be consolidated. Eclipse provides abstract syntax trees of programs (the JDT Core AST) and a Java model on top of that (the IJavaModel, also known as the JDT model). These representations do not contain any information about crosscutting structure (i.e., AspectJ program constructs). AJDT has its own A S T (an AspectJ AST) that is the basis for AJDT's structure model ASM. The latter is roughly equivalent to the IJavaModel, but contains crosscutting information. The relationship between the representations is shown in Figure 6.1. The fact that AJDT provides neither an open API for accessing or changing its AspectJ A S T made it unsuitable for our purposes (although an extension of Eclipse's AST manipulation support is planned). The A S M , while containing crosscutting information, does not provide the entire information of the JDT/IJavaModel (for example, it does not contain information about a method's parameter types), which rendered it unsuitable for our purposes as well. It is also more complex to retrieve information from it than from the IJavaModel . 19  This impacts our current implementation and limits its applicability to pure Java systems. An extension of our tool to create and maintain its own A S T representation using information from both the IJavaModel and the AJDT A S T is conceivable as future work. Currently, aspect-oriented constructs are not part of the utilized program representation (the JDT/IJavaModel), unless they are "masked" as outlined in Section 4.1.5. The masking and unmasking of aspect-oriented constructs requires an additional pre- and post-processing step of the involved sources. 1 9  "[The  IJavaModel]  is better and  Committer. Personal communication.  easier  to use [than the ASM]".  - M i k Kersten, AspectJ and  AJDT  86  Chapter 6. Discussion  !  I  i  Extended AJDT Java Model ;  IJavaModel  ASM AspectJ AST  JDT Core AST  AJDT Weaver  Figure 6.1: The programming models of Fxlipse and AJDT and their relationships (schematic)  We do show that consolidation of the different models is possible to some extent by implementing an impact analysis that checks if the proposed changes affect existing pointcuts. Recently, AJDT incorporated an extension of the IJavaModel that maps between the IJavaModel and the A S M . Although this extension does not yet provide an API, this is planned for a future version of AJDT. With such a facility, it will be possible to combine the benefits of the IJavaModel with the crosscutting information of the A S M , at which point it will be desirable to adjust our tool to make use of this facility. This is future work. The Eclipse Program Models The Eclipse APIs for both refactoring and AST manipulation were not public for large parts of the initial development of the refactoring tool. The APIs also changed considerably from build to build so that we were forced to abandon the idea of tying into these facilities. Instead, we ended up implementing all program transformations as text manipulations of the source code of the system in question. As in our current implementation no AST representation of the refactored system exists until the entire refactoring is completed, the feasibility of statically checking the proposed program transformations is limited. This could be addressed by an extension of our tool that maintains its own AST representation.  6.2.3  Tool  Using text manipulations of the program code instead of AST manipulations has a number of drawbacks related to inference between textual edits, as outlined in Section 4.1.3. Another issue to consider is the impact of the implementation of C C C refactorings as string manipulations on the performance of the refactoring tool. Much of the refactoring time is spent on pattern matching and string manipulation. It seems likely that an implementation utilizing AST manipulation would achieve better performance.  Chapter 6. Discussion  87  Program Analyses The program analyses provided by our tool as part of the mapping algorithm and the various impact analyses are not and were not intended to be comprehensive, and leave considerable room for improvement. Research efforts in the area of program analysis for refactorings (e.g., [3, 7, 23, 27, 47, 58, 68, 81]) can potentially be utilized in future versions of our tool.  Auto-Mapping It is conceivable that the mapping algorithm could be extended with refactoring-specific program analyses to avoid suggesting invalid mappings. For example, for the Extract Interface Implementation, type constraints could be used to restrict the mappings of the implementedMethod() role method so that all mapped methods have the same signature. In our current implementation, this check is instead performed before the refactoring is applied (i.e., in the planning phase). A future version of our refactoring framework could move parts of the impact analyses into the mapping phase to avoid illegal mappings in the first place. This appears feasible as the refactoring is always chosen before the mapping is performed.  Impact Analyses We see several ways to extend the current set of impact analyses. Since C C C refactorings (and a number of the refactorings primitives we employ) are composite refactorings, we believe that Kniesel's and Koch's work on the static composition of refactorings [47] could aid in determining the constraints of these refactorings, allowing us to compute their overall pre-conditions. Since both C C C refactorings and refactorings primitives are defined independently from specific programs and available in libraries (i.e., reusable), this computation would be required only once per composite refactoring, and would affect all subsequent applications of the refactoring. Expected benefits include the optimized verification of pre-conditions due to the removal of redundant or unnecessay checks. When members are moved up in the inheritance hierarchies (for example, in the Extract Interface Implementation C C C refactoring), variable declarations may need to be adjusted. This specific problem of refactoring for generalization is addressed for the object-oriented case by the work of Tip et. al. [81]. If these declarations are not updated, they might be too overspecific, which leads to conflicts with object-oriented design principles. Although it is not clear how well this approach works in an aspectoriented context (consider, for example, how d e c l a r e p a r e n t s statements might affect the type constraints [68] used), it appears to be a useful technique for automatically identifying and executing generalization refactorings as part of C C C refactorings. To ensure the safety of the transformation of fields, as in the Change Field Type refactoring primitive, we could utilize an aspect-oriented extension of the refactoring support for class library migration presented by Balaban et. al. [3]. Currently, such an analysis is not required as the primitive is only used within a single C C C refactoring {Memento) and the replacement is straight-forward. However, for future extensions of the refactoring framework, a safer and more general implementation is desirable.  Chapter 6. Discussion  88  A possible way to help automatically decide whether the intent of a concern implementation might be compromised in the course of a (planned) refactoring is based on the differentiation between various kinds of behavior preservation as suggested by Mens et. al. [58]. It is conceivable that by classifying different kinds of behavior preservation according to their impact on the rest of the system, a tool could estimate which refactorings are behavior-preserving (safe), which might produce "acceptable" behavior deviations (requiring developer feedback), and which might violate the intent of the implementation (unsafe). C C C Refactorings The currently supported set of C C C refactorings aim to generate aspect-oriented implementations, wich are mainly based on our previous work [38]. These implementations have been shown to have design tradeoffs [29], and certainly leave room for improvements. It is likely, for example, that future versions of the AOP design pattern implementations will utilize generic types (introduced in Java 1.5, and supported by AspectJ 5). For a transformation of our AOP implementation, an aspect-oriented version of refactoring-to-generics approaches [23, 27] based on type constraints could be utilized. Our investigated C C C refactorings, on the other hand, do not utilize such transformations, and do not require such analyses.  6.3  Future Work  Our results suggest several directions for further experimentation, including investigating other crosscutting concerns and their potential for role-based refactoring to aspects, extending the refactoring model to complex refactorings in general, and utilizing the role-based concern model to provide concern-specific views of software.  6.3.1  Refactorings for other Crosscutting Concerns  One avenue for future research is to apply the role-based refactoring approach to a wider range of crosscutting concerns. Unfortunately, aspect-oriented programming is still a rather new idea and investigations of crosscutting concerns and their AOP equivalents in a fashion detailed enough to provide a basis for a C C C refactoring description are rare. The design pattern study [38] was a good start as it showed how a set of common CCCs can be modularized in AOP, thereby providing suitable problem/solution pairs as a basis for C C C refactorings. Informal refactoring descriptions, such as those by Laddad [49] are an important next step, but more research in the area of crosscutting concerns is needed. Another option is to vary the implementation language. Although the role-based refactoring approach is inherently language independent (except for refactoring instructions, which are generally tied to an implementation language), it remains to be shown how well the approach works for other aspect-oriented languages. However, the lack of current reference implementations for common crosscutting concerns is even more pronounced for AOP languages other than AspectJ.  Chapter 6. Discussion  89  The role-based refactoring approach is useful whenever sets of program elements have to be modified in the same systematic way. A possible avenue of research is to investigate how applicable this concept is to large-scale refactorings [26] in general.  6.3.2  Improvements of the Refactoring Tool  Our tool's realizations of the individual steps of the refactoring workflow can be improved, as outlined below.  Suggesting Refactorings Currently our approach requires the developer to choose an appropriate C C C refactoring by hand. It is conceivable that the tool could be extended to integrate an aspectmining approach, e.g., [11, 21, 56, 74, 82, 84], so that non-modularized CCCs can be identified and appropriate refactorings can be suggested. The refactoring tool's library of C C C refactorings could form the basis of a directed mining approach, suggesting the CCCs for which to mine. For the specific case of design pattern refactorings we expect that pattern mining approaches, e.g., [2, 4] cannot only be utilized to identify the program elements comprising a non-modularized design pattern concern, but to also automatically suggest mappings from appropriate role elements.  Describing and Executing Refactorings Refactorings are described as elemental AOP refactoring steps, referring to the role elements identified in the C C C description. Currently, they consist of calls to a library of refactoring primitives we have implemented. The declarative nature of these descriptions suggests that a language could be developed for them. This would allow us to perform some basic consistency checks during parsing, such as identifying role elements of a concern description that are not referenced in the refactoring instructions.  Mapping Roles Our current model for the auto-completion of mappings between roles and concrete program elements uses both structural and lexical information. This approach has made the mapping step tractable for the examples we have investigated. However, we may be able to improve this process by using semantic information about the internals of role elements, in particular role methods. For example, we know that within the scope of the attach(Observer) method in the OBSERVER pattern, the argument object has to be added to some sort of data structure. In other words, a candidate method whose scope contains calls to an a d d ( . . ), p u t ( . . ), or i n s e r t ( . . ) method of an aggregate data structure is a more likely candidate than one whose scope does not. This additional information could be used to further refine the ranking of candidate methods and to suggest likely matches to the developer. As an alternative to our comparison of concern and program structure, we considered using a subgraph-matching approach as utilized in [6], but this did not provide us  Chapter 6. Discussion  90  with feedback on the level of single program elements, making it difficult to combine it with other analyses and utilizing the lexical information available. Our tool already implements a lexical analysis to differntiate between candidate program elements that have similar structural properties. Instrumental to this process is the specification of name fragments and their "weights", as described in Section 4.2. We expect that it is possible to extend the tool to "learn" good weights from the mappings of refactorings it performs. For each role element of a C C C refactoring, the tool could keep track of the names of mapped program elements and use this set of names to generate common name fragments.  6.3.3  Automatic Generation of Refactoring Instructions  We have discussed the benefits of an explicit concern structure earlier in this chapter. Ideally, we would like to extend the approach so that a similar structural description exists for the refactored code. Being able to compare the two concern structures would ease reasoning about the refactoring process and reduce its conceptual complexity, as well as serve as a documentation artifact for complex changes to a software system. It is conceivable that by describing not only the concern structure (as we currently do), but also the structure of the final, refactored concern, an explicit definition of refactoring instructions may be unnecessary: we believe that based on the structural differences of these descriptions, a tool could infer some or all of the refactoring instructions necessary to perform the transformation. Alternatively, the refactoring could be reduced to just the resulting concern structure, requiring only a mapping of (non-modularized) program elements to their associated role elements in the resulting (modularized) concern structure. A tool would generate the refactoring instructions based on the structure of the resulting concern and the provided mapping. We expect this to work best for small concerns, since without a structural description of the non-modularized concern, automated mapping support is difficult, and incomplete mappings are harder to detect.  6.3.4  Exploratory Generation of Role-Based Refactorings  Currently, developers must explicitly create (or reuse) a role-based concern description and associated refactoring instructions. One goal is to make complex refactorings easier to formulate and execute. We envision a lightweight implementation of our refactoring approach which allows developers to build up a description of their refactoring targets (as sets of role elements) in an exploratory fashion. That is, while exploring the code, developers can define role elements and mappings to concrete program elements they investigate. Role relations and further mappings are suggested based on the structural relationship of the mapped program elements, or are explicitly defined by the developer. We expect this to be helpful for defining any kind of principled, far-reaching refactoring, not just in an aspect-oriented context. One possible set of refactorings to investigate is Fowler's "big" refactorings [26]. The advantages we expect from creating a role-based concern model are the same as for role-based refactoring in general: the concern structure can help identify over-  Chapter 6. Discussion  91  looked program elements that need to be changed, and the description of refactoring instructions in terms of roles makes the whole refactoring more planable.  6.3.5  Extensions of the Role-Based Concern Model  The close relationship between roles and crosscutting behavior suggests than incorporating the roles as a language concept can aid reasoning about crosscutting concerns.  Using Join Points to Specify Mappings Currently, automapping support fails in a few select cases where the provided concern structure is insufficient to identify matching program elements. For these cases it is an open question how to effectively map roles to the concrete program elements that correspond to them. We propose to investigate this overlap and develop a clear join point model that is usable for specifying where roles apply. Such an approach would make it possible to avoid mapping program elements through code exploration where each element has to be explicitly selected. Instead, we believe that developers would be aided with facilities that translate their partial knowledge of the system into a mapping suggestion. For example, if a developer is trying to identify an instance of the OBSERVER pattern in a system, but only knows that the Observers are in a subpackage of the n e t w o r k i n g package and their name contains "Listener", he could use n e t w o r k i n g . * . * L i s t e n e r * to identify matching elements. We expect that using standard AspectJ techniques for specifying pointcuts, which generally consist of regular expressions over named program elements, will not prove to be sufficient, as this approach fails when trying to specify that two sets of program elements matched by regular expressions are the same. This limitation is addressed by alternative frameworks for expressing join points, such as LogicAJs generic aspect model [48]. With LogicAJ-like pointcuts it would, for example, be possible to capture instances of the S I N G L E T O N pattern by specifying that classes are sought that have a static method returning an object of that class, e.g., s t a t i c ?class ?class.*(..).  92  Chapter 7  Related Work This chapter describes work related to the role-based refactoring approach described in this dissertation, and highlights the novel aspects of our work. We discuss other work on refactoring, alternative models for crosscutting concerns, the relationship between roles and aspects, and other alternative aspect-oriented implementations of design patterns.  7.1 Refactoring Griswold and Opdyke officially introduced the term refactoring virtually at the same time [32, 67]. Their work provides the theoretical basis for automated refactorings realized in many refactoring tools, most notably the Smalltalk [30], Refactoring Browser [71,95]. Contemporary IDEs, such as Eclipse [91], typically offer some forms of refactoring support. Fowler popularized refactoring by providing a catalogue of refactorings [26]. Most refactoring research has targeted low-level program transformations in functional and object-oriented systems, with recent efforts concentrating on object-oriented software. The refactoring approach described in this dissertation focuses on refactorings of crosscutting concerns, which are composite refactorings consisting of multiple aspect-oriented refactoring steps.  7.1.1  Composite Refactorings  The concept of composite refactorings, i.e., refactorings that consist of multiple individual refactoring steps, was first introduced by Opdyke [67]. Fowler later used the term "big refactorings" to indicate the complexity of the changes involved [26]. An example of object-oriented composite refactorings is introduced by Kerievski's concept of "refactoring to patterns", which describe a series of refactorings that replace implementations with design pattern equivalents [44]. These transformations are similar to our C C C refactorings in that they target multiple, usually scattered and tangled, program elements, although the descriptions are informal and not tied to a concern model. Composite refactorings introduce the possibility of interference between steps of the composite refactoring. Bardey investigated this problem and presented a dependency analysis approach to modelling multiple refactoring steps [7]. This is similar to the impact analysis we discuss in Chapter 3, but focuses on object-oriented code only and requires a detailed description not only of a refactoring's preconditions, but also of  Chapter 7. Related Work  93  its effect on the system. An interesting property of his approach is the ability to reorder the individual refactoring steps to avoid potential conflicts. Kniesel and Koch provide a similar form of analysis for composite refactorings based on backwards transformation descriptions [47]. Their generic formal model for the automatic composition of conditional program transformations is programindependent (i.e., the combined preconditions for a composite program transformation can be calculated independently of the program to which they might be applied). Interestingly, this approach applies to arbitrary conditional program transformations (even non-behavior-preserving ones). In that sense their approach appears to be a natural fit for analyzing the compositions of the elementary refactorings, such as C C C refactorings. The benefit of adopting this approach for the description of C C C refactorings is obvious: the series of individual refactoring steps can be analyzed in advance and it is likely that redundant (and potentially costly) preconditions checks can be avoided (this is referred to as an "optimizing" effect). Although the examples they provide are on a much smaller scale than typical design pattern C C C refactorings, it would appear that the approach applies regardless of refactoring complexity.  7.1.2  Analyses for Ensuring the Behavior-Preservation of Object-Oriented Refactorings  Mens et. al. formalize behavior preserving program transformations as basic graph rewriting operations and statically analyze the dependencies between these operations at a semantic and syntactic level [58]. Their approach is language-independent, but a verification of whether it is possible to express refactorings affecting specific language features (e.g., Java features such as interfaces, inner classes, threads and exceptions) is not provided. Well-formedness constraints (i.e., constraints that guarantee a graph corresponds to a syntactically correct program) are essential to tie their graph notation to a particular programming language, like Java. These constraints are expressed using two mechanisms: type graphs (meta graphs expressing restrictions on program graphs) and forbidden subgraphs (subgraphs expressing illegal program configurations). The examples discussed are of considerably smaller scale than a typical design pattern C C C refactoring, and it thus remains to be seen if the approach scales to complex composite refactorings. Especially interesting about this approach is the differentiation between various kinds of behavior preservation. Mens et. al. discuss three kinds relevant to the investigated refactorings: access preservation, update preservation, and call preservation. It is conceivable that by classifying these and other kinds of behavior preservation according to their impact on the rest of the system, a tool could estimate which refactorings are behavior-preserving, which might produce "acceptable" behavior deviations, and which might violate the intent of the implementation. Tip et. al. present an approach for the detection, analysis, and resolution of generalization refactorings [81] based on type constraints [68]. The approach addresses the problem of updating variable declarations in the course of refactorings that move members up the inheritance hierarchy, for example, as part of an object-oriented Extract Interface or Pull Up Member refactoring. Although their approach is designed for use in an object-oriented context and an extension to AOP might introduce new  Chapter 7. Related Work  94  challenges (consider, for example, how d e c l a r e p a r e n t s statements might affect the type constraints used), it could be a useful technique for automatically identifying and executing generalization refactorings as part of C C C refactorings, for example the Extract Interface Implementation refactoring. Donovan et. al. present an approach to support the transformation of Java code to incorporate the generic type (i.e., parametric polymorphism) system of Java 1.5 [23]. The approach is based on a context-sensitive pointer analysis and realized in their fully automated translation tool called Jiggetai. A similar approach is presented by Fuhrer et. al. [27]. Fuhrer's approach provides a more scalable and general alternative to Donovan's work, and has been realized as part of the refactoring functionality of the Eclipse IDE (introduced in Eclipse version 3.1). Both approaches make heavy use of type constraints, and Fuhrer's work further introduces a set of constraint generation rules that help avoid the manual creation of constraints, which is tedious and error-prone. The refactorings presented in these two works could be a useful basis for the transformation of a number of aspect-oriented design pattern implementations, for example the O B S E R V E R pattern, which would benefit from using generic types for storing Observer per Subject. Refactorings to use generic libraries are not part of the currently investigated C C C refactorings, however, so this work is currently not applicable to C C C refactorings themselves. 20  The particular problem of replacing (library) types is addressed by the work of Balaban [3]. A mapping specification between legacy classes and their replacements outlines how the replacement takes places, while type and escape analysis ensures that the required changes are safe. The mapping specification consists of a set of rewrite rules, which are an interesting alternative for a role-based refactoring description for small-scale transformations that focus on single types. We perform a similar, yet much less complex, type transformation in the context of the Memento C C C refactoring, which uses the Change Field Type refactoring primitive. Specific, non-trivial problems, such as the preservation of thread-safety, do not apply in this case and could therefore be ignored. For a more general implementation of that primitive, an aspect-oriented version of the analyses presented in Balaban's work would be useful.  7.1.3 Aspect-Oriented Refactorings Refactorings of crosscutting concerns generally consist of multiple refactoring steps, some of which are aspect-oriented equivalents of traditional object-oriented refactorings, but take into account potential references to the changing program element from AO programming constructs. Adopting existing refactorings to make them aspectaware is the topic of various work, e.g., [34, 42, 86]. With the introduction of AOP, new refactorings are possible that target aspectoriented programming constructs. Collections of such refactorings have been presented by Monteiro et. al. [61, 62] and Iwamoto [42]. Their work confirms some of the lowlevel refactoring primitives we developed, for example their move method from class to inter-type declaration matches our move object member to aspect for methods. 2 0  T h e approach is more general as it allows for the accommodation of user-defined subtypes of generic  library classes.  Chapter 7. Related Work  95  Aspect-oriented refactorings that target crosscutting concerns currently focus primarily on extractions of single program elements into aspects [62, 83]. Recent approaches utilize aspect mining to identify candidate code fragments for extraction to aspects [9, 74]. Mining approaches are either based on textual patterns [84], patterns in execution traces [11], high fan-in methods [56], or duplicated code fragments [12]. A qualitative comparison of aspect mining techniques is provided by Ceccato [15]. Our approach does not rely on aspect mining, but instead helps determine the extent of a crosscutting implementation using an automapping algorithm that compares the structure of the target program and the concern description. It is conceivable that aspectmining techniques can be utilized in a future version of our role-based refactoring tool to automatically suggest refactorings. Besides approaches that provide a formal description of the refactoring step(s), Laddad investigated a number of C C C refactorings and described the required transformation steps informally by providing code examples illustrating the concern implementation before and after the transformation [49]. Although such informal descriptions are helpful for refactorings executed by hand, they do not provide a sufficient basis for realization in a refactoring tool. However, as Section 5.3 illustrates, a set of cases investigated by Laddad could be translated into role-based refactoring descriptions. Recently Binkley et. al. presented a partially implemented, human-guided approach for OO-to-AO refactorings that focuses on the specific problem of extracting OO code fragments into aspects [9]. Their approach relies on code which is partially marked to indicate candidates for the extraction. Although they propose to utilize an automated aspect-mining approach to to provide the marking, this is not yet realized, and their tool requires the developer to mark code segments by hand. Their tool supports an interative approach to aspect extraction consisting of discovery (determines applicable refactorings for the marked code), transformation (applies enabling OO refactorings), selection (lets the developer select appropriate A O P refactorings), and finally refactoring, which transforms the code. The actual code transformations are not implemented in the tool, but the authors assure that they pose no conceptual difficulty. Compared to our approach, Binkely et. al. do not provide a means to support identification of program elements pertaining to the implementation of the target concern, and their tool does not generate aspect code. The transformations are series of low-level A O P refactorings that are restricted to the extraction of code fragments into aspects — complex structural differences between original concern and aspect solution are not addressed. The aforementioned approaches to aspect-oriented refactoring do not employ a concern model. As we have shown in this dissertation, the role-based concern model aids the planning and execution of C C C refactorings and the associated automapping algorithm helps to determine the exact extent of a concern implementation. In previous work we investigated the realization of C C C refactorings based on Robillard's concern graphs model [72]. Our role-based approach proved to be more suitable for the description of refactorings as concern graphs are always tied to an implementation, and do not provide a means to abstract sets of program elements of the same kind based on their function within an aspect, for example to differentiate between methods in an O B S E R V E R implementation acting as attach() and detach().  Chapter 7. Related Work  7.2  96  Concern Modeling  The role-based concern model is the basis of our proposed C C C refactoring approach. Various models for concerns exist, with varying degrees of similarity to our model. For example, textual documentation can be seen as a model of the documented concern, as can program representations, such as aspects. Our model can be considered to be above the program model and not tied to the implementation level. Sutton and Rouvellou present a general-purpose concern-space modeling schema called Cosmos [77] that offers a distinction between logical and physical concerns. Logical concerns capture "matters of interest" and can be considered separately from physical concerns, which represent more tangible properties of a systems, such as its hard- and software. Logical concerns are loosely related to roles, and physical concerns to concrete implementations, although their model is more general in that the logical concerns do not differentiate on a method/field level, and physical concerns comprise other tangible elements of a system besides its implementation, such as its hardware. The model most closely related to our concern model is Robillard's concern graph model [72], in that both are graphs consisting of program nodes that represent program elements. Robillard's concern graphs aim to provide a description of the concern structure that is easy to manage and robust towards changes in the underlying program. Concern graphs are always tied to a concrete implementation, while our concern representations are abstractions of the essential elements of multiple, similar concern implementations. Furthermore, the actual program structure is only indirectly reflected in our concern descriptions: a single role element can correspond to multiple program elements in a concrete implementation, while for concern graphs the mapping is bijective. Lastly, concern graphs do not contain labels for individual nodes (role names are labels for role elements in our approach), so that different elements of the same type can only be differentiated by by their position in the graph and not based on descriptive names. For the specific purpose of modeling design pattern CCCs, Mapelsden et. al. introduce the visual design pattern modeling language DPML, built upon similar concepts as U M L [55]. This multi-level approach (design patterns, pattern instances, and object models) makes it possible to show objects and their roles within the pattern and to generate pattern instances from them. The approach limits the role concept to types and instead models their behavior using constraints on types. A similar approach is presented by Florijn et. al., who suggest a fragment-based representation of design patterns [25]. A fragment depicts a design element such as a class, method or association. Patterns themselves and all elements in a pattern instance (classes, relationships among them, code) are represented as (graphs of) fragments. Neither of these two approaches uses their concern models for describing refactoring tasks but solely the concern structures.  Chapter 7. Related Work  7.3  97  Aspects and Roles  Both aspect-oriented programming and the role modeling concept are techniques that are similar in that they permit a flexible adaptation of object-oriented constructs [35]. Kendall has investigated aspect-oriented designs of role models, in particular alternative realizations for the R O L E O B J E C T pattern and has shown that aspect-oriented mechanisms can represent roles effectively [43]. Lieberherr et. al. introduce the concept of Aspectual Components [53] and Aspectual Collaborations [54] which integrate component-based programming and AOP to support dynamic assignment of object behavior similar to role models. Similarly, Tamai et. al. propose a role model called Epsilon and an associated language EpsilonJ to realize object adaptation to environments [79]. Compared to these works, roles in our approach are not tied to a particular implementation, but the role concept is used in a more abstract fashion to describe the function of sets of program elements within a particular concern. For the context of design pattern roles in particular, Mikkonen presents a formal model of behavioral layers called object slices [59] to model roles and their relationship to the concrete classes playing those roles. Florijn et. al. introduce a fragment model (see above) that represents participant roles as a particular kind of fragments [25]. Both of these approaches are specific to design patterns.  7.4  Aspects and Design Patterns  Design pattern implementations are strongly influenced by the implementation language, causing some patterns to either disappear when they are captured by language constructs, or to have structurally simpler implementations [66, 78]. For example, DemeterJ [90] is an adaptive aspect-oriented extension to Java that provides explicit support for the V I S I T O R design pattern. Multiple authors have proposed and discussed individual aspect-oriented implementations of existing object-oriented design patterns. For example, Noda and Kishi provide an early comparison of their AspectJ and Hyper/J implementations of the O B S E R V E R pattern [63], separating the pattern concern from the application, while Sletten investigated an alternative realization of the C O M M A N D pattern [75]. Nordberg discusses the V I S I T O R , O B S E R V E R , and E X T E N S I O N O B J E C T patterns from the point  of view of how AOP and component-based development can help in software module dependency management [64], and how replacing or augmenting OO indirection with AOP indirection can lead to better structure for some design pattern [65] implementations. The study presented in Chapter 2 represents the first comprehensive investigation of a larger set of design pattern implementations in an aspect-oriented language. Since then, Tanaka and Ichisugi have confirmed that AOP implementation of design patterns can exhibit modularity benefits [94] in their AOP language MixJuice [41]. More recently, Garcia et al. have analyzed our proposed AOP design pattern implementations quantitatively [29] with respect to various code quality metrics, comparing them to their object-oriented equivalents. They confirm most of our findings from [38], but illustrate that separation of concerns, which was the main focus of our study, can be  Chapter 7. Related Work  98  conflicting with other desirable code properties, such as small size or cohesion of modularity units. In general, their study shows that our aspect-oriented implementations do have a set of associated design tradeoffs.  99  Chapter 8  Conclusions Describing and executing refactorings of non-modularized crosscutting concerns (CCCs) into aspects is a complex task. Multiple scattered and tangled program elements need to be considered and changed together. Other than for traditional refactorings, preservation of behavior may not always be possible or even desired. Instead, these refactorings focus on preserving the intent of the original implementation. The thesis of this research is that a role-based concern model enables the semiautomatic refactoring of crosscutting concerns, while preserving their original intent. To investigate this claim, we have developed a role-based refactoring approach and associated tool. In our approach, a crosscutting concern refactoring is described using a concern description and associated refactoring instructions. The concern description abstracts the concern structure by expressing it in terms of role elements and their relationships. Refactoring instructions are formulated in terms of these role elements. Invoking a refactoring involves mapping the role elements to specific concrete program elements. After the mapping has been checked, the refactoring instructions are executed on the mapped program elements. Thus, refactoring descriptions are effectively separated from the systems to which they may be applied. We demonstrated the feasibility of this approach through two case studies. In the first study, we showed how our approach and tool could be applied to refactor nonmodularized crosscutting concerns in a non-trivial system, using refactoring descriptions developed separately from the investigated code base. The second study showed that the role-based refactoring approach can express and help execute a variety of crosscutting concern refactorings. For both studies, the tool we developed provided support for the semi-automation of the investigated refactorings. This research makes four contributions to the field of software engineering. First, we provide a working, language-independent approach for the semi-automated refactoring of crosscutting concerns into aspects. We provide a refactoring tool as a proof-of-concept implementation of the approach, instantiated for the Java and Aspect! languages. The application of this refactoring tool to refactor various CCCs into aspects provides valuable insights into the issues associated with developing tool support for the refactoring of crosscutting concerns. Second, we provide a general model for describing crosscutting concerns and their refactorings in terms of roles. Because the model is abstract, CCCs and their refactorings described using our role-based model are not tied to a particular implementation. In addition, the model makes it possible to conceptualize complex program transformations as a single refactoring, and provides a basis for our approach to semi-automating C C C refactorings.  Chapter 8. Conclusions  100  Third, we provide a library of refactoring primitives and C C C refactoring descriptions. As the case studies have shown, the generality of these descriptions allows C C C refactorings to be applied to software systems for which they were not specifically developed, and the refactoring primitives to be reused in the definition of new C C C refactorings. Finally, we provide a comprehensive study of object-oriented and aspect-oriented implementations of design patterns, a set of commonly used concerns with often crosscutting properties. This study asserts that refactorings of non-modularized crosscutting concerns into aspects can be beneficial. Researchers and developers can download our reference implementations freely to utilize the aspect-oriented implementations we provide. Our implementations have had considerable impact already, being featured in various books and articles on AspectJ, e.g., [31, 50, 52, 60]. In conclusion, role-based refactoring makes it possible to semi-automate the complex process of refactoring crosscutting concerns into aspects. As the library of refactoring primitives and C C C refactorings matures, we can envision the eventual integration of our approach into aspect-oriented integrated development environments.  101  Appendix A  Aspect-Oriented Terminology • Advice - Encapsulates code to be run at join points specified by a particular pointcut. This code can either run before, after, or instead of the code at the join point, by using b e f o r e , a f t e r , and a r o u n d advice, respectively. • Aspect - A unit of modularity for the encapsulation of crosscutting concerns. • Aspect-Oriented Programming - A programming paradigm that provides explicit support for the encapsulation of crosscutting concerns. • AspectJ - An aspect-oriented extension to the Java programming language. • Pointcut - A program element that describes a set of join points. • Concern - A facet of a program that might be of interest to the developer, for example a functional or non-functional requirement. • Crosscutting Concern - A concern with an implementation that can not be modularized in a given decomposition. Non-modularized crosscutting concerns have an implementation that is scattered across multiple modules and tangled with other code. Aspect-oriented programming provides facilities for the modularization of crosscutting concerns. Common examples of crosscutting concerns include persistence, logging, caching, etc. • Declare Parents - An AspectJ construct that allows aspects to add an additional supertype to an existing type. • Inter-Type Declaration - Refers to an AspectJ-specific construct that allows an aspect to declare members on existing types. • Join Points - A point in the execution of a program. Examples of join points include method calls, method executions, and field accesses. • Scattered Code - Concern code that is not localized. • Tangled Code - Concern code that is interwoven with that of other concerns.  102  Appendix B  Refactoring Primitives In our refactoring framework, instructions for refactorings of crosscutting concerns are described as a series of calls to the library of refactoring primitives. Each primitive is an aspect-oriented composite refactoring. In the following, we describe the individual primitives we have developed.  B.l  Aspect Creation  As outlined in Section 4.1.2, primitives for aspect creation are different from other primitives in that they are applied before the rest of the refactoring instructions are executed. The tool provides an aspect factory class that offers three parameterized options for the creation of aspects, which it delegates to the following specialized primitives: • Create Aspect - creates a new stand-alone aspect to hold the modularized implementation of the target C C C . The new aspect is created in a specified package, and assigned the specified accessibility modifiers. • Create Subaspect - as above, but creates an aspect as a subaspect of an existing abstract library aspect. Abstract members of the abstract aspect, including pointcuts, are automatically concretized as stubs. • Create Aspect from Library Aspect - also creates the new aspect from an abstract aspect, but duplicates all of the abstract aspects concrete implementation, resulting in a stand-alone aspect.  B.2  Other Creational Primitives  These primitives create new program elements on aspects. • Create Advice - creates an advice in a given aspect. This primitive is parameterized to allow specification of the advice body and the kind of advice to create (e.g., b e f o r e , a f t e r r e t u r n i n g , etc.). • Create Pointcut - creates a pointcut in a given aspect. This primitive is comprised of several specialized pointcut creation primitives, for example capture  103  Appendix B. Refactoring Primitives  calls in pointcut, which captures all calls to a specified set of methods in a pointcut. Other primitives create compound pointcuts (i.e., pointcuts that are a composition of two or more existing pointcuts), or capture the execution of a set of methods. • Create Inter-Type Declaration - creates an inter-type declaration (ITD) by delegating the actual creation to two more specialized primitives that are responsible for the creation of field ITDs and method ITDs, respectively.  B.3  Transformational Primitives  Refactorings in this category manipulate existing programming constructs. • Move Object Member to Aspect - replaces an object member with an equivalent inter-type declaration. This is realized by specialized primitives forfieldsand methods. A l l primitives in this category rely on the creational primitives for ITDs mentioned above. • Change Abstract Class to Interface - replaces an abstract class with an interface and appropriate inter-type declarations. The primitive relies on the move object member to aspect primitive, which in turn uses the creational primitives for ITDs. • Change Accessibility Modifier - changes the accessibility modifier (public, private, etc.) of a member, for example to prepare them for replacement with an ITD. • Change Field Type - changes the type of a field by adjusting the field definition. This primitive is used within other primitives that ensure that the field is not referenced improperly. • Change Imports - adds or removes elements from the list of imports for a given type. This primitive is utilized by all other primitives that can have an impact on the imports of a type. • Remove Argument - removes an argument from a method. This is a specialized refactoring primitive used within the R E P L A C E A R G U M E N T T R I C K L E W I T H W O R M H O L E refactoring.  • Replace Method - replaces a method with another, existing method and updates the call sites accordingly. Unlike the traditional rename method refactoring, this effectively changes the implementation of the target method. • Replace Object Method with Aspect Method - replaces an instance method with a (static) aspect method. Call sites are updated so that the original target object of calls is passed as an additional parameter, for example  mySubject.attach(myObserver) i — > aspect.instanceOf().addObserver(mySubject,  myObserver).  Appendix B. Refactoring Primitives  B.4  104  Destructive Refactorings  Destructive refactorings remove program elements such as methods, fields and types. They are mainly used to dispose of program elements that are rendered obsolete by other refactorings, especially the "replace..." series of refactoring primitives. • Remove Type - removes a type from the system. • Remove Member - removes a member. This addresses the removal of both methods and fields. • Remove Method Calls - deletes all call sites to a particular method. • Remove Field References - deletes all references to a given field.  105  Bibliography [1] Ellen Agerbo and Aino Cornils. How to preserve the benefits of design patterns. In Proceedings of the 13th Conference on Object-Oriented Programming Systems, Languages, and Applications (OOPSLA '98), pages 134-143. A C M Press, 1998. [2] Giuliano Antoniol, Roberto Fiutem, and Luca Cristoforetti. Using metrics to identify design patterns in object-oriented software. In Proceedings of the 5th International Software Metrics Symposium (METRICS '98), pages 23-34. IEEE Computer Society, 1998. [3] Ittai Balaban, Frank Tip, and Robert Fuhrer. Refactoring support for class library migration. In Proceedings of the 20th Conference on Object-Oriented Programming, Systems, Languages and Applications (OOPSLA '05), pages 265-279. A C M Press, 2005. [4] Zsolt Balanyi and Rudolf Ferenc. Mining design patterns from C++ source code. In Proceedings of the 19th International Conference on Software Maintenance (ICSM '03), pages 305-314. IEEE Computer Society, 2003. [5] Carliss Y. Baldwin and Kim B. Clark. Design Rules: The Power of Modularity Volume 1. MIT Press, 1999. [6] Elisa Baniassad. Design Pattern Rationale Graphs: Linking Design to Source. PhD thesis, University of British Columbia, BC, Canada, 2002. [7] Uwe Bardey. Abhangigkeitsanalyse von Softwaretransformationen. Diploma thesis, Computer Science Dept. Ill, University of Bonn, Germany, Feb 2003. [8] Laszlo A . Belady and Meir M . Lehman. A model of large program development. IBM Systems Journal, 15(3):225-252, 1976. [9] David Binkley, Mariano Ceccato, Mark Harman, Filippo Ricca, and Paolo Tonella. Automated refactoring of object-oriented code into aspects. In Proceedings of the International Conference on Software Maintenance (ICSM '05), pages 27-36. IEEE Computer Society, 2005. [10] Tim Bray, Jean Paoli, and Michael Sperberg-McQueen (Eds). Extensible Markup Language (XML) 1.0 (2nd Edition). W3C Recommendation, 2000. [11] Silvia Breu and Jens Krinke. Aspect mining using event traces. In Proceedings of the 20th International Conference on Automated Software Engineering (ASE '04), pages 310-315. IEEE Computer Society, 2004.  Bibliography  106  [12] Magiel Bruntink, Arie van Deursen, Tom Tourwe, and Remco van Engelen. An evaluation of clone detection techniques for identifying crosscutting concerns. In Proceedings of the 20th International Conference on Software Maintenance (ICSM '04), pages 200-209. IEEE Computer Society, 2004. [13] Timothy Budd. An introduction to object-oriented programming. Addison Wesley, 1991. [14] Frank J. Budinsky, Marilyn A. Finnie, John M . Vlissides, and Patsy S. Yu. Automatic code generation from design patterns. IBM Systems Journal, 35(2): 151171, 1996. [15] Mariano Ceccato, Marius Marin, Kim Mens, Leon Moonen, Paolo Tonella, and Tom Tourwe. A qualitative comparison of three aspect mining techniques. In Proceedings of the 13th International Workshop on Program Comprehension (IWPC '05), pages 13-22. IEEE Computer Society, 2005. [16] Yvonne Coady, Gregor Kiczales, Mike Feeley, and Greg Smolyn. Using AspectC to improve the modularity of path-specific customization in operating system code. In Proceedings of the 8th European Software Engineering Conference held jointly with 9th International Symposium on Foundations of Software Engineering, pages 88-98. A C M Press, 2001. [17] James O. Coplien. Idioms and patterns as architectural literature. IEEE Software, 14(l):36-42, 1997. [18] James O. Coplien. Software design patterns: Common questions and answers. In The Patterns Handbook: Techniques, Strategies, and Applications, pages 311— 320. Addison-Wesley, 1998. [19] OleJ. Dahl. Structured Programming. Academic Press, 1972. [20] Jim des Rivieres and John Wiegand. Eclipse: A platform for integrating development tools. IBM Systems Journal, 43(2):371-383, 2004. [21] Arie van Deursen, Marius Marin, and Leon Moonen. Aspect mining and refactoring. Presented at the International Workshop on REFactoring: Achievements, Challenges, Effects (REFACE'03) at W C R E '03, 2003. [22] Edsger W. Dijkstra. The structure of the "THE"-multiprogramming system. Communications of the ACM, ll(5):341-346, 1968. [23] Alan Donovan, Adam Kiezun, Matthew S. Tschantz, and Michael D. Ernst. Converting java programs to use generic libraries. In Proceedings of the 19th Con' ference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA '04), pages 15-34. A C M Press, 2004. [24] Stephen G. Eick, Joseph L . Steffen, and Jr. Eric E . Sumner. Seesoft-a tool for visualizing line oriented software statistics. IEEE Transactions on Software Engineering, 18(ll):957-968, 1992.  Bibliography  107  [25] Gert Florijn, Marco Meijers, and Pieter van Winsen. Tool support for objectoriented patterns. In Proceedings of the Uth European Conference on ObjectOriented Programming (ECOOP '97), volume 1241 of LNCS, pages 472-495. Springer-Verlag, 1997. [26] Martin Fowler. Refactoring: Improving the Design of Existing code. AddisonWesley, 1999. [27] Robert Fuhrer, Frank Tip, Adam Kiezun, Julian Dolby, and Markus Keller. Efficiently refactoring Java applications to use generic libraries. In Proceedings of the 19th European Conference on Object-Oriented Programming (ECOOP'05), volume 3586 of LNCS, pages 71-96. Springer-Verlag, 2005. [28] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995. [29] Alessandro Garcia, Claudio Sant'Anna, Eduardo Figueiredo, Uira Kulesza, Carlos Lucena, and Arndt von Staa. Modularizing design patterns with aspects: a quantitative study. In Proceedings of the 4th International Conference on AspectOriented Software Development (AOSD '05), pages 3-14. A C M Press, 2005. [30] Adele Goldberg and David Robson. Smalltalk-80: the language and its implementation. Addison-Wesley, 1983. [31] Joseph D. Gradecki, Nicholas Lesiecki, and Joe Gradecki. Mastering AspectJ: Aspect-Oriented Programming in Java. John Wiley & Sons, Inc., 2003. [32] William G. Griswold. Program Restructuring as an Aid to Software Maintenance. PhD thesis, University of Washington, Seattle, WA, USA, 1992. [33] William G. Griswold and David Notkin. Automated assistance for program restructuring. ACM Transactions on Software Engineering Methodology, 2(3):228269, 1993. [34] Stefan Hanenberg, Christian Oberschulte, and Rainer Unland. Refactoring of aspect-oriented software. NetObject Days '03, Erfurt, Germany, 2003. [35] Stefan Hanenberg and Rainer Unland. Roles and aspects: similarities, differences, and synergetic potential. In Proceedings of the 8th International Conference on Object-Oriented Information Systems (OOIS '02), volume 2425 of LNCS, pages 507-520. Springer-Verlag, 2002. [36] Jan Hannemann, Ruzanna Chitchyan, and Awais Rashid. Report on the workshop on analysis of aspect-oriented software. In ECOOP '03 Workshop Reader, volume 3013 of LNCS, pages 154-164. Springer-Verlag, 2004. [37] Jan Hannemann, Thomas Fritz, and Gail C. Murphy. Refactoring to aspects: an interactive approach. In Proceedings of the Workshop on Eclipse Technology exchange (ETX) at OOPSLA '03, pages 74-78. A C M Press, 2003.  Bibliography  108  [38] Jan Hannemann and Gregor Kiczales. Design pattern implementation in Java and AspectJ. In Proceedings of the 17th Conference on Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA '02), pages 161173. A C M Press, 2002. [39] Jan Hannemann, Gail C. Murphy, and Gregor Kiczales. Role-based refactoring of crosscutting concerns. In Proceedings of the 4th International Conference on Aspect-Oriented Software Development (AOSD '05), pages 135-146. A C M Press, 2005. [40] Erik Hilsdale and Jim Hugunin. Advice weaving in AspectJ. In Proceedings of the 3rd International Conference on Aspect-Oriented Software Development (AOSD '04), pages 26-35. A C M Press, 2004. [41] Yuuji Ichisugi and Akira Tanaka. Difference-based modules: A class-independent module mechanism. In Proceedings of the 16th European Conference on ObjectOriented Programming (ECOOP '02), volume 2374 of LNCS, pages 62-88. Springer-Verlag, 2002. [42] Masanori Iwamoto and Jianjun Zhao. Refactoring aspect-oriented programs. Presented at the Workshop on AOSD Modeling With U M L at U M L '03, 2003. [43] Elizabeth A . Kendall. Role model designs and implementations with aspectoriented programming. In Proceedings of the 14th Conference on ObjectOriented Programming, Systems, Languages, and Applications (OOPSLA '99), pages 353-369. A C M Press, 1999. [44] Joshua Kerievsky. Refactoring to Patterns. Addison-Wesley, 2004. [45] Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Kersten, Jeffrey Palm, and William G. Griswold. An overview of AspectJ. In Proceedings of the 15th European Conference on Object-Oriented Programming (ECOOP '01), volume 2072 of LNCS, pages 327-353. Springer-Verlag, 2001. [46] Gregor Kiczales, John Lamping, Anurag Mendhekar, Chris Maeda, Christina Lopes, Jean-Marc Loingtier, and John Irwin. Aspect-oriented programming. In Proceedings of the 11th European Conference on Object-Oriented Programming (ECOOP '97), volume 1241 of LNCS, pages 220-242. Springer-Verlag, 1997. [47] Giinter Kniesel and Helge Koch. Static composition of refactorings. Science of Computer Programming, 52:9-51, 2004. [48] Giinter Kniesel, Tobias Rho, and Stefan Hanenberg. Evolvable pattern implementations need generic aspects. Presented at the Workshop on Reflection, AOP, and Meta-Data for Software Evolution. In ECOOP '04 Workshop Reader, volume 3344 of LNCS, pages 111-126. Springer-Verlag, 2004. [49] Ramnivas Laddad. Aspect-oriented refactoring series. Online document at The Server Side, http://www.theserverside.com/, 2003.  Bibliography  109  [50] Ramnivas Laddad. AspectJ in Action: Practical Aspect-Oriented Programming. Manning Publications, 2003. [51] Ramnivas Laddad. Aspect-oriented refactoring: Taking refactoring to a new level. Tutorial at AOSD '05, http://aosd.net/2005/tutorials/refactoring.php, 2005. [52] Nicholas Lesiecki. Enhance design patterns with AspectJ. Online document at IBM Developer Works, http://www-128.ibm.com/developerworks/java/library/jaopwork5/, 2005. [53] Karl J. Lieberherr, David H. Lorenz, and Mira Mezini. Programming with aspectual components. Technical Report NU-CCS-99-01, College of Computer Science, Northeastern University, Boston, M A , March 1999. [54] Karl J. Lieberherr, David H. Lorenz, and Johan Ovlinger. Aspectual collaborations: Combining modules and aspects. The Computer Journal, 46(5):542-565, 2003. [55] David Mapelsden, John Hosking, and John Grundy. Design pattern modelling and instantiation using DPML. In Proceedings of the 40th International Conference on Tools Pacific (CRPITS '02), pages 3-11. Australian Computer Society, 2002. [56] Marius Marin, Arie van Deursen, and Leon Moonen. Identifying aspects using fan-in analysis. In Proceedings of the 11th Working Conference on Reverse Engineering (WCRE '04), pages 132-141. IEEE Computer Society, 2004. [57] Hidehiko Masuhara and Gregor Kiczales. Modeling crosscutting in aspectoriented mechanisms. In Proceedings of the 17th European Conference on Object-Oriented Programming (ECOOP '03), volume 2743 of LNCS, pages 228. Springer-Verlag, 2003. [58] Tom Mens, Serge Demeyer, and Dirk Janssens. Formalising behaviour preserving program transformations. In Proceedings of the 1st International Conference on Graph Transformation (ICGT '02), volume 2505 of LNCS, pages 286-301. Springer-Verlag, 2002. [59] Tommi Mikkonen. Formalizing design patterns. In Proceedings of the 20th International Conference on Software Engineering (ICSE '98), pages 115-124. IEEE Computer Society, 1998. [60] Russell Miles. AspectJ cookbook. O'Reilly, 2005. [61] Miguel P. Monteiro and Joao M . Fernandes. Object-to-aspect refactorings for feature extraction. Industry Track paper at the 3rd International Conference on Aspect-Oriented Software Development (AOSD '04), 2004. [62] Miguel P. Monteiro and Joao M . Fernandes. Towards a catalog of aspect-oriented refactorings. In Proceedings of the 4rd International Conference on AspectOriented Software Development (AOSD '05), pages 111-122. A C M Press, 2005.  Bibliography  110  [63] Natsuko Noda and Tomoji Kishi. Implementing design patterns using advanced separation of concerns. Presented at the Workshop on Advanced Separation of Concerns in Object-Oriented Systems at OOPSLA '01, 2001. [64] Martin E. Nordberg III. Aspect-oriented dependency inversion. Presented at the Workshop on Advanced Separation of Concerns in Object-Oriented Systems at OOPSLA'01, 2001. [65] Martin E . Nordberg III. Aspect-oriented indirection beyond object-oriented design patterns. Presented at the Workshop "Beyond Design: Patterns (Mis)used" at OOPSLA'01, 2001. [66] Peter Norvig. Design patterns in dynamic programming. Presentation at Object World '96, 1996. [67] William F. Opdyke. Refactoring Object-Oriented Frameworks. PhD thesis, University of Illinois at Urbana-Champaign, IL, USA, 1992. [68] Jens Palsberg and Michael I. Schwartzbach. Object-oriented Type Systems. John Wiley and Sons, 1994. [69] David L. Parnas. On the criteria to be used in decomposing systems into modules. Communications of the ACM, 15(12):1053-1058, 1972. [70] Awais Rashid and Ruzanna Chitchyan. Persistence as an aspect. In Proceedings of the 2nd International Conference on Aspect-Oriented Software Development (AOSD '03), pages 120-129. A C M Press, 2003. [71] Don Roberts, John Brant, and Ralph Johnson. A refactoring tool for Smalltalk. Theory and Practice of Object Systems, 3(4):253-263, 1997. [72] Martin P. Robillard and Gail C. Murphy. Concern graphs: Finding and describing concerns using structural program dependencies. In Proceedings of the 24th International Conference on Software Engineering (ICSE '02), pages 406-416. A C M Press, 2002. [73] James Rumbaugh, Ivar Jacobson, and Grady Booch, editors. The Unified Modeling Language Reference Manual. Addison-Wesley, 1999. [74] David Shepherd and Lori L. Pollock. Ophir: A framework for automatic mining and refactoring of aspects. Technical Report 2004-03, Department of Computer and Information Sciences, University of Delaware, DE, USA, 2003. [75] Brian Sletten. Beyond actions — a semantically rich command pattern for the Java Foundation Casses (JFC/Swing) API. Presentation at JavaOne '02, 2002. [76] Jiri Soukup. Implementing patterns. In Pattern languages of program design, pages 395-412. A C M Press/Addison-Wesley, 1995.  Bibliography  111  [77] Jr. Stanley M . Sutton and Isabelle Rouvellou. Modeling of software concerns in Cosmos. In Proceedings of the 1 st International Conference on Aspect-Oriented Software Development (AOSD '02), pages 127-133. A C M Press, 2002. [78] Gregory T. Sullivan. Advanced programming language features for executable design patterns. Lab Memo AIM-2002-005, MIT Artificial Intelligence Laboratory, 2002. [79] Tetsuo Tamai, Naoyasu Ubayashi, and Ryoichi Ichiyama. An adaptive object model with dynamic role binding. In Proceedings of the 27th International Conference on Software Engineering (ICSE '05), pages 166-175. A C M Press, 2005. [80] Aleksandra Tesanovic, Mehdi Amirijoo, Mikael Bjbrk, and Jorgen Hansson. Empowering configurable QoS management in real-time systems. In Proceedings of the 4th International Conference on Aspect-Oriented Software Development (AOSD '05), pages 39-50. A C M Press, 2005. [81] Frank Tip, Adam Kiezun, and Dirk Baumer. Refactoring for generalization using type constraints. In Proceedings of the 18th International Conference on Object-Oriented Programing, Systems, Languages, and Applications (OOPSLA '03), pages 13-26. A C M Press, 2003. [82] Paolo Tonella and Mariano Ceccato. Aspect mining through the formal concept analysis of execution traces. In Proceedings of the 11th Working Conference on Reverse Engineering (WCRE '04), pages 112-121. IEEE Computer Society, 2004. [83] Paolo Tonella and Mariano Ceccato. Migrating interface implementations to aspects. In Proceedings of the 20th International Conference on Software Maintenance (ICSM '04), pages 220-229. IEEE Computer Society, 2004. [84] Tom Tourwe and Kim Mens. Mining aspectual views using formal concept analysis. In Proceedings of the 4th Workshop on Source Code Analysis and Manipulation (SCAM '04), pages 97-106. IEEE Computer Society, 2004. [85] Niklaus Wirfh. On the composition of well-structured programs. ACM Computing Surveys, 6(4):247-259, 1974. [86] Jan Wloka. Refactoring in the presence of aspects. Presented at the Workshop for PhD Students in Object-Oriented Systems (PhDOOS) at ECOOP '03. In ECOOP '03 Workshop Reader, volume 3013 of LNCS, pages 50-61. SpringerVerlag, 2004. [87] The AspectJ development tools web site, http://www.eclipse.org/ajdt. [88] The AspectJ user mailing list a s p e c t j - u s e r s @ e c l i p s e . o r g . [89] The AspectJ web site, http://www.aspectj.eclipse.org. [90] The DemeterJ web site. http://www.ccs.neu.edu/research/demeter/DemeterJava.  Bibliography  [91] The Eclipse web site, http://www.eclipse.org. [92] The JHotDraw project web site, http://www.jhotdraw.org. [93] The Metrics plugin for Eclipse web site, http://metrics.sourceforge.net. [94] The MixJuice improvement catalogue web site. http://cvs.rn 17n.org/ akr/mj/design-pattern/en. [95] The Refactoring Browser web site. http://st-www.cs.uiuc.edu/users/brant/Refactory.  112  

Cite

Citation Scheme:

        

Citations by CSL (citeproc-js)

Usage Statistics

Share

Embed

Customize your widget with the following options, then copy and paste the code below into the HTML of your page to embed this item in your website.
                        
                            <div id="ubcOpenCollectionsWidgetDisplay">
                            <script id="ubcOpenCollectionsWidget"
                            src="{[{embed.src}]}"
                            data-item="{[{embed.item}]}"
                            data-collection="{[{embed.collection}]}"
                            data-metadata="{[{embed.showMetadata}]}"
                            data-width="{[{embed.width}]}"
                            async >
                            </script>
                            </div>
                        
                    
IIIF logo Our image viewer uses the IIIF 2.0 standard. To load this item in other compatible viewers, use this url:
http://iiif.library.ubc.ca/presentation/dsp.831.1-0051755/manifest

Comment

Related Items