Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Towards A Catalog of Aspect-Oriented Refactorings: Miguel P. Monteiro João M. Fernandes

Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

Towards a Catalog of Aspect-Oriented Refactorings

Miguel P. Monteiro João M. Fernandes


Escola Superior de Tecnologia Departamento de Informática
Instit. Politécnico de Castelo Branco Universidade do Minho
Avenida do Empresário Campus de Gualtar
6000-767 Castelo Branco PORTUGAL 4710-057 Braga PORTUGAL

ABSTRACT [11] in the light of AOP and we propose several new AOP-
In this paper, we present a collection of aspect-oriented specific smells. We present a collection of AOP refactorings
refactorings covering both the extraction of aspects from object- aiming to remove those smells from legacy code (including
oriented legacy code and the subsequent tidying up of the updated versions of 4 of the refactorings presented in [23]). The
resulting aspects. In some cases, this tidying up entails the subject language we use is AspectJ [19], whose backward
replacement of the original implementation with a different, compatibility with Java opens the way for refactoring existing
centralized design, made possible by modularization. The Java applications by introducing AOP constructs. Space
collection of refactorings includes the extraction of common constraints prevent us from providing the complete descriptions
code in various aspects into abstract superaspects. We review of the refactorings in this paper: these can be found in [21].
the traditional object-oriented code smells in the light of aspect- We do not claim these collections are complete or
orientation and propose some new smells for the detection of comprehensive, but we believe they extend the existing
crosscutting concerns. In addition, we propose a new code smell proposals [18][14][15], thus contributing to further mature
that is specific to aspects. AOP. Though the refactorings presented in this paper derive
from studies of design patterns [12], they aim to be general-
Keywords purpose, rather than case specific or pattern specific.
Aspect-oriented programming, object-oriented programming, The rest of this paper is structured as follows. In section 0, we
refactoring, code smells, programming style. provide the motivation for our work. In section 3, we describe
the approach we took to develop the collection of refactorings.
1. INTRODUCTION In section 4, we review some of the traditional smells in the light
Refactoring [11][24] and Aspect-oriented programming (AOP) of AOP, provide the motivation for new code smells, specific to
[17] are two techniques that contribute to deal with the problems AOP, and propose several such smells. These smells require new
of permanent evolution of software. Refactoring facilitates the refactorings targeting AOP specific constructs, which we present
continuous change of source code, enabling it to evolve in line in section 5. In section 6, we survey related work and in section
with changes in environments and requirements. AOP provides 7 we consider future directions. In section 8, we summarize the
stronger modularization and software composition mechanisms paper.
than those provided by previous technologies, thus diminishing
the potential impact that changes to the code related to a given 2. MOTIVATION
concern have on code unrelated to that concern. We believe there are three main hurdles in need to be addressed
AOP’s steady progress from “bleeding edge” research field to so that refactoring techniques can be used in AOP software in an
mainstream technology [25] brings forward the problem of how effective and widespread way.
to deal with large number of object-oriented (OO) legacy code The first hurdle is the present lack of a fully developed idea of
bases. Experience with refactoring of OO software in the last “good” AOP style. This is an important issue, for a clear notion
half-decade suggests that refactoring techniques have the of style is a fundamental prerequisite for the use of refactoring,
potential to bring the concepts and mechanisms of aspect- enabling programmers to see where they are heading when
orientation to existing OO frameworks and applications. refactoring their code. Fowler et al. [11] advocated a specific
In this paper, we review some of the traditional OO code smells notion of style for OO code through a catalog of 22 code smells,
compounded by a catalog of 72 refactorings through which
those smells can be removed from existing code. These catalogs
AOSD 05 Chicago Illinois USA
proved very useful in bringing the concepts of refactoring and
© 2005 ACM 1-59593-043-4/05/03....$5.00 good OO style to a wider audience and in providing
Permission to make digital or hard copies of all or part of this work for programmers with guidelines on when to refactor and how best
personal or classroom use is granted without fee provided that copies are to refactor. Refactoring and a notion of good style are key
not made or distributed for profit or commercial advantage and that concepts of Extreme Programming [1], which regards a system’s
copies bear this notice and the full citation on the first page. To copy source code as primarily a communication mechanism between
otherwise, to republish, to post on servers or to redistribute to lists, people, rather than computers.
requires prior specific permission and/or a fee

111
A second hurdle – both a cause and a consequence of the first – 4. CODE SMELLS
is the present lack of an AOP equivalent of such catalogs. Our Code smells are the way proposed by Beck and Fowler (chap.3
work is based on the assumption that AOP would equally benefit of [11]) to diagnose problems in existing code that could be
from AOP specific catalogs of smells and refactorings, helping removed through refactorings. Code smells do not aim to
programmers to detect situations in the source code that could provide precise criteria for when refactorings are overdue.
be improved with aspects and guiding them through the Instead, code smells suggest symptoms that may be indicative of
corresponding transformation processes. something wrong in the code. Programmers are required to
A third hurdle is the absence of tool support for AOP constructs develop their own sense of when a symptom indeed warrants a
in current integrated development environments. The catalogs change. Decisions also depend on the specific aims of the
presented by Fowler et al. [11] provided a basis on which programmer and the specific state and structure of the code on
developers could rely to build tool support for OO refactoring: which he is working.
similar catalogs for AOP are likely to bring similar benefits to
tool developers. Tool developers will not be able to provide 4.1 On the Need for AOP Specific Smells
adequate support to refactoring operations unless they first have The notion of style in a programming language expresses the
a clear idea of AOP style, and consequently of exactly which coding practices that yield code easier to maintain and evolve.
refactorings are worthy of their development efforts. Though we Whenever a programming language provides alternative ways to
developed the refactorings presented in this paper to be achieve some result, the way that causes the least problems to
performed manually, we believe they can be helpful to present and future programmers is the one considered in the best
developers of tool support in identifying useful material on style. Throughout the various stages of development of
which they can focus their work. programming languages, many ideas of style appeared due to the
advent of new, superior mechanisms. We briefly mention three
examples:
3. THE APPROACH
We took the approach of using refactoring experiments based on 1. Dijkstra’s famous dictum that the “Go-to statement
case studies, as a vehicle for gaining the necessary insights. The [should be] considered harmful” [8] stemmed from the
case studies we used are code bases in Java and AspectJ with the availability of control structures, namely loops.
appropriate structural characteristics. We approached the Java
2. Fowler et al. [11] considered the use of the switch
code bases as bad-style or “smelly” AspectJ code, and searched
statement to be a code smell, due to the availability of
for the kinds of refactorings that would be effective in removing
polymorphism and dynamic binding.
those smells.
3. Orleans suggested in [20] that the ‘if’ statement be
The first case study comprised the extraction of one crosscutting
considered harmful in the context of languages using
concern from a workflow framework, whose results are
elaborate forms of predicate dispatch.
presented in [23]. Our second case study was the collection of
implementations (version 1.1) in both Java and AspectJ of the All these considerations suggest that the appropriate notion of
23 Gang-of-Four (GoF) design patterns [12], presented by style for a given language strongly depends on what can be
Hannemann and Kiczales [13]. achieved with that language. In this light, the suitable style of
AspectJ can not be the same as for Java. AspectJ enables
The 23 GoF patterns illustrate a variety of design and structural
programmers to perform compositions that are impossible with
issues that would be hard to find in a single code base (except in
Java and avoid negative qualities such as code scattering and
very large and complex systems). The GoF patterns effectively
code tangling. This suggests that many of traditional OO
comprise a microcosm of many possible systems. They provided
solutions resulting in those negative qualities should now be
us with a rich source of insights, without the need to analyze
considered bad style, including the OO implementations of some
large code bases or learn domain-specific concepts.
design patterns [13].
The implementations presented by Hannemann and Kiczales
The very compositional power of AspectJ can be cause for
[13] are currently one of the nearest things to examples of good
problems. AspectJ offers multiple ways to achieve various
AOP style and design, presenting a clear notion of the desirable
effects and compositions. For instance, the implementation of
internal structure for aspects. Many of the findings presented in
mixins [2] can be achieved both through marker interfaces and
this paper stem from our study of these examples, compounded
through inner static aspects placed within interfaces. Likewise,
with studies of Java implementations of the same patterns by
non-singleton aspect associations provide alternatives to
various authors [9][6], which further enriched the patterns’
solutions obtained with the default singleton aspects. AspectJ
potential as providers of insights.
programmers are sometimes faced with so many choices that it
Our approach was to pinpoint the refactorings that would be becomes hard to decide on the design most appropriate to a
needed to transform the Java implementations into the AspectJ particular situation. There is a need to further study the
implementations. We then tested and refined the refactorings consequences and implications of each solution in order to make
thus obtained on other Java implementations of the same choices clear. We believe that catalogs of code smells and
patterns [9][6]. The refactoring process described in [22] refactorings are an effective way to present this knowledge to
derived from one of our test sessions. programmers.

112
4.2 OO Smells in the Light of AOP enclosed within the interface modeling the superimposed role. If
We analyzed the code smells presented in [11], [30] and [16], the programmer strives for total obliviousness [10] of the
and believe some can be used by AOP programmers as secondary role, she can use Replace Implements with Declare
symptoms of the presence of crosscutting concerns. This Parents ([21], p.21; Table 1). As an alternative to Extract
particularly applies to Divergent Change ([11], p.79) and Interface Implementation [18], we propose Split Abstract Class
Shotgun Surgery ([11], p.80). According to Fowler et al., into Aspect and Interface ([21], p.21; Table 1), which
“Shotgun Surgery is one change that alters many classes” (i.e. a completely encapsulates the secondary concern into an aspect,
symptom of code scattering) and “Divergent Change is one class which introduces the extra state and behavior to the interface.
that suffers many kinds of changes” (i.e. a symptom of code When the related code is more complex than a simple
tangling). We think it is useful to extend these definitions to implementation of an interface, we suggest using Extract
cover methods as well as classes. Wake [30] mentions Feature into Aspect ([21], p.5; Table 1) to move all the related
configuration information, logging and persistence as possible code to an aspect (see section 5.2).
causes to the Shotgun Surgery smell, all of which can be
counted among the favorite examples for the use of AOP. 4.4 Abstract Classes as a Code Smell
Kerievsky [16] proposes a variant of Shotgun Surgery that he The AspectJ composition mechanisms enabling the emulation of
calls Solution Sprawl. Kerievsky states ([16], p.43) that “you mixins [2] also enable the separation of definitions (i.e.
become aware of this smell when adding or updating a system implementation code) from declarations in abstract classes, so
feature causes you to make changes to many different pieces of that these can be turned into interfaces. Hannemann and
code”. The difference between the two smells is the way they are Kiczales take this approach in implementing five of the GoF
sensed – “we become aware of Solution Sprawl by observing it, design patterns in AspectJ [13]. This separation has the
while we detect Shogun Surgery by doing it”. Both variants are advantage that classes become free to inherit from some other
equally promising as indicators of crosscutting concerns. class and interfaces can still be provided with a default
implementation. This suggests that abstract classes should now
We propose the Extract Feature into Aspect refactoring ([21], be considered a code smell. Two of the refactorings presented
p.5; see also Table 1 and section 5.2) as a general framework for here (see Table 1) remove that smell by moving implementation
the modularization of concerns detected through these smells. code to an aspect and turning abstract classes into interfaces. We
use Split Abstract Class into Aspect and Interface ([21], p.21) to
4.3 The Double Personality Code Smell extract the concrete members of an abstract class into an aspect,
The Double Personality smell can be found in classes that play and we turn the resulting pure abstract class into an interface
multiple roles. Ideally, each class should play a single role, using Change Abstract Class to Interface ([21], p.4).
meaning that it contains only one, coherent, set of
responsibilities. This often is not possible in OO frameworks 4.5 The Aspect Laziness Code Smell
and applications. The Aspect Laziness smell applies to aspects that do not carry
Examples of Double Personality can be found in the OO the full weight of their responsibilities and instead pass the
implementations of design patterns [12] that include what burden to classes, in the form of inter-type declarations. We
Hannemann and Kiczales call superimposed roles – roles detect this smell in aspects that resort to the mechanism of inter-
assigned by the pattern to classes that have functionality and type declarations to add state and behavior to a class when
responsibility outside the pattern [13]. Examples are the Chain something more dynamic and/of flexible would be desirable.
of Responsibility ([12], p.223) pattern, which superimposes the AspectJ inter-type declarations are a static mechanism, applying
Handler role to some of the participant classes, and the Observer to all instances of the target class, throughout their entire life
pattern ([12], p.293), which superimposes the Subject and cycles. We detect the Aspect Laziness smell in uses of inter-type
Observer roles. declarations for solving problems whose requirements have one
or several of the following characteristics:
One symptom that can help to detect Double Personality in Java
source code is implementation of interfaces. Interfaces are a • The additional state and/or behavior are needed by only a
popular way to model roles in Java – e.g. the motivation for subset of the instances of the target classes.
Extract Interface ([11], p.341). When a class implements an • The additional state and/or behavior are needed only during
interface modeling a role that does not relate to the class’ certain specific phases in the execution of the program.
primary concern, the class smells of Double Personality.
• Instances of the target classes (may) require multiple
When Double Personality is detected in one class, we suggest instances of that state and behavior simultaneously.
that developers analyze the code base to see if it applies to just
that class. Again, looking to the interfaces may help: if multiple In such cases, the mechanism of inter-type declarations is not
classes implement the interface, this means the secondary dynamic or flexible enough. It is preferable for the aspect itself
concern is crosscutting (it cuts across multiple classes). to hold the additional state and behavior and manage a map
between the additional state and the specific target instances.
If only one class is affected, or if the code of the secondary role
is restricted to the implementation of the interface, the solution We propose Replace Inter-type Field with Aspect Map ([21],
is to extract the secondary role to a mixin [2]. There are several p.28) and Replace Inter-type Method with Aspect Method ([21],
ways to do this. Laddad’s Extract Interface Implementation [18] p.33) to replace the existing design with a mapping logic that
suggests placing the secondary concern inside an inner aspect provides the same functionality more flexibly.

113
4.6 Evil Demons Though notifyObservers is overridden (lines 29-35 and 42-48),
Fowler et al. [11] also make brief references to evil demons, its functionality is reused (lines 32 and 45).
symbolizing wrong ways of thinking that negatively impact on 01 public class Flower {
the code. One is Procedural Thinking, representing approaches 02 private boolean isOpen;
03 private ONotifier oNotify = new ONotifier();
to OO programming stemming from procedural programming. 04 private ClNotifier cNotify = new ClNotifier();
We detect a similar problem with AOP – Object-Oriented 05
Thinking, or Decentralized Thinking – an OO-style approach to 06 public Flower() {
the use of aspect-specific constructs. This thinking translates in 07 isOpen = false;
08 }
not appreciating that aspects can hold state of their own, and in 09 public void open() { // Opens its petals
designs that excessively rely on inter-type declarations, in fact 10 System.out.println("Flower open.");
recreating within an aspect the decentralized designs typical of 11 isOpen = true;
12 oNotify.notifyObservers();
OO. Such designs lead to the Aspect Laziness smell. 13 cNotify.open();
14 }
4.7 Illustrative Example 15 public void close() { // Closes its petals
16 System.out.println("Flower close.");
In this section, we present a code example that is used in various 17 isOpen = false;
sections of this paper to illustrate several smells and effects of 18 cNotify.notifyObservers();
some of the refactorings. The example is based on Eckel’s 19 oNotify.close();
20 }
implementation [9] of the Observer pattern [12]. We describe a 21 public Observable opening() {
refactoring process targeting this example in [22]. 22 return oNotify;
23 }
The intent of Observer is to “define a one-to-many dependency 24 public Observable closing() {
between objects so that when one object changes state, all its 25 return cNotify;
dependents are notified and updated automatically” [12]. The 26 }
27 private class ONotifier extends Observable {
example includes two observers, one of which is shown in 28 private boolean alreadyOpen = false;
Figure 1, with the primary concern shaded (the other observer, 29 public void notifyObservers() {
class Hummingbird, is similar). Figure 2 shows the class playing 30 if(isOpen && !alreadyOpen) {
31 setChanged();
the role of Subject: Flower (shaded code relates to the primary 32 super.notifyObservers();
concern). Each of Flower’s two operations, open and close the 33 alreadyOpen = true;
petals, gives rise to one observing relationship. 34 }
35 }
01 public class Bee { 36 public void close() {
02 private String name; 37 alreadyOpen = false;
03 private OObserver oObserver = new OObserver(); 38 }
04 private CObserver cObserver = new CObserver(); 39 }
05 40 private class ClNotifier extends Observable {
06 public Bee(String nm) { name = nm; } 41 private boolean alreadyOpen = false;
07 private class OObserver implements Observer { 42 public void notifyObservers() {
08 public void update(Observable o, Object a){ 43 if(isOpen && !alreadyOpen) {
09 System.out.println( 44 setChanged();
10 "Bee " + name + "'s breakfast time!"); 45 super.notifyObservers();
11 } 46 alreadyOpen = true;
12 } 47 }
13 private class CObserver implements Observer { 48 }
14 public void update(Observable o, Object a){ 49 public void close() {
15 System.out.println( 50 alreadyOpen = false;
16 "Bee " + name + "'s bed time!"); 51 }
17 } 52 }
18 } Figure 2. Flower class as Subject in the implementation of
19 public Observer openObs() {
20 return oObserver; the Observer pattern from [9].
21 } Each observer likewise encloses one inner class implementing
22 public Observer closeObs() {
23 return cObserver; java.util.Observer for each observing relationship (Figure 1,
24 } lines 07-12 and 13-18 respectively). As prescribed by the
25 } interface, each inner class defines an update method (lines 08-11
Figure 1. Bee class as Observer in the implementation of the and 14-17). Because of this design, all participants betray strong
Observer pattern from [9]. doses of Double Personality.
Eckel’s implementation uses the Observer/Observable protocol As is plain from the example, OO does not cope well with
from Java’s standard java.util API, which requires the Subject concerns affecting multiple objects and classes, forcing
participant to inherit from java.util.Observable. Eckel’s design programmers to produce decentralized designs for crosscutting
manages to separate the two observing relationships by defining concerns, when they would like to centralize the concern’s
inside each participant an inner class for each relationship. Thus, implementation within some module. Such designs lead to
Flower defines 2 inner classes (Figure 2, lines 27-39 and 40-51 duplicated code in every class playing some role in the concern.
respectively) that inherit from java.util.Observable. Flower uses
2 inherited methods: (1) setChanged (lines 31 and 44), used to Programmers trying to cope with code scattering and tangling
mark a subject as having been changed, and (2) notifyObservers, often resort to interfaces and/or inner classes to ameliorate the
which notifies all its observers if the subject was changed. effects. These constructs improve both the interface and internal

114
structure of classes: interface types help to better organize the structure of the resulting aspects (following Tidy Up Internal
interactions of a class with other classes, and inner classes help Aspect Structure [21], p.36), because such tasks are
to better structure the internals of a class, namely to separate the considerably easier to perform after the associated
code related to the class’ primary concern from unrelated code. implementation is modularized. In case duplication is detected
We believe the limitations in the compositions achievable with among different but related aspects, we extract the
OO provide one of the motivations to use inner classes and commonalities to a (possibly reusable) superaspect (using
interfaces. Independent authors reached the same conclusion Extract Superaspect [21], p.37). This strategy leads to the
regarding interfaces [28]. following grouping: (1) extraction of crosscutting concerns, (2)
improving of the internal structure of an aspect, and (3)
generalization of aspects. The sequence of code transformations
5. THE REFACTORINGS described in [22] also fits naturally with this grouping.
This section presents an overview of our refactorings. These are
fully documented in [21], using a format and level of detail The three refactorings mentioned above are composite
similar to the one used by Fowler et al. [11] (Kerievsky took the refactorings. Rather than prescribe specific actions on the source
same approach in [16]). The format includes (1) name, (2) code, as is the case of those documented in [11], they provide a
typical situation, (3) recommended action, (4) motivation stating framework for the other refactorings from the same group,
the situations when applying the refactoring is desirable, (5) a specifying the situations when they should be used and when
detailed Mechanics section, and (6) code examples. Tables 1-3 they should not. For this reason they also provide suitable entry
present the refactorings, mentioning the first three elements of points to someone approaching the catalog.
the format.
The use of a composite refactoring is useful to provide a broader
The refactorings do not attempt to cover all possible situations view of a refactoring process. For instance, most extraction
that can potentially arise in source code. For instance, they do processes as prescribed by Extract Feature into Aspect ([21],
not cover uses of reflection. Likewise, they do not deal with p.5) entail a relaxation of the access qualifier of fields (usually
what we call the fragile base code problem [23][22], also known private), for a period spanning several refactorings (while there
as the fragile pointcut problem [26] – caused by the fact that is code accessing the field both inside and outside the aspect).
almost all refactorings can potentially break existing aspects, The above composite refactoring enables us to specify exactly
particularly pointcuts. We believe human programmers will only when the access to the field should be relaxed, and when it can
be able to deal thoroughly with this problem when provided again be turned private to the aspect.
with a new generation of tools, specifically designed to account
for the presence of aspects. However, we also believe it is 5.2 Refactorings for Extracting Features to
possible to keep this problem under control, provided adequate
practices are followed, including programming AspectJ’s
Aspects
We expect the refactorings from this group will comprise the
constructs with a prudent and appropriate style, such as that
starting point for the majority of the refactoring processes
proposed by Laddad [18]. This is particularly important with
targeting OO legacy code.
pointcuts, which should be made in a style stressing intent rather
than a specific case (e.g. expressions using wildcards). This way Extract Feature into Aspect ([21], p.5) pinpoints the procedures
pointcuts can express a general policy and may be robust enough for extracting the scattered elements of a crosscutting concern
not to be affected by minor modifications in the target code, into a single module. Four of the refactorings from this group
such as the removal or addition of a new class or method. are updated versions of those presented in [23]. Extract
Another good practice is to place the aspects close to the code Fragment into Advice ([21], p.9) is an updated version of
they affect whenever possible, to increase the likelihood that all Extract Advice from [23][22]).
team members are aware of the aspects potentially affected by
refactorings. This often entails placing the aspect in the same We suggest using Move Field From Class to Inter-type ([21],
package, or even within the same source file as the target class p.17) to move state to the aspect. Behavior can be moved using
(as inner or peer aspects). Move Method From Class to Inter-type ([21], p.19) and Extract
Fragment into Advice ([21], p.9).
The traditional OO refactorings can be used in AspectJ code as
well. We did not detect any refactoring from [11] targeting an Moving an inner class to an aspect is done in two stages: first
OO construct that could not be applied to that construct within using Extract Inner Class to Standalone ([21], p.13), to obtain a
aspects. For instance, in the mechanics of Extend Marker standalone class from the inner class, and next using Inline
Interface with Signature ([21], p.24) we prescribe the use of Class within Aspect ([21], p.15) to turn the resulting class into
Extract Method ([11], p.110) inside aspects. an inner class within the aspect. We did not see a justification
for defining a refactoring equivalent to Extract Inner Class to
5.1 Grouping the Refactorings Standalone ([21], p.13) for interfaces, as interfaces are not
generally used within classes. Interfaces are inlined into aspects
The collection is structured in groups of refactorings with
using Inline Interface within Aspect ([21], p.16), after which
similar purposes, as is done in [11]. The adopted grouping also
they can be turned into marker interfaces.
reflects a strategy likely to be followed in many refactoring
processes. This establishes that prior to anything else, all We propose Replace Implements with Declare Parents ([21],
elements related to a crosscutting concern should be moved to a p.21) for inlining the implements clause of classes implementing
single module (following Extract Feature into Aspect [21], p.5). the interfaces.
Only afterwards should we start improving the underlying

115
Table 1 – Refactorings for Extraction of Crosscutting Concerns
Name of the refactoring Typical situation Recommended action
An abstract class prevents their subclasses from Turn the abstract class into an interface and change
Change Abstract Class to
inheriting from another class its relationship with the subclasses from inheritance
Interface
to implementation
Extract Feature into Code related to a feature is scattered across several Extract all the implementation elements related to the
Aspect methods and classes, tangled with unrelated code feature to an aspect
Part of a method is related to a concern whose code Create a pointcut capturing the required joinpoint
Extract Fragment into
is being moved to an aspect and context and move the code fragment to an
Advice
appropriate advice based on the pointcut
Extract Inner Class to An inner class relates to a concern being extracted Eliminate dependencies from the enclosing class and
Standalone into an aspect turn the inner class into a standalone class
A small standalone class is used only by code within Move the class to within the aspect
Inline Class within Aspect
an aspect
Inline Interface within One or several interfaces are used only by an aspect Move the interfaces to inside the aspect
Aspect
Move Field from Class to A field relates to a concern other than the primary Move the field from the class to the aspect as an
Inter-type concern of its enclosing class inter-type declaration
Move Method from Class A method belongs to a concern other than the Move the method into the aspect encapsulating the
to Inter-type primary concern of its owner class secondary concern as an inter-type declaration
Classes implement interface related to a secondary Replace the implements in the class with a declare
Replace Implements with
concern. Implementation of the interface is used only parents in the aspect
Declare Parents
when the related concern is present in the system
Classes are prevented from using inheritance because Move all concrete members from the abstract class to
Split Abstract Class into
they already inherit from an abstract class defining an aspect. You can then turn the abstract class into
Aspect and Interface
some concrete members an interface

Table 2 – Refactorings for Restructuring the Internals of Aspects


Name of the refactoring Typical situation Recommended action
An inner interface represents a role used only within Add an inter-type abstract declaration of the specific
Extend Marker Interface the aspect. You would like the aspect to call a signature to the interface
with Signature method specific to one implementing type, not
declared by the interface
An aspect refers to specific concrete types, Replace the references to specific types with a
Generalize Target Type
preventing it from being reused marker interface and make the specific types
with Marker Interface
implement the marker interface
You would like a inter-type member to be visible in Declare the inter-type member as public and place a
Introduce Aspect
an aspect al all its subaspects, but not outside the declare error preventing its use outside the aspect
Protection
aspect inheritance chain inheritance chain
An aspect statically introduces additional state to a Replace the inter-type declarations with a structure
Replace Inter-type Field
set of classes, when a more dynamic or flexible link owned by the aspect performing a map between the
with Aspect Map
between state and targets would be desirable additional state and target objects
Replace Inter-type An aspect introduces additional methods to a class or Replace the inter-type method with a aspect method
Method with Aspect interface, when a more dynamic and flexible getting the target object as parameter
Method composition would be desirable
The internal structure of an aspect resulting from the Tidy up the internal structure of the aspect by
Tidy Up Internal Aspect
extraction of a crosscutting concern is sub-optimal removing duplication and dependencies on case
Structure
specific target types

116
Table 3 – Refactorings to deal with Generalization
Name of the refactoring Typical situation Recommended action
Extract Superaspect Two or more aspects contain similar code and functionality Move the common features to a superaspect
All subaspects use the same advice acting on a pointcut Move the advice to the superaspect
Pull Up Advice
declared in the superaspect
Pull Up Declare Parents All subaspects use the same declare parents Move the declare parents to the superaspect
Pull Up Inter-type An inter-type declaration would be best placed in the Move the inter-type declaration to the
Declaration superaspect superaspect
All subaspects use a marker interface to model the same Move the marker interfaces to the superaspect
Pull Up Marker Interface
role
Pull Up Pointcut All subaspects declare identical pointcuts Move the pointcuts to the superaspect
A piece of advice is used by only some subaspects, or each Move the advice to the subaspects that use it
Push Down Advice
subaspect requires a different advice
Push Down Declare A declare parents in a superaspect is not relevant for all the Move the declare parents to the subaspects
Parents subaspects where it is relevant
Push Down Inter-type An inter-type declaration would be best placed in a Move the inter-type declaration to the
Declaration subaspect subaspect where it is relevant
Push Down Marker A marker interface declared within a superaspect models a Move the marker interface to those subaspects
Interface role used only in some subaspects
A pointcut in the superaspect is not used by some Move the pointcut to those subaspects that use
Push Down Pointcut
subaspects inheriting it it

Figure 3 shows the participants from Figures 1-2, after each of the observing relationships and the moments when these become
two observing relationships was extracted to its own aspect, using effective, but the present structure does not enable this.
the refactorings presented in this section. During the extraction of 01 public class Flower {
both observing relationships [22] the isOpen field (line 4) was 02 private boolean isOpen;
encapsulated, yielding two new methods for the Flower class: 03 public Flower() {
isOpen (lines 6-8) and setIsOpen (lines 9-11). The code for the 04 isOpen = false;
05 }
reaction of the observers when they are notified of open and close 06 boolean isOpen() {
events was likewise extracted to methods breakfastTime (lines 26- 07 return isOpen;
29) and bedtimeSleep (lines 30-33) respectively. Figure 4 shows 08 }
09 private void setIsOpen(boolean newValue) {
part of the aspect related to observing the open operation. The 10 isOpen = newValue;
other aspect (not shown), related to the observation of close, is 11 }
similar. 12 public void open() { // Opens its petals
13 System.out.println("Flower open.");
14 setIsOpen(true);
5.3 Restructuring the Internals of Aspects 15 }
We can see from Figures 3 and 4 that the code for implementing 16 public void close() { // Closes its petals
the Observer pattern is no longer spread across the participant 17 System.out.println("Flower close.");
18 setIsOpen(false);
classes, but the structure of the aspect resulting from the 19 }
extraction still hardly resembles the one presented in [13], as it 20 }
ideally would be the case (Figure 5 shows a refactored structure 21 public class Bee {
22 private String name;
closer to that presented in [13]). The aspect’s internal structure 23 public Bee(String nm) {
still relates to the original, decentralized, design. The aspect 24 name = nm;
betrays Duplicated Code ([11], p.76), as it introduces identical 25 }
fields (Figure 4, lines 10-11 and 12-13) and methods (lines 18-20 26 public void breakfastTime() {
27 System.out.println(
and 21-23) to the two observer participants. The duplication has 28 "Bee " + name + "'s breakfast time!");
always been present, but now that the code is modularized, it is 29 }
clearly exposed. After modularization, the original design is no 30 public void bedtimeSleep() {
31 System.out.println(
longer justified and the inner classes comprise a needlessly 32 "Bee " + name + "'s bed time!");
complicated structure. 33 }
34 }
The code also betrays Aspect Laziness, because in this example it Figure 3. Code of Flower and Bee after extracting the
is desirable to select the individual objects participating in the observing relationships to an aspect.

117
Hannemann and Kiczales [13] mention four modularity properties When using Generalise Target Type with Marker Interface ([21],
for their implementation of the Observer pattern: locality, p.25) we may sometimes find that a single call to a case specific
reusability, composition transparency and (un)pluggability. Just method prevents a code fragment to be reusable. For such cases,
after the extraction, the aspect (Figure 4) has only the first and last we propose Extend Marker Interface with Signature ([21], p.24),
of these properties. which separates the generically applicable code from case-specific
01 public aspect ObservingOpen {
code, by extending marker interface with the method’s signature.
02 static class ONotifier extends Observable { This way we avoid the use of downcasts and eliminate
03 //... dependencies to specific types (i.e. the module no longer needs to
04 } import those types). The abstract declarations of methods isOpen
05 static class OObserver implements Observer {
06 //... and breakfastTime (Figure 5) result from using this refactoring.
07 }
public aspect ObservingOpen {
08 private ONotifier Flower.oNotify =
private interface Subject {}
09 new ONotifier(this);
private interface Observer {}
10 private OObserver Hummingbird.oObserver =
11 new OObserver(this);
public abstract boolean Subject.isOpen();
12 private OObserver Bee.oObserver =
public abstract void Observer.breakfastTime();
13 new OObserver(this);
private boolean Subject.alreadyOpen = false;
14
15 public Observable Flower.opening() {
private WeakHashMap subject2ObserversMap =
16 return oNotify;
new WeakHashMap();
17 }
private List getObservers(Subject subject) {
18 public Observer Bee.openObs() {
List observers =
19 return oObserver;
(List)subject2ObserversMap.get(subject);
20 }
if(observers == null) {
21 public Observer Hummingbird.openObs(){
observers = new ArrayList();
22 return oObserver;
subject2ObserversMap.put(subject,
23 }
observers);
24
}
25 pointcut flowerOpen(Flower flower):
return observers;
26 execution(void open()) && this(flower);
}
27 after(Flower flower) returning :
public void addObserver(Subject subject,
28 flowerOpen(flower) {
Observer observer) {
29 flower.oNotify.notifyObservers();
List observers = getObservers(subject);
30 }
if(!observers.contains(observer))
31 pointcut flowerClose(Flower flower):
observers.add(observer);
32 execution(void close()) && this(flower);
subject2ObserversMap.put(subject, observers);
33 after(Flower flower): flowerClose(flower) {
}
34 flower.oNotify.close();
public void removeObserver
35 }
(Subject subject, Observer observer) {
36 }
getObservers(subject).remove(observer);
Figure 4. Part of the extracted aspect ObservingOpen }
modularizing observations of Flower’s open operation. public void clearObservers(Subject subject) {
getObservers(subject).clear();
Inter-type declarations are one of the reasons why the structure of }
aspects resulting from extraction processes is often unsuitable. private void notifyObservers(Subject subject) {
if(subject.isOpen()&& !subject.alreadyOpen) {
Inter-type declarations are usually transparent to client code (to subject.alreadyOpen = true;
our knowledge, only code using AspectJ’s within pointcut List observers = getObservers(subject);
designator can be affected by extraction refactorings based on for(ListIterator it =
inter-type declarations) and therefore make it simple to move observers.listIterator();
it.hasNext();) {
members from classes to aspects. However, only the source code ((Observer)it.next()).breakfastTime();
is modularized: the inter-type members still belong to their }
respective target classes at the binary and runtime levels. Their }
}
static nature can lead to the Aspect Laziness smell. At the very pointcut flowerOpen(Subject subject):
least, the extracted aspect will need a tidying up. In some cases, execution(void open()) && this(subject);
including this one, it will require a complete redesign. after(Subject subject) returning:
flowerOpen(subject) {
The Tidy Up Internal Aspect Structure ([21], p.36) refactoring notifyObservers(subject);
}
provides the general framework for improving the internal pointcut flowerClose(Subject subject):
structure of extracted aspects. The refactorings it prescribes can execution(void close()) && this(subject);
transform the ObservingOpen aspect from Figure 4 to the one after(Subject subject): flowerClose(subject) {
shown in Figure 5. The mechanics prescribe at the start the use of subject.alreadyOpen = false;
}
Generalise Target Type with Marker Interface ([21], p.25). Using declare parents: Flower implements Subject;
the refactoring we replace references to concrete types (Flower, declare parents:
Bee and Hummingbird in the example) with marker interfaces (Bee || Hummingbird) implements Observer;
}
representing the roles played by the participants (Subject and
Observer in the example). This refactoring removes the Figure 5. Aspect ObservingOpen after being tidied up.
duplication caused by multiple inter-type declarations of the same The motivation to both Replace Inter-type Field with Aspect Map
member. In simpler cases, it is enough to attain (un)pluggability. ([21], p.28) and Replace Inter-type Method with Aspect Method

118
([21], p.33) is twofold. One is to remove the Aspect Laziness seems to be tools for the automatic detection of aspects, they also
smell. Another is to deal with hurdles arising with the movement mention several open questions about refactoring to aspects,
of duplicated inter-type declarations along aspect hierarchies (see including “how can existing code smells be used to identify
section 5.4). These two refactorings prescribe how to replace candidate refactorings?” and “how can the introduction of aspects
inter-type state and behavior with a mapping structure providing be described in terms of a catalog of new refactorings?”. In this
the same functionality in a more dynamic way, and amenable to paper, we contribute to answering these two questions.
be controlled by client objects. In this example we used the same
Iwamoto and Zhao announced in [15] their intention to build a
implementation, based on a weak hash map, as in the reusable
catalog of AOP refactorings. They present a catalog of 24
aspect for the Observer pattern, presented in [13].
refactorings, but the information provided about them is limited to
The motivation for Introduce Aspect Protection ([21], p.27) stems the names of the refactorings. The refactorings we present in this
from the impossibility of using the protected access in inter-type paper and document in [21] include a description of the situations
members. This refactoring prescribes how to preserve this access where the refactoring applies, mention of preconditions, detailed
through declare error clauses. mechanics and code examples.
Several authors [15][14][29][31] call into attention the fragile
5.4 Dealing with Generalization base code problem (though they do not use this name), in some
The refactorings from this group deal with the extraction of
cases illustrating it with some code examples. These authors
commonalities to superaspects, with Extract Superaspect ([21],
conclude that existing OO refactorings [11] can not be applied to
p.37) providing the general framework. All the other refactorings
code bases with aspects. We believe these problems can be
in this group deal with moving members up and down the
ameliorated if adequate procedures are followed [18], including
inheritance hierarchies of aspects. Refactorings for moving
adoption of an appropriate style for programming and evolving
traditional OO members such as fields and methods are not
aspect constructs, particularly pointcuts. Hanenberg et al. [14]
included, as the issues and mechanics are similar to those
propose aspect-aware refactorings – refactorings that take into
documented in [11]. In [22] we show how the reusable aspect
account the presence of aspects and preserve behavior by updating
presented in [13] can be extracted from the one illustrated in
any pointcuts that may be affected by the transformation – and
Figure 5.
propose a set of enabling conditions to preserve the observable
Pull Up Inter-type Declaration ([21], p.39) and Push Down Inter- behavior. By the author’s admission, these conditions must be
type Declaration ([21], p.42) have a very restricted scope of automatically verified by an aspect-aware tool, as the manual
applicability, only to simple cases not involving duplication. They verification is an exhausting task, even in small systems.
are almost anti-refactorings: one motivation for including them in Hanenberg et al. announce a tool providing a subset of the
the collection is to better document the related problems and warn functionality they deem desirable.
against attempts to treat inter-type declarations as if they were like
Hanenberg et al. [14] also propose three AOP refactorings –
the other kinds of members. The hurdles arise because duplicated
Extract Advice, Extract Introduction and Separate Pointcut. Their
inter-type declarations of fields can not generally be moved
Extract Advice corresponds to our Extract Fragment into Advice
between superaspects and subaspects. Such movements change
refactoring ([21], p.9). Our collection of refactorings [21] goes
the number of instances of inter-type fields and their relation to
deeper in exploring the refactoring space, providing more detail
aspect instances. It is important to keep in mind that (1) the
and tackling issues such as the tidying up of the internal structure
visibility scopes of multiple inter-types declarations of the same
of aspects resulting from extraction processes. We do not
member can not overlap and that (2) target objects (i.e. instances
subscribe the recommendation, in their Extract Advice refactoring,
of classes affected by the inter-type declaration) have one separate
to use ‘around‘ advice in the general case. We think that in cases
instance of the inter-type member for each subaspect. If the
where either ‘before’ or ‘after’ advice can be used, these should
various inter-type declarations are factored out to a single
be used in preference to ‘around’, because it makes the scope of
declaration in a superaspect, target objects will have just one
the advice easier to perceive at a first look at the code. In addition,
instance of the introduced member. This situation is somewhat
the ‘around’ advice is also more powerful than is often needed. In
similar to changing a class member from instance to static. In
the case of code using it without a strict need for it, we envision
most cases, dealing with duplicated inter-type declarations entails
refactorings such as Change Around Advice to Before and Change
the prior replacement of the introduced fields with some mapping
Around Advice to After Returning. Their proposed Extract
logic, establishing the links between target objects and the
Introduction refactoring corresponds to our Move Field from
additional state and behavior. Such replacements happen to be
Class to Inter-type ([21], p.17) and Move Method from Class to
exactly what is accomplished by Replace Inter-type Field with
Inter-type ([21], p.19) refactorings, which provide more detail.
Aspect Map ([21], p.28) and Replace Inter-type Method with
Separate Pointcut relates to evolution of pointcuts and has no
Aspect Method ([21], p.33).
correspondence in our collection. This refactoring argues that, just
The remaining refactorings from this group deal with pulling up as it is beneficial to organize our systems using small methods
and pushing down aspect-specific constructs, including pointcuts, with meaningful names, we should do the same with pointcuts.
advice and declare parents clauses. Inner interfaces are also Hanenberg et al. do not elaborate on code smells, but we can infer
included due to their widespread use as marker interfaces. from Separate Pointcut that anonymous pointcuts could be a code
smell.
6. RELATED WORK In [18] Laddad prescribes several guidelines to ensure AOP
Deursen et al. [7] give a brief overview of the state of art in the refactorings for concern extraction are applied in a safe way.
area of aspect mining and refactoring. Though their main concern These involve the creation of a first version of the pointcut, based

119
on a case-by-case enumeration of the interesting joinpoints, Laddad does not pinpoint the code smells that his refactorings are
followed by its replacement with a semantically more meaningful supposed to remove. We think that the material presented by
pointcut, based on wildcards. Laddad also proposes a mechanism Laddad has the potential to throw new light on existing OO code
based on AspectJ’s declare error mechanism to verify whether two smells or to yield new ones. For instance, his Extract Method
different pointcut expressions capture exactly the same set of Calls and Replace Argument Trickle by Wormhole refactorings
joinpoints. In addition, Laddad recommends that aspects start respectively suggest the Scattered Method Calls and Argument
being developed with a restricted scope, often affecting the Trickle smells. Further research is required to discover latent
methods of a single class, in order to make it simpler to test their smells and assess their feasibility and applicability.
impact on the base code. Only afterwards should the scope of the
Tonella and Ceccato [28] base their work on the assumption that
aspect widen, when its functionality is already tested with the
interfaces are often (not always) related to concerns other than the
restricted case. Considering that at present there is no adequate
one pertaining to the system’s main decomposition. This is an
tool support for AOP refactorings, and that aspects can potentially
Interface Implementation smell, though the authors do not name it
impact a large number of joinpoints across an entire system,
this way. They provide specific guidelines for when an interface
procedures such as these are essential to any refactoring process
implementation is a symptom of a latent aspect and present a tool
targeting non-trivial systems.
for mining and extracting aspects based on these criteria, and
In addition, Laddad presents a collection of refactorings [18] with report on experimental results. These extractions are also covered
a significant utility value, particularly to developers of J2EE by the refactorings we present here and document in [21]. The
applications. The refactorings vary widely in both level and scope authors also point out various issues that can arise in a typical
of applicability, including generally applicable refactorings like extraction of an interface implementation into an aspect. Our
Extract Interface Implementation, Extract Method Calls, and refactorings prescribe procedures to deal with all these issues.
Replace Override with Advice, but also concern-specific
In [3] and [4] Cole and Borba propose programming laws from
refactorings such as Extract Concurrency Control and Extract
which refactorings for AspectJ can be derived. The authors focus
Contract Enforcemement. In addition, some refactorings belong to
on the use of their laws to derive existing refactorings such as
the category of “refactoring to patterns” as presented by Kerievsky
those proposed in [18], [14] and [15], and describe two case
[16] – Extract Worker Object Creation and Replace Argument
studies in which the laws were tested, comprising the extraction of
Trickle by Wormhole. These two refactorings are based on two of
concurrency control and distribution respectively. Many, though
the design patterns presented by Laddad in [19] – Worker Object
not all, of the laws relate to the extraction of crosscutting concerns
Creation ([19], p.247) and Wormhole ([19], p.256) respectively.
to aspects, and therefore there is some overlap between the
The Extract Exception Handling refactoring as presented in [18]
refactorings they derive and our own extraction refactorings
goes towards a variant implementation of the Exception
(section 5.2). However, their main emphasis is to provide proofs
Introduction pattern ([19], p.260).
that the transformations are behavior preserving, while we focus
We believe programmers would benefit if Laddad’s refactorings on covering new ground in the refactoring space. Nevertheless,
were presented in the same format as used by Fowler et al. [11] the authors remark that extraction procedure for the second case
and Kerievsky [16], and which we use as well [21][23] (some study is generalizable, because its implementation of distribution
refactorings are presented with only a mention of its name and a is commonly used, and claim that it is possible to derive a
brief motivating paragraph). A mechanics section would be concern-specific Extract Distribution refactoring.
particularly beneficial, having proved very useful as a checklist
To our knowledge, no work besides ours deals with the potentially
and to lead developers through the safest sequences of steps, in
bad internal structure of aspects resulting from extraction
preference to riskier or less convenient ones. The important step-
processes. With the exception of the work by Tonella and Ceccato
by-step guidelines proposed by Laddad for creating a new aspect
[28], we do not have knowledge of any other work covering the
and subsequently evolving it are included in the code example
issue of AOP code smells.
illustrating the use of Extract Method Calls, but not in several
other refactorings to which they also apply (Laddad places some
reminders). A mechanics section would make that part process 7. FUTURE WORK
clearer, and would clarify the relations between refactorings.
7.1 Other Code Smells
We noticed that several of Laddad’s refactorings, namely the In addition to the traditional OO smells we mentioned in section
problem-specific ones, can be decomposed into simpler, lower 4.2, there are a few others we believe can be useful in detecting
level steps – always an important thing with refactoring. During crosscutting concerns, but which we did not sufficiently explore
our work on the mechanics of the refactorings documented to pinpoint suitable refactorings to remove them. We’re
in [21], we focused on the minute details of the refactoring considering the possibility that Parallel Inheritance Hierarchies
process, enabling us to improve their characterization. In some ([11], p.83) and Combinatorial Explosion ([30], p.109) may be
cases, this led us to decompose the refactoring under study into indicative of the presence of crosscutting concerns in some cases
several smaller steps. For instance, Split Abstract Class into (the latter is a variant of the former, proposed by Wake [30]).
Aspect and Interface ([21], p.21) and Change Abstract Class to We’re presently considering whether these smells could be
Interface ([21], p.4) were initially conceived as a single considered symptoms of the “tyranny of the dominant
refactoring. We believe similar benefits can be obtained by decomposition” [27] in some cases.
similarly approaching Laddad’s refactorings – some of the
resulting lower level steps would correspond to existing steps, Besides existing OO smells, there are many latent AOP specific
while others would possibly yield new refactorings. smells waiting to be discovered. For instance, privileged aspects:
the rationale for avoiding them is the same as for avoiding the use

120
of public data. As Colyer and Clement remark in [5], aspect 7.4.2 Pointcuts
privilege confers the general privilege to see any private state At present, refactorings and code smells specifically targeting
anywhere, while one often wishes to express privilege with pointcuts are still a largely unexplored area. AspectJ’s pointcut
respect to a single class or a restricted set of classes. Presently, protocol comprises a rich language for quantification [10] and is
this is not possible with AspectJ. Unfortunately, privileged aspect likely to yield an equally rich pattern language for refactoring
may be unavoidable in cases affecting multiple packages and in pointcut expressions, as well as their interaction with advice.
which the aspect needs access to non-public (e.g. protected and Further research is needed on the adequate use of pointcut
package-protected) data. Refactoring the affected code bases to designators (e.g. pointcut smells), and how best to evolve pointcut
expose the non-public data is one alternative. We need to study expressions.
use cases of privileged aspects to assess whether common patterns
can be found, and pinpoint refactorings that tackle this issue. 7.5 Restructuring the Remaining Base Code
In this paper, we cover the restructuring of aspect code resulting
7.2 Maturing the Refactorings from the extraction of crosscutting concerns, taking advantage of
There is scope for maturing the refactorings presented here. It is the newfound modularization. It is also worth to study the impact
important to test the refactorings with more case studies, of such extractions on the remaining code base and what actions
particularly larger and more complex ones. In addition, we would be desirable (e.g. post-extraction refactorings).
consider the possibility that the composite refactorings (section
5.1) will evolve to give origin to various refactorings in the 7.6 Dealing with Published Interfaces
conventional sense, or to be turned into an introductory text to a Refactoring legacy code entails dealing with published interfaces,
group of related refactorings. i.e. interfaces used by clients that developers could not change.
Occasionally the tangling resulting from the presence of
7.3 Other Refactoring Ideas crosscutting concerns is present in the signatures, in which case it
We detected more latent refactorings in the material from our case can not be readily removed. In such cases, developers have the
studies. Next, we present some promising ideas for refactorings option to refactor towards rather than to a goal, while a
that were not yet fully explored: deprecation policy is pursued. We partially dealt with that issue in
• Replace Throws with Declare Error – many existing [23], having devised the Partition Constructor Signature
instances of Java code throw an exception upon detection of refactoring ([21], p.44). We did not continue our work in that
illegal situations. Some of these situations can be specified direction, but deem it worthy of further research.
by statically determinable pointcuts, in which case it is more
effective to replace them with a declare error clause. 7.7 Opposite Refactorings
We do not provide opposites for the presented refactorings,
• Remove Signatures from Inner Interface – As a rule, marker preferring to focus on extending the reach of the existing
interfaces do not declare operations, so it is worth exploring collection of refactorings. However, opposites are important to
a refactoring to remove the operations declared by an inlined enable developers to backtrack, whenever they find out they took
interface. a wrong turn, and because opposites are often useful in their own
right (e.g. pull up vs. push down refactorings).
• Replace Downcast with Interface Extension – We proposed
Extend Marker Interface with Signature ([21], p.24) to
resolve dependencies to concrete types caused by calls to 8. SUMMARY
type-specific methods. This idea can be taken further by In this paper, we review existing OO code smells in the light of
completely removing dependencies on a type, namely type AOP. Divergent Change can be a sign of code tangling and both
casts, to the point of removing the import of the type. Shotgun Surgery and Solution Sprawl can be signs of code
scattering. We propose AOP specific code smells, both for
In addition, there are many possible variants to the refactorings detecting crosscutting concerns in existing OO code and for
documented in [21]. One example is to extract common code from improving the structure of extracted aspects – Double Personality,
multiple, similar aspects through an Extract Subaspect refactoring Abstract Classes and Aspect Laziness.
instead of an Extract Superaspect ([21], p.37).
Simply moving the members relating to a crosscutting concern
7.4 Covering Other Language Characteristics does not yield a well-formed aspect. Extracted aspects expose
The refactorings we present here are the result from the two problems caused by crosscutting, including Duplicated Code
specific case studies, and do not use every possible aspect ([11], p.76). Aspect Laziness relates to the static nature of inter-
construct. New research should cover the remaining aspect type declarations. We can take advantage of the new-found
constructs, as well as the interactions between them and with modularity to tidy up the aspect’s internal structure with further
existing Java constructs. We next mention two subjects. refactorings. We present a collection of 27 AOP refactorings,
documented in [21], which can remove these smells from source
7.4.1 Non Singleton Aspect Association code, comprising the following groups:
Our work so far concentrated on singleton aspects. In future, we
• 10 refactorings to remove the smells related to crosscutting
expect to cover other kinds of aspect association in order to obtain
concerns from existing OO code. Besides covering common
a clearer idea of the advantages and disadvantages of non-
members such as fields and methods, these refactorings also
singleton aspects, e.g., when should they be preferred and what
deal with inner classes and interfaces.
refactorings should be used to transform singleton aspects.

121
• 6 refactorings to remove problems found in extracted [14] Hanenberg, S., Oberschulte, C., Unland, R., Refactoring of
aspects, including Duplicated Code and Aspect Laziness. Aspect-Oriented Software, Net.ObjectDays 2003, Erfurt,
Germany, September 2003.
• 11 refactorings to deal with the generalization of aspects (i.e.
the extraction of common code to superaspects). [15] Iwamoto, M., Zhao, J., Refactoring Aspect-Oriented
Programs, 4th AOSD Modeling With UML Workshop,
We discuss some of the many future directions in the hunt for new UML'2003, San Francisco, USA, October 2003.
AOP refactorings and code smells, taking the contributions of this
paper and related work as the starting point. [16] Kerievsky, J., Refactoring to Patterns, Addison-Wesley,
2004.
Acknowledgements [17] Kiczales, G., Lamping, J., Mendhekar, A., Maeda, C., Lopes,
Miguel Monteiro is supported by PRODEP III (Medida 5 – Acção C., Loingtier, J., Irwin, J., Aspect-Oriented Programming,
5.3 – Eixo 3 – Formação Avançada de Docentes do Ensino ECOOP'97, Finland, June 1997.
Superior) and by project PPC-VM (POSI/CHS/47158/2002). João
M. Fernandes is supported by project METHODES [18] Laddad, R., Aspect-Oriented Refactoring, parts 1 and 2, The
(POPI/CHS/37334/2001). Four anonymous referees made Server Side, 2003. www.theserverside.com/
valuable suggestions which helped to improve this paper. [19] Laddad, R., AspectJ in Action – Practical Aspect-Oriented
Programming, Manning 2003.
9. REFERENCES [20] Orleans, D., Separating behavioral concerns with predicate
[1] Beck, K., Extreme Programming Explained: Embrace dispatch, or, if statement considered harmful, workshop on
Change, Addison-Wesley 2000. Advanced Separation of Concerns in Object-Oriented
[2] Bracha, G., Cook, W., Mixin-Based Inheritance, ECOOP/ Systems at OOPSLA ’01, Tampa Bay, USA, October 2001.
OOPSLA 1990. [21] Monteiro, M. P., Catalogue of Refactorings for AspectJ,
[3] Cole, L., Borba, P., Deriving Refactorings for AspectJ, Technical Report UM-DI-GECSD-200402, Universidade do
presented in AOSD'2005, Chicago, USA, March 2005. Minho, December 2004. Available at
www.di.uminho.pt/~jmf/ PUBLI/papers/2004-TR-02.pdf
[4] Cole, L., Borba, P., Using Programming Laws to Modularize
Concurrency in a Replicated Database Application, 1st [22] Monteiro, M. P., Refactoring a Java Code Base to AspectJ –
Brasilian Workshop on Aspect-Oriented Software An Ilustrative Example, Technical Report UM-DI-GECSD-
Development - WBSOA'04 - SBES'04, Brazil, October 2004. 200403, Universidade do Minho, December 2004. Available
at www.di.uminho.pt/~jmf/PUBLI/papers/2004-TR-03.pdf
[5] Colyer, A., Clement, A., Large-scale AOSD for Middleware,
AOSD 2004, Lancaster, UK, March 2004. [23] Monteiro, M. P., Fernandes, J. M., Object-to-Aspect
Refactorings for Feature Extraction, industry paper
[6] Cooper, J., Java Design Patterns: A Tutorial, Addison- presented at AOSD'2004, UK, Lancaster, March 2004.
Wesley 2000. Also availabe at www.patterndepot.com/put/8/ Available at http://aosd.net/ 2004/archive/Monteiro.pdf
DesignJava.PDF.
[24] Opdyke, W., Refactoring Object-Oriented Frameworks,
[7] Deursen, A., Marin, M., Moonen, L., Aspect Mining and Ph.D. Thesis, University of Illinois at Urbana-Champaign,
Refactoring, workshop on REFactoring: Achievements, 1992.
Challenges, Effects (REFACE03), Waterloo, Canada,
November 2003. [25] Sabbah, D., Aspects – from Promise to Reality, AOSD 2004,
Lancaster, UK, March 2004.
[8] Dijkstra, E., Go-to Statement Considered Harmful,
Communications of the ACM, 11 (3), March 1968. [26] Störzer, M., Koppen, C., PCDiff: Attacking the Fragile
Pointcut Problem, Interactive Workshop on Aspects in
[9] Eckel, B., Thinking in Patterns, revision 0.9. book in Software (EIWAS) 2004, Berlin, Germany, September 2004.
progress, May 20, 2003. Available at http://64.78.49.204/
IPatterns-0.9.zip [27] Tarr, P., Ossher, H., Harrison, W., Sutton Jr., S.M., N
Degrees of Separation: Multi-Dimensional Separation of
[10] Filman, R. E., Friedman, D. P., Aspect-Oriented Concerns, ICSE'99, May, 1999.
Programming is Quantification and Obliviousness,
workshop on Advanced Separation of Concerns, OOPSLA [28] Tonella, P., Ceccato, M., Migrating Interface
2000, Minneapolis, October 2000. Implementation to Aspects, ICSM'04, Chicago, USA,
September 2004.
[11] Fowler, M. (with contributions by K. Beck, W. Opdyke and
D. Roberts), Refactoring – Improving the Design of Existing [29] Tourwé, T., Brichau, J., Gybels, K., On the Existence of the
Code, Addison Wesley 2000. AOSD-Evolution Paradox, AOSD 2003 Workshop on
Software-engineering Properties of Languages for Aspect
[12] Gamma, E., Helm, R., Johnson, R., Vlissides, J., Design Technologies, Boston, USA, 2003.
Patterns – Elements of Reusable Object-Oriented Software,
Addison-Wesley, 1994. [30] Wake, W., Refactoring Workbook, Addison Wesley, 2004.
[13] Hannemann, J., Kiczales, G., Design Pattern Implementation [31] Wloka, J., Refactoring in the Presence of Aspects,
in Java and AspectJ, OOPSLA 2002, November 2002. ECOOP2003 PhD workshop, July 2003.

122

You might also like