A Framework for the Checking and Refactoring of...

50
A Framework for the Checking and Refactoring of Crosscutting Concepts MACNEIL SHONLE The University of Texas at San Antonio and WILLIAM G. GRISWOLD and SORIN LERNER University of California, San Diego Programmers employ crosscutting concepts, such as design patterns and other programming idioms, when their design ideas cannot be efficiently or effectively modularized in the underlying programming language. As a result, implementations of these crosscutting concepts can be hard to change even when the code is well structured. In this article, we describe Arcum, a system that supports the modular maintenance of crosscutting concepts. Arcum can be used to both check essential constraints of crosscutting concepts and to substitute crosscutting concept implementations with alternative implementations. Arcum is complementary to existing refactoring sys- tems that focus on meaning-preserving program transformations at the programming-language-semantics level, because Arcum focuses on transformations at the conceptual level. We present the underpinnings of the Arcum approach, and show how Arcum can be used to address several classical software engineering problems. Categories and Subject Descriptors: D.2.7 [Software Engineering]: Software Architectures—Domain-specific architectures, languages, patterns. General Terms: Languages, Design. Additional Key Words and Phrases: Design patterns, Refactoring. 1. INTRODUCTION Modularity is a software design principle to help manage complexity: programmers de- compose programs into smaller units, called modules, each of which can have an interface that both hides a module’s internal implementation details and defines how the other mod- ules in the system can interact with it. Modularity has many benefits, including modular substitution and interface checking. Modular substitution is beneficial because the imple- mentation of a module can be changed without requiring changes to, or extensive retesting of, other parts of the system. Interface checking is beneficial because it can detect pro- gramming errors, such as type errors, which leads to improved reasoning over the module itself or over the uses of the module. Author’s address: Macneil Shonle, Department of Computer Science, The University of Texas at San Antonio, One UTSA Circle, San Antonio, TX 78249. This work was supported in large part by the NSF Science of Design grant CCF-0613845, with additional support from an IBM Eclipse Innovation Award. Permission to make digital/hard copy of all or part of this material without fee for personal or classroom use provided that the copies are not made or distributed for profit or commercial advantage, the ACM copyright/server notice, the title of the publication, and its date appear, and notice is given that copying is by permission of the ACM, Inc. To copy otherwise, to republish, to post on servers, or to redistribute to lists requires prior specific permission and/or a fee. c 20YY ACM 0000-0000/20YY/0000-0001 $5.00 ACM Journal Name, Vol. V, No. N, Month 20YY, Pages 1–50.

Transcript of A Framework for the Checking and Refactoring of...

Page 1: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring ofCrosscutting Concepts

MACNEIL SHONLE

The University of Texas at San Antonio

and

WILLIAM G. GRISWOLD and SORIN LERNER

University of California, San Diego

Programmers employ crosscutting concepts, such as design patterns and other programming idioms, when theirdesign ideas cannot be efficiently or effectively modularized in the underlying programming language. As a result,implementations of these crosscutting concepts can be hard to change even when the code is well structured.

In this article, we describe Arcum, a system that supports the modular maintenance of crosscutting concepts.Arcum can be used to both check essential constraints of crosscutting concepts and to substitute crosscuttingconcept implementations with alternative implementations. Arcum is complementary to existing refactoring sys-tems that focus on meaning-preserving program transformations at the programming-language-semantics level,because Arcum focuses on transformations at the conceptual level.

We present the underpinnings of the Arcum approach, and show how Arcum can be used to address severalclassical software engineering problems.

Categories and Subject Descriptors: D.2.7 [Software Engineering]: Software Architectures—Domain-specificarchitectures, languages, patterns.

General Terms: Languages, Design.

Additional Key Words and Phrases: Design patterns, Refactoring.

1. INTRODUCTION

Modularity is a software design principle to help manage complexity: programmers de-compose programs into smaller units, called modules, each of which can have an interfacethat both hides a module’s internal implementation details and defines how the other mod-ules in the system can interact with it. Modularity has many benefits, including modularsubstitution and interface checking. Modular substitution is beneficial because the imple-mentation of a module can be changed without requiring changes to, or extensive retestingof, other parts of the system. Interface checking is beneficial because it can detect pro-gramming errors, such as type errors, which leads to improved reasoning over the moduleitself or over the uses of the module.

Author’s address: Macneil Shonle, Department of Computer Science, The University of Texas at San Antonio,One UTSA Circle, San Antonio, TX 78249.This work was supported in large part by the NSF Science of Design grant CCF-0613845, with additional supportfrom an IBM Eclipse Innovation Award.Permission to make digital/hard copy of all or part of this material without fee for personal or classroom useprovided that the copies are not made or distributed for profit or commercial advantage, the ACM copyright/servernotice, the title of the publication, and its date appear, and notice is given that copying is by permission of theACM, Inc. To copy otherwise, to republish, to post on servers, or to redistribute to lists requires prior specificpermission and/or a fee.c© 20YY ACM 0000-0000/20YY/0000-0001 $5.00

ACM Journal Name, Vol. V, No. N, Month 20YY, Pages 1–50.

Page 2: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

2 · Macneil Shonle et al.

However, not every logical unit of a program, or concern, can be effectively encapsulatedinto a module. The inability of a concern to be encapsulated can be due to limitations in theprogramming language or the inherent non-modular nature of the concern [Kiczales et al.1997]. The implementation of a concern that cannot be encapsulated, called a crosscuttingconcern, is harder to change and harder to reason about than a modular implementation.As a result, the implementation of a crosscutting concern does not have the benefits ofmodular substitution and interface checking.

The visitor pattern is one example of a crosscutting concern that can be hard to changeand hard to check. The visitor pattern is a traversal concern, and is employed when aheterogeneous set of data-structures needs to be traversed in a depth-first order [Gammaet al. 1995]. A simple conceptual change to the traditional implementation of the visitorpattern, such as “use a breadth-first traversal instead of a depth-first traversal,” wouldrequire changes to every class involved. Additionally, there may be other changes that aresimple to express conceptually, such as “don’t traverse over cached objects,” that maynot require an entire rewrite of the system, but still would be tedious and error prone tochange. The visitor pattern is also brittle to changes made to the class structure, such aswhen a field is added to a class. For example, global changes are necessary when instancesof a type that must also be traversed become reachable from a different class [Lieberherr1996, p. 60].

Unfortunately, such crosscutting is not rare. Crosscutting concepts, such as designpatterns and well-structured programming idioms, are a common form of crosscuttingand thus fall outside of traditional modular bounds, even when the program is well-designed [Griswold 2001]. Such crosscutting concepts might be general in nature, likethe visitor pattern, or domain-specific in nature, relevant only to a family of programs.As a result, even well-designed programs are susceptible to subtle bugs, and will have toundergo changes that are crosscutting in nature.

In this article, we present a framework called Arcum, a tool-based approach that extendsthe benefits of modularity to such crosscutting concepts. Arcum’s goal is to be a meansfor programmers to express their intentions to the IDE.1 Specifically, our implementationof Arcum in the Eclipse IDE allows many kinds of crosscutting concepts implemented inJava to be automatically checked and replaced with alternative implementations, allowingpreviously difficult-to-modify code to become more fluid and flexible.

1.1 Overview of the Arcum Approach

The key challenge in maintaining the crosscutting implementation of a concept is thatthe relevant code is not localized to a single module. For example, the concept may beexpressed numerous times in the code, constituting repetition: All of the traversal coderelated to the visitor pattern will commit to using the same algorithmic implementation(such as using the implicit runtime stack or an explicit Stack object).

Arcum copes with crosscutting using a match-and-replace paradigm. Specifically, theexpected implementation of a crosscutting concept is expressed as a set of syntactic pat-terns and semantic constraints, called an option. With such matching, it is possible to findall instances of the implementation of a crosscutting concept, as well as check that certainproperties are satisfied by that implementation. Such checks are applied at compile-time,

1In that spirit, the name “Arcum” derives from the Latin phrase “intendere arcum in,” which means “to aim a bowand arrow at (something)” and is the metaphorical root of the word intention [Dennett 1992, p. 333].

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 3: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 3

much like type checking. For example, an option for the visitor pattern can test if thetraversal code does not mistakenly follow backward links back to parent objects.

In Arcum, once a crosscutting implementation can be found, it can also be replacedwith a different implementation. However, rather than the programmer writing replace-ment rules (transformations) in a pattern-action style, the programmer instead writes a newset of syntactic patterns and semantic constraints for the desired implementation—a sec-ond option. Arcum can then infer the differences between the two options’ patterns, andinternally construct a set of transformation rules and checks to achieve the replacement.The inference step is made possible by applying a modularity regime to the patterns them-selves: An Arcum interface for the pair of options is declared, to which both must adhere.The interface is comprised of typed parameters and semantic checks, in which the param-eters are program fragments (e.g., expressions) that are passed between the two patternmatchers: the patterns for the current implementation match existing code fragments, andthe patterns for the desired implementation are “run backwards” to take the existing codefragments and generate new code fragments in their place.

Arcum declarations are auxiliary supplements to a Java program. A programmer maybe motivated to declare one or more options when the need arises for either transforming acrosscutting concept or for better checking of a particular implementation. Once declared,transformation is merely a matter of specifying the replacement of the prevailing optionwith an alternative option. The correctness of such a replacement is aided by checks speci-fied in the Arcum declarations. Because only patterns are declared and the transformationsthemselves are inferred, replacements can be run in both directions, that is, from one optionto another, and then back again.

Arcum declarations can be maintained as persistent, supplemental descriptions to a Javaprogram, offering the benefits of substitutability and checking to crosscutting code. Beingpersistent, unlike a typical refactoring transformation invoked by a programmer via anIDE, an instantiated option is continuously checked (for example, every time the programis compiled), not just during refactoring. Continuous checking ensures that the abilityto replace the prevailing option with an alternative option is preserved. Also, due to itsdeclarative nature, an option provides a precise mechanism for documenting a crosscuttingconcept and expressing the programmer’s intentions for its implementation.

A unique benefit of the Arcum approach is that because Arcum declarations are supple-ments, the core source code remains unchanged, so that programs retain exactly the sameJava semantics they had before. The program is changed only when one implementation istransformed to one of the alternative options. Such transformations are always performedwithin the IDE at the programmer’s discretion, by specifying a change in the prevailingoption. The separation of Arcum code and Java code reduces the cost and risk of ini-tiating the use of Arcum, and enables late-stage adoption. Even though Arcum does notdirectly extend the Java programming language, its checks are a form of extension to Java’stype system (achieved through additional error messages enabled by the user). Hence, theflexibility of the Arcum approach relies upon the expressiveness of programmer-specifieddeclarations rather than upon the expressiveness of a new programming language.

1.2 Contributions

The primary contribution of this article is the description and detailed evaluation of Arcum,a new method for extending key benefits of modularity—checking and substitutability—tocrosscutting concepts.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 4: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

4 · Macneil Shonle et al.

Arcum’s declarative match-and-replace approach comprises two other contributions tothe software tools literature:

— Arcum’s use of interfaces to associate related sets of patterns demonstrates a practi-cal declarative method for specifying a broad class of reversible code transformations.

— The Arcum approach generalizes the concept of refactoring by unifying refactoringand program checking. The semantic preconditions employed by traditional refactoringtools use the programming language’s semantics for guarantees of program equivalence.These semantics assume a strict model of equivalence, in which behaviors are preservedin the same way across all programs, not allowing a looser notion of equivalence based onmodule-level requirements. For example, even if a module interface requires that a list ofobjects be ordered, it may not specify how the ordering must be achieved (through quick-sort, merge sort, or even some other method that obviates sorting all together). Arcumallows the programmer to express these module-level semantics as static checks that arecontinually monitored during the development process, thus guaranteeing that any viola-tions would be caught when a refactoring is performed.

With these high-level contributions in mind, the following benefits accrue from the Ar-cum approach:

— Arcum provides an additional means for the programmer’s conception of the pro-gram to be expressed. Not only does this give programmers the opportunity to documentdesign decisions (and their alternatives) when a traditional modular solution is not possi-ble, it also enables automatic checking of implementations, some of which may be specificto only a small family of programs.

— The presence of a system like Arcum can change the value landscape of softwaredevelopment. Programmers can develop with advanced programming strategies such as re-flection or exotic design patterns without a permanent commitment to them. Strategies withdiffering trade-offs (such as the many dynamic/static trade-offs in Java) can be adopted orabandoned at any time by instantiating alternative options. The Arcum approach enablesthe best of both worlds: The program can be written in the more expressive form for thecurrent task, and then effortlessly transformed into the more efficient form when necessary.

— Commonly encountered design alternatives can be encoded in reusable options andinterfaces, which can be parameterized to apply to many programs. In turn, these can bemade available in the form of Arcum libraries for a particular software development group,for an entire organization, or even for the public at large. This would allow programmersat all levels of expertize to benefit from Arcum, even those who are not entirely familiarwith the details of the Arcum programming language.

Aspects of the Arcum approach have previously been published in conference and work-shop proceedings [Shonle 2007; Shonle et al. 2007; 2008a; 2008b]. This article providesa comprehensive and unified presentation of the Arcum system. Furthermore, this articlecontains the following new content:

—a formalization of the Arcum language’s syntax and semantics;—a description of new language constructs not previously published;—more complex and realistic examples expressed in Arcum, including a visitor pattern

example not previously published; and—a more in depth description of the execution engine for the Arcum language.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 5: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 5

01 public class Image {02 String altText;03 /* ... */0405 public Image(String alternative) {06 this();07 this.altText = alternative;08 }0910 public String toString() {11 if (altText == null)12 return defaultAltText();13 else14 return altText;15 }16 }

Fig. 1. A simple internal field implementation of the altText attribute.

1.3 Outline

Section 2 provides an overview of the Arcum approach and shows how constructs thatmimic modules (i.e., interfaces and options) can be practical in addressing a variety ofcrosscutting concerns. Section 3 presents a high-level description of the Arcum language.Section 4 describes Arcum’s solver, which is used for both program checks and programtransformations. To show Arcum’s breadth of applicability, Section 5 presents a case studydemonstrating Arcum’s capabilities through several examples. Section 6 describes relatedwork. Section 7 discusses possibilities for future work. Finally, we close with a fewconcluding remarks in Section 8. A formal description of Arcum’s syntax is presentedin Appendix A and a formalization of Arcum’s transformation semantics is presented inAppendix B.

2. THE ARCUM APPROACH

This section illustrates the Arcum approach with an example centered on a simple Javaprogram that processes HTML image elements. Image elements in HTML have an optional‘alt’-tag attribute that specifies alternate text to display in place of the image. There area variety of ways to implement this concept of “alternate text” in Java. For example, onecan simply add a field named altText to the Image class that represents image elements,as shown in Figure 1. Alternatively, if one expects the alternate text to often be absent(meaning that it takes on a predefined default value), then storing the alternate text in anexternal table can save memory at the expense of processor cycles. Such an implementationis shown in Figure 2.

Even this intentionally simplistic problem can show the limits of what a programmercan prepare for or anticipate. If the change to attribute storage was not anticipated, thenthe programmer’s code would already use the internal field implementation. Although thecode shown in Figure 1 has only two reads (lines 11 and 14) and one write (line 7), in arealistic codebase one would expect to encounter many references to the altText field thatneed to be modified. These references to the field may even be scattered across multiplemodules (as was the case when we looked at the Polyglot codebase in Section 2.3).

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 6: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

6 · Macneil Shonle et al.

01 public class Image {02 static Map<Image,String> altText = new IdentityHashMap<Image,String>();03 /* ... */0405 public Image(String alternative) {06 this();07 Image.altText.put(this, alternative);08 }0910 public String toString() {11 if (Image.altText.get(this) == null)12 return defaultAltText();13 else14 return Image.altText.get(this);15 }16 }

Fig. 2. Static Map implementation of the altText attribute.

Additionally, even if changes are anticipated, there are limits to how a programmer couldprepare for it. In this simple example, the factory pattern would work if the programmerwas careful, but that would only prepare the code for that specific field to be externalized.Realistically, only a relatively small number of changes to design decisions can be preparedfor in code. For example, using the factory pattern solution to prepare for both internal andexternal representations of n attributes would require 2n concrete object implementations.Ultimately, programmers make decisions that leave code unprepared for possible changes,making refactoring necessary.

The Arcum approach makes refactoring cases like the attribute example easier for pro-grammers through automation, allowing changes to be made as easily as modular substi-tution. As a result, code can be treated as if it were prepared for many combinations ofpossible changes; that is, the benefits of modular substitution can be extended to cases thatwould otherwise require complex sequences of refactoring operations. To compare refac-toring with and without Arcum, we describe how a developer would refactor a large bodyof code from the internal field implementation of the “alternate text” concept to the staticMap implementation, first using a regular IDE such as Eclipse (Section 2.1), and then usingthe Arcum framework (Section 2.2).

2.1 Refactoring using Eclipse

A developer could use Eclipse’s built-in refactorings in the following way to transform thecode in Figure 1 into the code in Figure 2: (1) Replace all references to the altText fieldin the original code with calls to getter and setter methods with the ‘Encapsulate Field’refactoring; (2) Manually edit these getter and setter methods to call the appropriate Mapoperations instead; And, optionally, (3) inline the calls to the getter and setter methods withthe ‘Inline Method’ refactoring.

Although these built-in refactorings make manual modification less onerous, the prob-lem remains the same: refactorings generally require many changes to be made to thecode, and the tool performing the transformations is simply not aware of the conceptspresent in the code being manipulated. Refactoring without conceptual-awareness resultsACM Journal Name, Vol. V, No. N, Month 20YY.

Page 7: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 7

Fig. 3. Refactoring in Arcum for Eclipse. The front-most window is a preview of the refactoring to be per-formed. In the background is Eclipse, with an Arcum view at the bottom that shows a compressed view of theimplementation’s scattered code fragments.

check {InternalStorage(targetType: Image, attrType: String, attrName: altText);

}

Fig. 4. Mapping for the original InternalStorage implementation of the altText attribute.

in a variety of drawbacks, including: (1) The application of a sequence of refactoringsteps and manual edits is error-prone and tedious—it is error-prone, for example, becausethe manual editing of the getter and setter methods by the programmer occurs outsideof Eclipse’s meaning-preserving operations; (2) It is often difficult to switch betweenthe original implementation to the refactored implementation; (3) The programmer caninadvertently introduce subtle bugs: for example, transforming f(this.altText = y)into f(Image.altText.put(this, y)) is an incorrect transformation because the putmethod returns the previous value in the Map; And, (4) little of the work done for refactor-ing the altText field can be reused for refactoring other fields.

2.2 Refactoring using Arcum

The Arcum approach addresses the above limitations by enabling programmers to formallycapture concepts in their code. Rather than directly applying refactoring transformations,an Arcum programmer first declares behavior (in the interface) and implementation de-scriptions (in the options) for the code that will be changed. After the options and theirinterface have been described, the prevailing implementation can be replaced by any otherrelated option. By default, the chosen option is retained and continues to impose checks

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 8: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

8 · Macneil Shonle et al.

every time the program is compiled, to ensure that new or modified code also satisfies thetransformation’s pre- and post-conditions.

Options and interfaces can be parameterized so that they can be reused by other pro-grammers and applied to a wide variety of programs. Arcum’s user interface is a simpleextension to the Eclipse IDE, allowing refactorings like “externalize storage” to be ap-plied easily in different contexts (see Figure 3). Arcum refactorings can be invoked bythe user through context menus associated with the user’s mapping. A mapping specifiesconcrete arguments for an option’s parameterizations. Figure 4 shows a mapping for theInternalStorage option to be the current implementation of the AttributeInterface.

Figure 5 shows how the Image constructor from the example is transformed with Arcum.At the bottom left of the figure is the original Java code for the constructor, and at thebottom right is the desired target Java code. At the top of the figure is the Arcum codespecifying the interface that both options implement. The declarations of the two optionsare directly below the interface: one using an internal field (the InternalStorage option),and another using a static Map (the ExternalStorage option).

Note that rather than designing a refactoring that applies only to the “attribute for alter-nate text” concept, the programmer has designed a parameterized interface so that it canbe applied to any attribute of any class. In particular, the AttributeInterface from Fig-ure 5 takes three parameters: targetType is the class for which the attribute is defined,attrType is the type of the attribute, and attrName is its name. The goal of parameteriz-ing options is to make the options available for later reuse, rather than having to implementthem from scratch.

The relevant part of the AttributeInterface code for this example is the attrSetconcept (Figure 5, boxed), which represents all locations in the Java program where theattribute’s value is set. The members of the concept, in this case setExpr, targetExprand valExpr, are fragments of Java code that are extracted from the locations in the codewhere the attribute is set. For example, targetExpr is the object whose attribute is be-ing set, valExpr is the value that the attribute is being set to, and setExpr is the entireexpression that performs the set operation. Arcum variables, such as setExpr, keep trackof the source code location of the code fragment they represent. So, in this example, thesetExpr variable identifies the location and scope of the set operation, which is later usedto determine what portion of the code gets transformed or preserved.

Each option specifies a different implementation of the attrSet concept. An abstractconcept is implemented by an option when it provides a pattern that identifies the frag-ments of Java code that are instances of the concept. For example, the pattern in theInternalStorage option (boxed) shows how a regular assignment to a field becomes aninstance of the attrSet concept:

setExpr == [‘targetExpr.‘field = ‘val];

In the Image constructor example (Figure 1), line 7 of the Java code matches this pattern,and therefore becomes an instance of the concept. Similarly, the boxed pattern in theExternalStorage option states which Map operations become instances of the attrSetconcept.

Arcum patterns declaratively state the association between a crosscutting concept andthe various fragments of Java code that implement an option. A key feature of Arcum isthat these associations are bi-directional: Not only are the patterns used to build conceptinstances from Java code, but they are also used in the other direction, to generate JavaACM Journal Name, Vol. V, No. N, Month 20YY.

Page 9: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 9

...

05 public Image(String alternative) {

06 this();

07 Image.altText.put( this , alternative );

08 }

Transformed Program

option ExternalStorage implements AttributeInterface {

match Field mapField, Type mapType, Expr mapInit,

AccessSpecifier spec {

mapType == [java.util.Map<`targetType, `attrType>]

&& mapInit == [new WIHashMap<`targetType,`attrType>()]

&& mapField == [static `spec `mapType `attrName = `mapInit]

&& hasField(targetType, mapField)

} onfail {"Must have a map named `attrName", targetType}

match attrGet(Expr getExpr, Expr targetExpr) {

getExpr == [`targetType.`mapField.get(`targetExpr)]

}

match attrSet(Expr setExpr, Expr targetExpr, Expr val) {

setExpr == [`targetType.`mapField.put(`targetExpr, `val)]

}

}

interface AttributeInterface(Type targetType : isClass(targetType),

Type attrType : isReferenceType(attrType),

Name attrName : isSimpleName(attrName)) {

abstract attrGet(Expr getExpr, Expr targetExpr) {

check {isA(getExpr, attrType) && isA(targetExpr, targetType)}

check "The value of `getExpr must be used" {!isExpressionStatement(getExpr)}

}

abstract attrSet(Expr setExpr, Expr targetExpr, Expr val) {

check {isA(targetExpr, targetType) && isA(val, attrType)}

check "The value of `setExpr cannot be accessed" {isExpressionStatement(setExpr)}

}

abstract AccessSpecifier spec;

}

Pattern Matching

Concept Mapping Concept Remapping

Node Generation

...

05 public Image(String alternative) {

06 this();

07 this . altText = alternative ;

08 }

Original Program

option InternalStorage implements AttributeInterface {

match Field field, AccessSpecifier spec {

field == ([transient `spec `attrType `attrName]

|| [`spec `attrType `attrName])

&& hasField(targetType, field)

&& (isA(targetType, <java.io.Serializable>)

<=> isTransient(field))

} onfail {"Must have a field named `attrName", targetType}

match attrGet(Expr getExpr, Expr targetExpr) {

getExpr == [`targetExpr.`field]

}

match attrSet(Expr setExpr, Expr targetExpr, Expr val) {

setExpr == [`targetExpr.`field = `val];

}

}

Fig. 5. Overview of how Arcum transforms code into an alternative implementation. By changing the map-ping, which describes the current option deployed, the code is automatically transformed in accordance with thesubstituted option.

code from concept instances.The directionality of the association is determined by how the mapping is instantiated

and later changed. As declared in Figure 4, the InternalStorage implementation is theprevailing option at the beginning of the scenario. To refactor to the sparse implementa-tion of the altText field, the programmer changes the named option in the mapping toExternalStorage, which triggers a refactoring of the code.

In the scenario, the altText field is initially implemented as a simple class field andthe conceptual flow of information in Figure 5 goes in the clockwise direction, followingthe direction of the arrows. For example, the field assignment on line 7 in the originalcode is pattern matched into a concept instance, at which point the references setExpr,targetExpr and valExpr are bound. The newly constructed concept instance is lifted tothe interface level, and then pushed back down to the alternate ExternalStorage option,at which point the pattern along with setExpr, targetExpr and valExpr, are used toconstruct the replacement code.

Due to the bi-directional nature of patterns, the mapping can be changed later to per-form the refactoring in the other direction. Because our approach explicitly and persis-tently identifies substitutable crosscutting concepts and their prevailing options, their con-sistency properties can be continuously checked. This makes future transformations easierto perform because the checking aids code compliance. For example, as mentioned previ-

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 10: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

10 · Macneil Shonle et al.

ously, a programmer would like to prevent the incorrect application of the refactoring totransform f(this.altText=y) into f(Image.altText.put(this,y)), because the putmethod returns the previous value in the Map. This requirement is checked by the interfacein Figure 5 with the check clause (where isExpressionStatement(e) tests whether theexpression e is used directly as a statement).

The predicates in check clauses are checked continuously, to make sure that developersdon’t accidentally change code in a way that prevents the crosscutting concept from beingtransformed. When such a check fails on a program fragment, the developer will see thefragment highlighted as a compile-time error (similar to type errors in Java), with a relevantmessage. The developer can then decide to either change the program fragment to make itpass the check, or to change the mapping itself that caused Arcum to perform the check.Under some circumstances, the developer may realize an alternative mapping needs to beemployed instead. Overall, the purpose of continuous checking is just like type checking:to ensure that code conforms to the developer’s stated intentions.

Much of the power of the Arcum approach arises from the fact that its transformationsare focused on preserving the requirements as asserted in the interface, rather than pre-serving every detail of language-semantics-level behavior. We still call this refactoring,because the programmer’s intent is that an Arcum interface specifies the important behav-iors that need to be preserved during transformation to another implementation.

2.3 Application of AttributeInterface

We applied our AttributeInterface Arcum code to the Polyglot extensible compilerframework [Nystrom et al. 2003], which uses advanced design idioms that could benefitfrom management by Arcum. To support extension, the Node class in Polyglot has twofields: del and ext. Based on their infrequent usage on a per-object basis, a sparse repre-sentation of these fields could conserve memory usage.

We first instantiated the InternalStorage option on these fields to recognize theircurrent implementation, and then externalized them by updating the mappings to use theExternalStorage option, resulting in 13 and 12 substitutions, respectively. The net sav-ings in memory was small for several test runs, about 10%, so we reverted the changesimply by reverting the two mappings to use the InternalStorage option again.

In general, Arcum can be used in this way for experimentation. In particular, one mightexternalize a field, to see if it actually saves memory on test executions and then perhapsonly much later (after several other changes to the system are made, some of which affecthow often such objects are instantiated) change it back. This kind of exploration would nothave been easy in Eclipse alone, as discussed in Section 2.1. These benefits are somethingprogrammers are already accustomed to: it is the benefit of modular substitution.

2.4 Arcum’s Role in the Programming Process

Although Arcum adds another layer on top of their Java code, which adds to what theprogrammer must manage, this layer can be beneficial to the development process. Forexample, the Eclipse IDE is a tool that the programmer must manage, but it providesmultiple benefits, such as automated refactoring. For common crosscutting concepts, suchas the visitor example, reusable Arcum libraries of interfaces and options can be accessedas commands in the IDE, as black boxes. Thus, programmers do not necessarily need tounderstand the details of the Arcum language to benefit from it.

When a programmer writes Arcum code directly, there is a learning curve, and the pro-ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 11: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 11

grammer must become familiar with concepts like pattern matching and predicate logic.However, the programmer is not additionally burdened by thinking at a higher level ofabstraction (at the conceptual level) because it is likely that the programmer is alreadyconceptualizing their program at that level. Thus, Arcum can be a means for programmersto explicitly encode their view of the crosscutting concerns that occur in their programs.

When used in a software development team, not all programmers need to become famil-iar with Arcum’s language. It is feasible for a handful of developers to write Arcum code,becoming in essence the Arcum power users for the entire project, and providing Arcumlibraries that the other developers can use as black boxes, without understanding how theywork.

A program developed with Arcum can fit naturally in existing development processes,because Arcum’s options and interfaces are purely supplemental, and do not change thesemantics of the program, which remains in pure Java. As a result, executions of theprogram and the debugging of it are unchanged, allowing Arcum to fit in with existingenvironments, tools, and techniques.

However, there are some cases where changes to Java code can affect Arcum code. Forexample, if a program check is written broadly, it is likely that changes to the code canrequire changes to the Arcum code, either by changing a parameter in a mapping, or bychanging the check itself in the Arcum option or interface. In the presence of crosscutting,it is all the more important to have tool assistance for checks to make developers moreaware of other affected design decisions in the program.

3. THE ARCUM LANGUAGE

The key construct of the Arcum language is the concept, which describes a collection ofJava code fragments (Section 3.1). All Arcum code appears in an interface, an option, or amapping. An interface (3.2) specifies the names and types of the concepts common to alloptions that implement the interface. An option (3.3) provides concrete definitions of theconcepts in the interface by using patterns. Finally, a mapping (3.4) allows options to beparameterized for a particular application.

3.1 The Concept Construct

A concept is used to describe one distinct role, structure, or operation that occurs in thecontext of a complete crosscutting concept’s implementation (a similar construct is referredto as a sub-concept by Kozaczynski et al. [1992]). A concept can either represent a singleprogram fragment or a set of tuples of program fragments. Concepts can be associatedwith conditions that allow optional user-readable error messages to describe what codewas expected.

The AttributeInterface in Figure 5 specifies three abstract concepts: attrGet,attrSet, and accessSpecifier. Because an Arcum interface is abstract, its conceptsmust be too. A concept’s name, tuple member types, check clauses, optional errormessages, and a partial specification may be specified in an interface. These abstractconcepts are given concrete definitions via patterns specified in the options that implementits interface. Any partial specifications provided at the interface level are conjoined withthe complete specification at the option level, which helps prevent code duplication forcommon restrictions. The attrGet and attrSet concepts represent, respectively, theabstract operations of getting and setting the attribute, where both operations can occur inthe program multiple times.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 12: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

12 · Macneil Shonle et al.

Table I. Example built-in predicates.

Predicate Name Description

isA(t1, t2) Is type t1 equal to or a subtype of type t2?hasMethod(c, m) Does class c have a method m?isTransient( f ) Is field f declared as transient?isReferenceType(t) Is type t a reference type?isExpressionStatement(e) Is expression e the contents of a statement?

Each concept tuple has a root program fragment, of which all other members in the tupleare sub-members. In syntactic terms, the root program fragment is an AST node that is di-rectly or indirectly the parent of all other AST nodes in the tuple. For example, the attrSetconcept has three tuple members, each of which are expressions: setExpr, targetExpr,and valExpr. The targetExpr is the expression whose value is the object that has theattribute and valExpr is the new value for the attribute. Both are sub-expressions ofsetExpr. The root program fragment must be the first variable in a concept’s memberlist, and is treated like a placeholder, or program location, when subject to transformations(see Section B.2 for more details).

When a concept’s root fragment is an expression or statement it represents an opera-tion. But concepts can also express structural properties of code and other crosscuttingforms. For example, one could declare a concept that represents “all declarations of typeVector.” Such a concept would be useful for porting from one library to another (forexample, changing uses of the Vector collection class to the newer ArrayList class, asdone by Balaban et al. [2005]). Structural examples of concepts include methods, fields,and annotations.

3.1.1 The Check Clause. Programmers can add conditions with error messages to aconcept. For example, the abstract attrGet concept from Figure 5 declares:

check "The value of ‘getExpr must be used" {!isExpressionStatement(getExpr)

}

The above check tests that the expression specified by getExpr cannot have its valuediscarded. The error message in the programming environment is associated with the rootprogram fragment. Other fragments mentioned in the text of the message (escaped with abacktick “‘”) can help focus the user’s attention to the specific cause of the problem.

In general, the Boolean condition provided in a check clause is evaluated for each con-cept instance. Conditions are expressed using a simple propositional logic, augmentedwith built-in primitives, examples of which are shown in Table I. A check clause’s errormessage is optional, to provide a compile-time error message to the user in the event thatthe condition cannot be satisfied. When an error message is not specified a default errormessage describes the condition that failed.

3.1.2 Interface Parameters. An interface’s parameters are specified in the map-ping instead of by the options that implement the interface. Parameters are typicallyrequired for an Arcum interface declaration to be instantiated for multiple uses. TheAttributeInterface in Figure 5 has three parameters: a Class named targetType (theclass that has the attribute), a Type named attributeType (the type of the attribute), andACM Journal Name, Vol. V, No. N, Month 20YY.

Page 13: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 13

a String named attrName (the name of the attribute). This parameterization permits theAttributeInterface to be applied to several different attributes instead of, for example,being hard-coded only for Strings in the Image class.

The type of the parameter tuple in this example demonstrates how interface propertiesmust hold for all options. Because the InternalStorage option assumes a field can beadded to the targetType it must assume the targetType is a Java class and not a Javainterface, and thus all other options must make the same assumption as well. This is anexample of how the interface must accept the least common denominator—an essentialproperty of modular substitution in general.

3.2 The Interface Declaration

An Arcum interface declares, at the behavioral level, what is common to all of its imple-menting options. The interface’s primary purpose is to document the crosscutting concept’sinterface and to centrally specify requirements that apply equally to all options that imple-ment it.

Concepts specified in the Arcum interface are abstract and all concepts must be con-cretely implemented by the options that implement the interface.

The abstract spec concept in Figure 5 represents a single program fragment, of typeAccessSpecifier. This concept is used by the AttributeInterface to simplify theinterface’s parameters list. Instances of the AccessSpecifier type specify one of themodifiers private, public, protected or the implicit “package” modifier. Both theInternalStorage and ExternalStorage options infer this specifier by defining it to bethe access specifier of the field named attrName. This same kind of inference can be usedto remove the attrType member from the parameters list as well. The decision on whetherto let a program fragment be a parameter or an inferred concept depends on the current andexpected options that the interface will modularize. For example, it may always be safe toassume that the spec can be inferred but not safe to assume that the attrType can alwaysbe inferred—for instance, an implementation that did not use the Java 5 generic Map classwould not have this type information available in the Java source code, and thus wouldhave to be specified in the Arcum mapping.

3.3 The Option Declaration

An option describes one complete implementation of a crosscutting concept specified byan Arcum interface. Options use the implements keyword to specify which interface theyimplement. Unlike classes, an option can only implement one interface. The constructsused to implement options are patterns and invariant condition checks.

3.3.1 Patterns. Options specify the implementation of concepts using declarative pat-terns, which are used to both identify and construct program fragments. Patterns are ex-pressed as Java-like pseudo-code inside square brackets, with backtick marks to identifyArcum variables inside the pseudo-code. For example, the InternalStorage option inFigure 5 uses the following pattern to match (or generate) expressions representing the setoperation:

match attrSet(Expr setExpr, Expr targetExpr, Expr valExpr) {setExpr == [‘targetExpr.‘field = ‘valExpr]

}

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 14: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

14 · Macneil Shonle et al.

The pattern in the square brackets ([. . .]s) is matched against the entire program underanalysis, and produces bindings for setExpr for all matches found. Arcum supports pat-terns to match different kinds of Java program fragments. The algorithms that use patternsfor matching and for generating new AST nodes are discussed in Section 4.2. An Arcumvariable can be associated with either a single pattern expression or a union of severalpattern expressions (combined with the ||-operator).

Patterns can also appear in angle brackets (<. . .>s), as also found in the InternalStor-age option in Figure 5:

isA(targetType, <java.io.Serializable>)

When angle brackets are used, the pattern is not used for pattern matching against theprogram. Instead, the pattern is used literally, as a way to quote Java code. For example,Java type names are referenced using these literal quotes.

An option can match program fragments that are option-local; that is, specific to theimplementation of a single option. For example, a concept in the InternalStorage optionin Figure 5 has the single member field:

match Field field, AccessSpecifier spec {field == ([transient ‘spec ‘attrType ‘attrName]

|| [‘spec ‘attrType ‘attrName])/* ... */

}

Because the field concept is option-local, this field does not have to be present in any ofthe alternative options. Here, a union pattern is used to reflect that the transient modifiermay or may not be present; Section 4.2.2 discusses how Arcum determines which patternto use for code generation.

The program fragments matched by abstract concepts can be considered an instanceof homogeneous crosscutting, where the information that is scattered fits a general pat-tern [Colyer and Clement 2004]. In contrast, some option-local program fragments areexamples of heterogeneous crosscutting, where an option’s implementation may requireprecise but context-dependent infrastructure that is scattered over the program.

3.3.2 Invariant Condition Checks. During the development of an option, it may benecessary for additional requirements to be placed on the abstract concept to which it isrelated, in order to preserve substitutability. For example, consider the field access patternshown in Figure 5 for InternalStorage’s implementation of the attrGet concept. IfFigure 5 didn’t contain contains checks for the attrGet concept at the abstract conceptlevel (in the interface), and a programmer added such checks to attrGet the option level,then the interface will be required to contain those checks too.

For example, if the option writer had added the following check clause inside the patternmatching construct:

match attrGet(getExpr, targetExpr) {getExpr == [‘targetExpr.‘field]

check {isA(getExpr, attrType) && isA(targetExpr, targetType)

}

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 15: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 15

}

Here, Arcum would generate a compile-time error, because the restrictions on the typesof getExpr and targetExpr must be applied to all options, in order to guarantee bi-directionality of transformations. To fix the error, the developer must move the checks upto the interface level.

An option writer may implicitly add similar checks during option development. For ex-ample, Java does not allow a field access to be a statement, and so the expression statement:

this.altText;

would be rejected by by the Java compiler. Thus, whenever field access expressions areused, there is an additional requirement that the expression not be a statement. By forcing a!isExpressionStatement check to be added to the interface, substitutability is preservedfor alternate options. For example, the expression statement:

Image.altText.get(this);

is accepted by the Java compiler, even though accessing a value and ignoring it would bemeaningless to the concept itself. By forcing the !isExpressionStatement requirementto hold over all options, errors such as the latter are prevented from being inadvertentlywritten. Thus, emergent conditions that arise in the development of a concept and itsoptions can show the developer when new requirements must be added to the interface.

3.4 Mappings

Arcum mappings are used to state which options are implemented in a program. Figure 4shows a sample Arcum mapping. In general, an Arcum mapping is a list of option instan-tiations, where each instantiation states the option’s name, and a set of bindings for all ofthe option’s parameters.

One benefit of the mapping format is that there is a separate file that documents someof the architecture of the program and the design decisions made. Such a record providesprogrammers with a different view into the decision space of the program: When changesneed to be considered, the list of mappings shows the decisions made, and thus providesinsight into the possible alternatives to consider.

4. THE ARCUM SOLVER

In this section, we present the techniques used to design and implement the Arcum Solver.The goal of the Arcum Solver is two-fold: first, it must solve the declarative match predi-cates in the Arcum code to find all concept instances in a given piece of Java code; second,it must perform the transformations required to switch from one option to another. Manytools have previously been designed for tasks similar to Arcum, including program querytools (such as JunGL [Verbaere et al. 2006], QL [Moor et al. 2007] and PQL [Martin et al.2005]), and program analysis/transformation engines [Lacey et al. 2002; Sittampalam et al.2004; Bravenboer et al. 2008; Lerner et al. 2005], some of which are even based on dat-alog [Reps 1994; Whaley and Lam 2004; Whaley et al. 2005]. Not surprisingly then,parts of the Arcum Solver build upon these previous techniques. In particular, the mono-tonic fixed-point solver used to find concept instances (described in Section 4.1) followsclosely the techniques from the Rhodium system [Lerner et al. 2005] used to run declara-tive dataflow analyses, and it also borrows the idea of stratified negation from Datalog andProlog [Abiteboul et al. 1995].

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 16: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

16 · Macneil Shonle et al.

Our solver is also unique in that Arcum uses the pattern predicate language not just tofind matches in a program, but also to generate code for the target option being transformedto. In particular, our transformation engine (described in Section 4.2) uses a generate-and-test approach to find a transformed program that also matches the target pattern.

We now describe both the fixed-point solver used to find all option instances (Sec-tion 4.1) and the Arcum transformation engine (Section 4.2). The fixed-point solver andthe transformation engine are both implemented using 19,000 lines of Java code as a plug-in for the Eclipse IDE. They are built on top of Eclipse’s Java Development Tools plug-in,and thus use the Language Toolkit API to manipulate Java ASTs. Whereas our descriptionof the fixed-point solver is high-level and informal in nature, a formal treatment of theArcum semantics can be found in Appendix B.

4.1 Monotonic Fixed-Point Solver

The Arcum solver for predicates is used to find all instances of concepts in a piece ofJava code. To this end, it must find all predicates that hold in the program, namely allmatch clauses that hold (such as the one for attrSet in Figure 5), and all define clausesthat hold (such as the one for hasA in Figure 6). The solver does this using a standarditerative fixed-point computation, as described in the dataflow analysis literature [Cousotand Cousot 1977; 1979], that starts with no predicates holding, and then adds predicates asthey are determined to hold, until no more predicates can be found to hold.

The Arcum solver for predicates guarantees termination by requiring a strict monotonic-ity requirement: At each step of the evaluation, the set of tuples of program elements thatbelong to a predicate is unioned with a set of new tuples. The solver terminates once afixed-point is found; i.e., when the existing set does not change after a complete iteration.Once a tuple is added to the set, it will always be a member. Thus, the solver alwaysreaches a fixed-point because the size of the set is bounded by the number of elements inthe n-ary crossproduct of all program fragments, where n is the number of members ofeach tuple.

Predicates defined in Arcum can be (mutually) recursive. Figure 6 is an example withtwo mutually defined relations: The hasA relation depends on itself and hasAListOf, andhasAListOf depends on hasA. The directlyHasA relation is not recursive and dependsonly on the built-in relations: hasField, isStatic, and isA.

The case of solving the directlyHasA is the simplest: Initially, the set of tuples for thedirectlyHasA(t, u) relation is empty, with no bindings for any t or u. The fixed-pointsolver runs through the following steps to try to satisfy the expression (a conjunction ofthree subexpressions):

hasField(t, field?) && !isStatic(field) && isA(field, u)

(1) hasField(t, field?): Because hasField is a built-in relation (and defined accordingto the compiled program) every solution for t and field are returned as results. Thenotation “field?” declares a new binding for field.

(2) !isStatic(field): For the next conjunct, since there are already bindings for field,solving the conjunct acts as a filter (filtering out static fields).

(3) isA(field, u): Given this potentially shorter list of bindings for field (and the asso-ciated bindings for t), the last conjunct is solved. From the built-in predicate isA, thesolver can determine all the u’s corresponding to the fields.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 17: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 17

define hasA(Type t, Type u) {directlyHasA(t, u)|| hasAListOf(t, u)|| (hasA(t, v?) && isSubtypeOf(v, u))

}

define directlyHasA(Type t, Type u) {hasField(t, field?) && !isStatic(field) && isA(field, u)

}

define hasAListOf(Type t, Type u) {exists (Type v : hasA(t, v)) {

v == <‘u[]> || (isA(c?, <Collection>) && v == <‘c<‘u> >)}

}

Fig. 6. The hasA relation: Defined in terms of itself, directlyHasA and hasAListOf, where hasAListOf isdefined in terms hasA.

(4) Finally, a projection of the tuples (t, field, u) is taken, keeping only t and u.

Because the set of predicates that directlyHasA depends on are all solved (that is,the set cannot gain new elements, since every candidate in the finite program has beenexhausted), the solution arrived at after this first iteration of the algorithm is the completesolution, and the predicate can be marked as solved.

If the first two conjuncts in the above expression were swapped, forming:

!isStatic(field?) && hasField(t, field) && isA(field, u)

then the evaluation process is similar, but potentially longer to evaluate, because the fieldis implicitly bound to every field in the program, before the !isStatic(field?) filter isapplied.

Next in the process is the solution of the hasA and hasAListOf predicates. Becausethese two predicates are mutually dependent, the iterations of their solution must be inter-leaved until the contents of their solution sets don’t change.

Because the fixed-point solver starts with the empty set as a solution, and then buildsthe set up, monotonically increasing its size, programmers must be careful in how decla-rations are solved. For example, consider a doesNotPrint(m) predicate, which holds fora method m if m does not make any PrintStream calls and also doesn’t call any meth-ods that directly or indirectly make PrintStream calls. Figure 7 is one attempt at codingthis predicate. On the first iteration of the solver, the set is empty and thus the conjunctdoesNotPrint(n) on line 3 will not find any solutions for n. As a result, no methods msatisfying the predicate will be found.

The problem with this attempted solution is that its base-case (the solution after the firstiteration) does not contain instances that would satisfy a final solution. To resolve thisissue, the solution must be conceived in terms of starting with known good solutions andbuilding the set up from there. Figure 8 shows one such resolution: define mayPrint first,and then define doesNotPrint as its negation. The mayPrint predicate works becauseunder its base-case it collects all methods m that invoke a PrintStream method. Underthe next iteration, it collects all methods m that call those methods, and so on, until a fixed-

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 18: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

18 · Macneil Shonle et al.

01 define doesNotPrint(Method m) {02 forall (Method n : invokes(m, n)) {03 !hasSignature(<java.io.PrintStream>, n) && doesNotPrint(n)04 }05 }

Fig. 7. A broken specification for the doesNotPrint predicate. The predicate is intended to be true when methodm performs a printing operation or makes a call to another method that does.

01 define mayPrint(Method m) {02 exists (Method n : invokes(m, n)) {03 hasSignature(<java.io.PrintStream>, n)04 || mayPrint(n)05 }06 }0708 define doesNotPrint(Method m) {09 !mayPrint(m)10 }

Fig. 8. A correct specification for the doesNotPrint predicate.

point is reached. Once the mayPrint predicate is solved, it is simply a matter of writingits negation (on lines 8–10).

During evaluation of predicates, if the Arcum solver encounters a pattern variable like mthat is not yet bound to any values, then the solver must iterate over all possible instancethat m could range over. For example, if m is declared as a Method, then the solver wouldhave to iterate over all possible methods. In general, this can cause an explosion in thenumber of cases to explore: if there is another variable n ranging over methods, and n isnot yet bound to any values, then the solver must iterate over all pairs m, n of methods.We have successfully mitigated this problem by simply placing predicates that constrainvariables like m and n as early as possible in the predicates (i.e.: closer to the beginning ofthe predicate), so that when the solver evaluates predicates, the variables get constrainedearly, thus pruning the search space early.

The doesNotPrint example illustrates an important point about Arcum’s computationalmodel: Arcum allows programmers to directly write so-called “may analyses,” not “mustanalyses”—a “must” analysis must be written as the negation of a “may not.” This is ex-actly what happened with doesNotPrint: “must (not print)” was converted to the negationof “may not (not print),” that is to say the negation of “may print.”

There are however some subtleties when dealing with negation and the interactionof may/must analyses. In particular, if a predicate depends on another predicate via anegated clause, there is the potential for incorrect results to be added to the solution setbecause the intermediate solution is incomplete. For example, suppose that mayPrint anddoesNotPrint in Figure 8 are solved simultaneously: Then the mayPrint solution willbe correct, but the doesNotPrint solution will end up with the set of all methods.

This issue with negation is well-known in the logic databases community and the logicprogramming community. To address this problem, we adapt a standard solution calledACM Journal Name, Vol. V, No. N, Month 20YY.

Page 19: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 19

stratified negation [Abiteboul et al. 1995]. In particular, we compute the dependency graphbetween predicates, recording for each dependency whether the dependency is positive ornegative: a positive dependency between relation A and relation B indicates that B occursin the formula for A in a positive (i.e.: non-negated) position; a negative dependency be-tween A and B indicates B occurs in A in a negative (i.e.: negated) position. We solve eachstrongly connected component (SCC) in the dependency graph at once, so that mutuallydependent relations are iterated to a fixed-point simultaneously. Furthermore, we rejectArcum programs that have any negative dependencies in a cycle, which essentially guar-antees that negative dependencies (i.e. negations) can only occur between SCCs, ratherthan inside them. This stratification of the solver allows us to safely solve may and mustproblems using the same solver, while still allowing negation to be used in Arcum.

4.2 Transformation Algorithm

The Arcum transformation algorithm takes code that implements a source option and trans-lates it to new code that implements a destination option. The following process performssuch a transformation:

(1) Use the patterns specified in the source option to bind option-local concepts and ab-stract concepts. The pattern matching identifies the program fragments, representedas AST nodes, that participate in the refactoring.

(2) Perform all option-specific and interface-level constraint checks, and stop with an errorif any of the checks fail.

(3) Remove from the program all AST nodes that were pattern matched into the sourceoption’s local concepts. For example, when refactoring from the InternalStorageoption to the ExternalStorage option in Figure 5, the altText field gets removedfrom the program because its AST node was pattern matched into an option-local con-cept. AST nodes that match into option-local concept are removed during transfor-mation because by design these concepts are option-specific—otherwise, the conceptswould be abstract and specified at the interface-level.

(4) Construct new AST nodes using the patterns from the destination option’s local con-cepts and insert them into the program. In the refactoring scenario from Figure 5, theconcept mapField in the ExternalStorage option will add a declaration of a staticMap to the program.

(5) Replace each concept instance with a new AST node generated from the destinationoption’s patterns; construct the new AST node such that it satisfies the destinationoption’s constraints (if present).

The main challenge in the above algorithm lies in processing patterns both to performpattern matching (in step 1), and to generate new AST nodes (in steps 4 and 5). These twouses of patterns are described in Section 4.2.1 and Section 4.2.2, respectively.

4.2.1 Pattern Matching. Arcum patterns are represented using ASTs that can havevariable nodes for sub-trees in addition to concrete AST nodes. A standard unificationroutine is used to perform the pattern matching. The concrete syntax of the program iscanonicalized before the matching is performed, so that operations are closer to their se-mantic meaning. For instance, even though the pattern

setExpr == [‘targetExpr.‘field = ‘valExpr]

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 20: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

20 · Macneil Shonle et al.

uses the “dot” notation, it will also match program fragments that use the implicit this(without the dot).

One practical consideration in implementing the pattern matcher is that parsing of squarebrackets is greatly simplified if one knows the kind of expression in the square brackets(i.e.: statement vs. expression vs. field declaration). In the above case, for example, thetype of setExpr is an Expr, and thus the code in the brackets is parsed as a Java expression.Thus, to simplify our implementation, we require that all uses of the unification operator(‘==’) have an Arcum variable on the left-hand side. To unify two program fragmentpatterns, an intermediate variable (for example, one created from an exists clause) mustbe introduced.

4.2.2 Node Generation. One of the key features of Arcum is that patterns are bi-directional: not only are they used for matching Java code fragments into concept in-stances, but they are also used in the other direction, to generate Java code fragments fromconcept instances. As an example, the following pattern in the ExternalStorage optionis used in the refactoring scenario (from Figure 5) to insert a call to the put method of thestatic map:

setExpr == [‘targetType.‘mapField.put(‘targetExpr, ‘valExpr)]

A concept instance and a destination pattern generate an AST node by taking the par-tially specified AST representing the pattern, and inserting into it the values of the Arcumvariables from the concept instance. Because Arcum variables store references to programfragments the above pattern creates an AST node representing the call to put, and theequality (==) makes the newly created AST at the location in the program specified bysetExpr.

For some patterns, there are multiple possible AST nodes that could be generated.For example, the field pattern shown in Figure 5 shows two possibilities for the field-declaration, where either the transient modifier is present or not:

field == ([transient ‘spec ‘attrType ‘attrName]|| [‘spec ‘attrType ‘attrName])

&& hasField(targetType, field)&& (isA(targetType, <java.io.Serializable>)

<=> isTransient(field))

Its conjoined constraint specifies when the field should be transient: the field must betransient exactly when the targetType class implements the Serializable interface:

isA(targetType, <java.io.Serializable>) <=> isTransient(field)

Here, the <=> represents the logical if and only if operator. When there are multiple pos-sible AST nodes that could be generated from a pattern or union of patterns, the Arcumsystem uses a generate-and-test approach: we generate all of the possible AST nodes, andthen use the conjoined constraints to prune nodes out. This approach works well as longas there are a small number of possible AST nodes to generate. In the above example, Ar-cum would generate both field-declarations: one with the modifier and one without. Theevaluation of the constraint determines which of the two AST nodes to use.

The replacement algorithm uses a top-down ordering to replace nodes once they havebeen generated, to allow for sub-nodes of concepts to be replaced by other concepts. Byusing this top-down order, Arcum is able to correctly transform:ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 21: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 21

anImage.altText = defaultImage.altText;

into:

altText.put(anImage, altText.get(defaultImage));

5. CASE STUDY

This section presents a case study of Arcum’s use on a variety of classical software en-gineering problems that are induced by crosscutting. Although some examples were ad-dressed in Arcum’s own code base, we believe each such examples provides a plausibledemonstration of how crosscutting manifests itself in real-life programs. Other examplescovered in this section were inspired by design patterns and other commonly known in-stances of crosscutting. For each example, we describe how the problems associated withcrosscutting can be mitigated using Arcum. Each category of software engineering prob-lem covered has a working example developed and tested against the code base.

We start with a detailed description of two variants of the familiar visitor design pattern,and show how these different implementations provide different views into the programand how unexpected complications can be addressed with a tool like Arcum (Section 5.1).

Next, we address the process of debugging as a programming task that requires reason-ing over crosscutting code, which sometimes results in making crosscutting changes to fixthe bug or to identify its root cause (Section 5.2).

Then, we explore the category of software engineering problems related to code migra-tion and the trade-offs between making a program’s implementation more standardized ormore project-specific (Section 5.3).

Next, we show how Arcum can be used to perform tasks that programmers typicallythink of as find-and-replace, but that cannot be performed easily or completely in a texteditor or even in an IDE like Eclipse (Section 5.4).

Finally, we discusses some of the common issues we came across and lessons learnedwhile developing our Arcum code (Section 5.5).

5.1 The Visitor Pattern

The first part of our case study is an extensive example showing how Arcum can be used tocapture the visitor pattern [Gamma et al. 1995], and improve the ability to comprehend andevolve implementations of this pattern. We chose the visitor pattern because it has manyinteresting variants, including complex code transformations that go far beyond transform-ing one statement to another. In particular, it is possible to use Arcum to elide hundreds oflines of code of traversal-related infrastructure (which includes methods and interfaces) byinstead making a call that uses a reflection library.

Section 5.1.1 provides a description of the visitor pattern with a simple, but complete,example. Section 5.1.2 details how the visitor pattern can be understood at a higher con-ceptual level, which forms the foundation of an Arcum interface for the visitor pattern.Section 5.1.3 presents an encoding of the traditional visitor pattern in Arcum as an inter-face and an option, and shows the implications of the encoding in terms of bug detection.Section 5.1.4 presents a dynamic encoding of the visitor patter in Arcum using reflectionand the DJ library. With these two options, the visitor pattern can be applied as-needed forgeneral traversal needs, without sacrificing efficiency or expressiveness.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 22: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

22 · Macneil Shonle et al.

01 interface IBookVisitor {02 public void visit(Book book);03 }0405 class Library {06 private Shelf[] shelves;0708 public void main(String[] args) {09 Library library = new Library();10 IBookVisitor bookVisitor = new IBookVisitor() {11 public void visit(Book book) {12 // visit a book13 }14 };15 this.visitBooks(bookVisitor);16 }1718 public void visitBooks(IBookVisitor visitor) {19 for (Shelf shelf : shelves) {20 shelf.visitBooks(visitor);21 }22 }23 }2425 class Shelf {26 private Book[] books;2728 public void visitBooks(IBookVisitor visitor) {29 for (Book b : books) {30 visitor.visit(b);31 }32 }33 }

Fig. 9. A simple but complete example of the visitor pattern.

5.1.1 An Example of the Visitor Pattern. The visitor pattern is a depth-first traversalover a heterogeneous collection of objects. One popular example of the visitor pattern isa language interpreter with an abstract syntax tree that is enhanced with new operationsto be performed over AST nodes. Even this canonical use of the visitor pattern presentsdifficulties with respect to comprehension and evolution. In fact, the complexity of the vis-itor pattern sometimes leads developers to choose to avoid it altogether [Metsker and Wake2006, p. 338]. For example, it is hard to detect bugs in a visitor pattern implementation;such as when a new field is added to a AST node and the corresponding accept method isnot updated. It is also difficult to perform crosscutting changes to a typical implementationof the visitor pattern, such as changing the depth-first traversal into a breadth-first traversal.

Figure 9 provides a simple example of the visitor pattern, showing a Library classthat is composed out of Shelf instances, and a Shelf class that is composed out of Bookinstances. Using the visitor pattern, each instance of Book that is reachable from a giveninstance of Library will be passed to a visitor object, which can then perform an operationon it. The interface for visitor objects is specified on lines 1–3: Any object that implementsACM Journal Name, Vol. V, No. N, Month 20YY.

Page 23: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 23

define classGraph(Type from, Type to, Field edge) {(from == rootType || classGraph(_, from, _))&& hasA(from, to, edge)

}

define traversalGraph(Type from, Type to, Field edge) {classGraph(from, to, edge)&& !bypassEdge(edge)&& (targetType(to) || traversalGraph(to, _, _))

}

Fig. 10. Two recursively defined relations: classGraph, stated in terms of the hasA relation and itself; andtraversalGraph, stated in terms of the classGraph relation and itself. The hasA relation used here is a three-tuple form that exposes the Field that makes the relation hold.

this interface can be used as a “call back” during the traversal over the object structure.Lines 10–14 shows the definition of a visitor object (using an anonymous inner-class),and line 15 is the method call that causes the traversal itself to happen. In addition tothe interface for the visitor object, the classes involved in the pattern’s implementationmust support additional infrastructure: In this case two visitBooks methods are necessary(defined on lines 18–22 and 28–32).

5.1.2 Class Graphs and Traversal Graphs. Conceptually, the visitor pattern can be un-derstood as an operation involving two graphs: a class graph and a traversal graph [Lieber-herr 1996]. A class graph abstracts the has-a relationships of a group of classes: classes arerepresented as graph nodes, and fields are the edges that connect nodes. For the purposesof exposition, we consider class graphs formed from a single root class. Figure 10 definesa classGraph relation, where rootType is an externally specified Type.

The traversal graph is a subgraph of the class graph that is defined in terms of a traversalstrategy. A traversal strategy is specified by a set of target types and a set of edges (fields)to bypass. Starting from the root of the class graph, an edge is included in the traversalgraph only when (1) taking the edge will eventually lead to one of the target types, and (2)the edge is not in the bypass set. Example of edges to bypass include fields representingcached computations, and fields that are merely back-links to parent nodes. The relationin Figure 10 defines a traversalGraph relation, where targetType and bypassEdge areexternally specified predicates.

Reasoning over the visitor pattern with traversal graphs is a generalization of the visitorpattern, because a single class graph can have many sub-traversal graphs, some of whichmay overlap or be independent. When multiple traversal strategies are present, the methodsof the traversal infrastructure must also change. For example, instead of having generalaccept methods, a class may have methods with names related to the traversal strategiesassociated with it. Supporting multiple traversal strategies is more efficient and can alsosimplify the logic of visitor objects, but such support also requires even more traversalinfrastructure, which repeats multiple properties of the class graph and thus representsrepeated code. A solution that easily supports multiple traversal strategies, and can berefactoring to and from at will, is discussed in Section 5.1.4.

The definition of traversalGraph can be viewed as starting at the bottom of the classgraph and moving up. Initially, the only valid bindings for the to variable are those from

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 24: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

24 · Macneil Shonle et al.

the targetType relation. So, the first time the equation is solved the only members of therelation are those nodes from the classGraph that connect directly to one of the targettypes. The next iteration of the constraint solver is then able to use these new bindingsfrom the recursive clause of the equation, adding to the set all nodes that connect directlyto a node that connects directly to a target type. The process continues until no additionaledges can be considered as traversal edges, at which point a fixed-point is found.

The purpose of the traversal graph is to work in terms closer to the conceptual problem:What are the classes visited? As the program evolves, the class graph and the traversalgraph may change while the set of desired targetTypes is fixed. As a result, when codingis shifted to make the set of targetTypes the main definition form which other graphs arecomputed, the development process is more adaptive to change [Lieberherr 1996].

5.1.3 Visitor Arcum Option Implementation. A general purpose VisitorConceptcan be parameterized by the variables that occurred free in the code from Figure 10:the rootType variable, the targetType relation, and the bypassEdge relation. TheVisitorConcept can additionally be parameterized by: a Java interface that all visitorobjects must implement, and a name for the traversal. Figure 11 declares these parameterson lines 2–7. A declaration of the form T id, for example the one on line 2, simplydeclares id of the given type T. A declaration of the form T id:P declares id of the giventype T satisfying the predicate P. For example, line 3 declares visitorInterface to bea Type that satisfies isInterface. Similarly, line 4 declares rootType to be a Type thatsatisfies isClass. A declaration of the form id(T1 id1, . . ., Tn idn) declares a n-aryrelation. For example, line 5 declares targetType to be a unary relation on Types, whichessentially is a set of Types. Lines 6 and 7 are also relation declarations, in this case sets ofFields. These declarations also have a default clause, which is a value for the relationif none is provided when instantiating the interface. The default value for the viaEdgerelation is the set of all fields (the isField relation), and the default value for bypassis the empty relation false (indicating the empty set for bypass meaning that no edgesshould be bypassed).

Lines 13–22 of Figure 11 examine each type given in the targetType relation andchecks to see if the type is valid as a target (expressed in lines 14–17) and if the visitor-Interface has a corresponding visit method defined on that type (lines 18–21). Whensuch a method signature is not present, the user is given the error message on line 20, whichindicates what was expected. In general, the expression forall (T id:P) { B } shouldbe read as “for all id of type T such that P, B should hold”.

This visitor interface check is useful when the members of the targetType set changes.For example, a user could parameterize the use of the visitor pattern with a targetTypeset defined in terms of all subclasses of an abstract class. When a new subclass is cre-ated, either the corresponding visitors should change to accommodate this new type, orthe expression defining the targetType set should be revised to exclude the case. In bothcases, the introduction of the new subclass is an important event that requires modificationto either the program or the supplemental description of the program’s implementation.Although not shown in Figure 11, additional Arcum code can easily be added to checkthe implication in the other direction as well: if a visit method signature is present in theinterface, then the programmer probably intended it to be included in the targetType set.

Line 9 of Figure 11 specifies an abstract concept that captures all expressions (root)that represent invocations that start the traversal. Each traversal is applied to some baseACM Journal Name, Vol. V, No. N, Month 20YY.

Page 25: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 25

01 interface VisitorConcept(02 Name traversalName,03 Type visitorInterface : isInterface(visitorInterface),04 Type rootType : isClass(rootType),05 targetType(Type type),06 viaEdge(Field edge) default isField(edge),07 bypassEdge(Field edge) default false)08 {09 abstract visit(Expr root, Expr target, Expr visitor);10 define classGraph(Type from, Type to, Field edge) { /* ... */ }11 define traversalGraph(Type from, Type to, Field edge) { /* ... */ }1213 check {14 forall (Type t : targetType(t)) {15 !isAggregate(t)16 onfail {"‘t: Target types cannot be arrays or collections"}17 }18 forall (Type t : targetType(t)) {19 hasSignature(visitorInterface, <public boolean visit(‘t ‘_)>)20 onfail {"Missing visit method of type ‘t", visitorInterface}21 }22 }2324 define isAggregate(Type t) {25 isArray(t) || isA(t, <Collection>)26 }27 }

Fig. 11. Arcum code listing for a visitor pattern interface.

object (target), and is given a visitor instance (visitor). Lines 10–11 of Figure 11are placeholders for the complete definitions of the classGraph and traversalGraphrelations, specified in Figure 10.

One possible implementation of the VisitorConcept is the traditional “Gang of Four”implementation [Gamma et al. 1995]. Figure 12 shows GangOfFourVisitor, an optionthat implements this interface. Details related to Java interfaces are elided for expositorypurposes.

The visit concept is matched starting on line 2 of Figure 12. Line 3 binds the visitexpression to a call to the traversal method, and line 4 restricts the matched program frag-ments to only those traversal calls related to the given rootType. Line 5 is an additionalfilter using the within relation: code that implements the traversal infrastructure itselfshould not count as visit operations. This use of the within relation parallels the use ofthe adviceexecution pointcut in AspectJ.

The acceptMethod definition starting on line 8 of Figure 12 describes a correct imple-mentation of the traversal infrastructure. (For example, Figure 9 shows the definition of twovisitBooks methods, which form this infrastructure. These methods are typically namedaccept methods, but in this example the method name is specified by the traversalNameparameter, in order to provide greater flexibility.

The acceptMethod definition serves as a guide to identify missing statements or meth-ods when the class graph changes. For example, there are situations where a programmer

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 26: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

26 · Macneil Shonle et al.

01 option GangOfFourVisitor implements VisitorConcept {02 match visit(Expr root, Expr target, Expr visitor) {03 root == [‘target.‘traversalName(‘visitor)]04 && isA(rootType, target)05 && !exists (Method m : acceptMethod(m)) { within(root, m) }06 }0708 match acceptMethod(Method m) {09 traversalGraph(c?, _, _) && isClass(c)10 && hasMethod(c, m)11 && m == [public void ‘traversalName(‘visitorInterface v) {12 ‘[Statement stmt : acceptMethodStmt(c, stmt)]13 }]14 }1516 define acceptMethodStmt(Class owner, Statement stmt) {17 traversalGraph(owner, _, edge?)18 && stmt == select {19 targetType(target?) && declaredAs(edge, target):20 <visitor.visit(this.‘edge);>,21 isAggregate(iterable?) && declaredAs(edge, iterable):22 <for (‘iterable ‘‘element : this.‘edge) {23 ‘element.‘traversalName(v);24 }>,25 default:26 <this.‘edge.‘traversalName(v);>27 }28 }29 }

Fig. 12. Arcum code listing for GangOfFourVisitor, the traditional Gang of Four implementation of theVisitorConcept interface.

may add a new field to a class, creating another node that should be visited. If the additionof a the field enables a new subgraph of the entire class graph to be reachable, then globalchanges are required. We found this check to be helpful in driving the process of imple-menting new visitors and for finding bugs in existing code. In the source control historyof the Arcum project one bug recurred multiple times: certain sub-expressions were notbeing type-checked, because the traversal infrastructure left out those cases.

Line 9 of Figure 12 takes a projection of the traversalGraph, taking only types that areclasses (as opposed to interfaces). Lines 10–13 ensure that each of these classes has the ap-propriately defined accept methods. The expression ‘[Statement s : P] representsa list of statements satisfying predicate P. Thus, line 12 is just saying that the body of theaccept method is a list of statements satisfying the helper relation acceptMethodStmt.This helper relation, defined on lines 16–28, relates a class with a series of statements thatthe class’s accept method should contain. Line 17 extracts an edge in the traversal graphthat is outgoing from the class we are currently considering. Lines 18–27 use a select ex-pression, which in general has the form: select{case1:v1,...,casen:vn,default:v}.A select expression evaluates to the appropriate value based on which case is satisfied(including the default case, which is satisfied if none of the other cases are). The select

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 27: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 27

expression on line 18 has three cases: (1) If the edge connects to a targetType, then thevisit method is called (lines 19–20); (2) If the edge is a collection of elements that leadto other targets, then each element of that collection is recursively traversed (lines 21–24);and (3) Otherwise, a recursive traversal is performed (lines 25-26). Not shown in this fig-ure is the definition for acceptSignature, which is similar to acceptMethod but appliedto Java interfaces instead.

The for statement appearing in lines 22–24 of Figure 12 creates a new local variable,element, but uses two backticks before its name. These backticks are required whenlocal variables need to be matched or generated from Arcum patterns. Such patterns canmatch with code using different local variable names. When a pattern that uses a newlocal variable is generated, the new variable’s name follows Eclipse’s default suggestion(typically, a lower case version of the name of the type). When a pattern that uses a newlocal variable is matched, it has the additional restriction that code not described by theoption cannot refer to the variable.

5.1.4 The Visitor Pattern using Reflection and the DJ Library. The benefit of using thevisitor pattern is that it allows authors of a library to provide a generic traversal mechanismfor clients to use, thus allowing clients to write extensions without having to modify thecode base of the library. Yet the visitor pattern requires extensive traversal infrastructureto work, making it unsuitable for experimentation or other agile contexts where the classstructure might radically change. Fortunately, there is an alternative implementation ofthe visitor pattern that enables quick experimentation and supports agile contexts: The DJlibrary uses reflection in Java to offer a dynamic implementation of the visitor pattern [Or-leans and Lieberherr 2001]. The programmer describes the set of target types and the set ofedges to bypass by creating a Strategy object, and then the Strategy object can performthe depth-first traversal on the object graph. Figure 13 shows an example of the DJ librarybeing used on the simple Book example from Figure 9. The example is greatly simpli-fied, because the Strategy specification on lines 4–6 provides enough information to usereflection to compute the traversal necessary.

The DJ library offers multiple benefits. Because DJ reduces the amount of code thatneeds to be written, the program’s class structure is easier to change. This reductionin code makes it easier for alternative designs to be explored, increasing the software’squality. Additionally, the bugs discussed in Section 5.1.3 do not occur since the traversallogic is contained in the DJ library. Furthermore, the DJ library offers a modular solu-tion, something that even AspectJ cannot do. In particular, although AspectJ can be usedto encapsulate the visitor pattern by defining all of the traversal methods in the same as-pect [Hannemann and Kiczales 2002], any changes made to the class hierarchy will requirechanges in the aspect, making AspectJ’s encapsulation non-modular.

Figure 14 shows an Arcum option that implements the VisitorConcept by using theDJ library. The code listing comprises the entire Arcum code necessary to describe the im-plementation. (The class TypeLiteral is used instead of the simpler ClassName.classnotation, due to a technical limitation with Java’s generics; the workaround was devisedby Gafter [2006].) Here, the Arcum option is a direct translation from the sample code,parameterizing when necessary. More complex constructs to generate the traversal infras-tructure are unnecessary, because the DJ library itself is doing all of the heavy lifting.

The downside of using the DJ library is its extra performance costs: reflective operationscan be expensive and are harder for VMs to optimize. However, due to the fluid nature of

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 28: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

28 · Macneil Shonle et al.

01 class Library {02 private Shelf[] shelves;0304 public static Strategy visitBooks =05 Strategy.root(new TypeLiteral<Library>(){})06 .targets(new TypeLiteral<Book>(){});0708 public void main(String[] args) {09 Library library = new Library();10 IBookVisitor bookVisitor = new IBookVisitor() {11 public void visit(Book book) {12 // visit a book13 }14 };15 visitBooks.traverse(library, bookVisitor);16 }17 }1819 class Shelf {20 private Book[] books;21 }

Fig. 13. A modified version of Figure 9 that uses the DJ library.

01 option DJLibrary implements VisitorConcept {02 match Field strategy, Expr init {04 init == [Strategy.root(new TypeLiteral<‘rootType>() {})05 .targets(‘anyOrder:[Expr e: targetType(t?)06 && e == <new TypeLiteral<‘t>() {}>])]07 && strategy == [public static Strategy ‘traversalName = ‘init]08 && hasField(rootType, strategy)09 } onfail {"Must have a static field named ‘traversalName", rootType}1011 match visit(Expr root, Expr target, Expr visitor) {12 root == [‘rootType.‘strategy.traverse(‘target, ‘visitor)]13 }14 }

Fig. 14. Arcum code listing for DJVisitor, a dynamic implementation of the VisitorConcept interface.

Arcum refactorings, programmers can get the best of both worlds. When performance iscritical, the traditional implementation can be used. Then, when changes need to be madeto the class structure, the implementation can be refactored to use the DJ library instead.After the changes are made, the program can be tested and then refactored back to thetraditional implementation. In this way, the view of the program presented to the user isthe one best suited for his or her needs.

5.2 Debuggability

The considerations made while debugging a program are different than the considerationsduring the design and implementation processes. For instance, while a well-designed pro-ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 29: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 29

gram is modularized based on the criteria of what is likely to change [Parnas 1972], thereare an infinite number of design futures—attempting to anticipate them all is simply im-practical. This lack of anticipation is pronounced when it comes to software bugs: thekind of bugs that trouble programmers weren’t known to them when they first designedthe system. Thus, in the process of debugging, a programmer may need to make changesacross the decomposition of the system to help find the cause of the bug, and then to fix it.

At one stage in the development of Arcum, we encountered an intermittent bug. Eventu-ally, we discovered that the cause of the problem was a dependency on the iteration order ofHashMaps. The hashCode used was the default identity code. On the VM we were using,this identity was related to the object’s initial location in memory and thus objects wouldbe hashed to different sections of the hash table (and, hence, be iterated in a different order)on different executions of the program. After finding the cause of the non-determinism, wewanted to see how Arcum could be used to help. One solution is related to the class librarymigration problem (see Section 5.3): The program can be refactored, replacing uses ofHashMap with LinkedHashMap, which has a predictable iteration order. By changing theprogram to use a deterministic order, we were able to reliably reproduce the bug, makingit easier to locate the root cause of the problem and then to fix it.

A naive global search and replace could not be used in general to address this problemdue to the following drawbacks: (1) Replacements would be oblivious to syntactic context,and thus may accidentally make too many changes, for example changing a class by thesame name in another package; (2) A search and replace would not add or remove importstatements. Even if one designed a smarter semantic type-replacement refactoring, whichavoided the above two drawbacks, it would still have additional drawbacks: (3) Such re-placements would not account for the cases where the two classes have different ways ofbeing constructed (e.g., one uses constructor, the other factories); and (4) Replacementswould not account for the case where some of the method names in the two classes differ,or when the order of parameters of the methods are different.

AspectJ’s join-point model could have been used for this particular problem: advicecan be used to replace instantiations of HashMap objects with LinkedHashMap objects.Furthermore, a range of “development aspects” have been devised to allow the temporarymodification of the program’s behavior for the purposes of testing and debugging [Kicza-les et al. 2001a]. For example, AspectJ is very useful in contexts where instrumentationis needed, such as logging arguments and return values, or measuring various quantitiesduring program execution. However, there are times when the temporary transformationsneeded for debugging are beyond AspectJ’s abilities. For instance, in the example aboveof changing HashMap objects with LinkedHashMap objects, if the alternative type is nota subtype of the declared type, then advice cannot be used, because the type of declaredvariables would also have to be changed.

The above example of making a program more deterministic is a special case of a moregeneral problem: oftentimes what was assumed to be stable at development time mightneed to be changed to assist debugging. It is not surprising that a programmer would notdecompose a program to easily detect a bug, because, by definition, he or she did notsee the bug coming. By using Arcum, defensive techniques can be employed, even thosepreviously considered impractical (such as making every HashMap a LinkedHashMap),because there is always the option to change the code back again.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 30: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

30 · Macneil Shonle et al.

5.3 Class Library Migration

Often it is desirable to remove the use of a legacy library and directly use its replacementinstead. The solution for this problem devised by Balaban et al. [2005] includes a typeconstraint solver that finds the largest set of code locations that can be safely changed, evenin the presence of synchronized methods. For example, uses of the always-synchronizedVector class can be changed to uses of the more efficient ArrayList class, where theArrayList instances are synchronized only when necessary.

Arcum supports a complementary variation of class library migration. Instead of deter-mining the largest set of code locations that can be safely migrated, Arcum’s approach isto have the location set explicitly described, thus enabling migrations based on idiomaticuses. For example, one migration description might involve “all uses of Vector in packagep or by class C.” When the set cannot be transformed, the starting option presents the userwith static error messages. All errors have to be resolved before transformation is allowed.In some instances, the location-set specified might match more code than expected, requir-ing the user to narrow the set’s definitions; in other instances, the set definition is correctbut modifications need to be made to the code itself first, to bring it into conformance; inyet other cases, the user might realize, by the nature of the errors, that he or she needs totake a completely different approach. In this way, Arcum gives the programmer an oppor-tunity to interact with the tool, helping to ensure that his or her conception of the systemmatches the actual implementation, because the extra checking performed by Arcum willappear as familiar error messages in the IDE.

The Arcum approach is also different from Balaban et al.’s approach because checks per-sist after refactoring. For example, Balaban et al.’s solver adds synchronization wrappersto data-structures only when it is possible for instances to escape the current thread. How-ever, such wrappers are only generated at refactoring time: nothing prevents a programmerfrom later writing code that lets a non-wrapped data-structure to be accessed by a differ-ent thread. Such a case should be treated as an error in the Arcum approach, because thepost-conditions after a refactoring is made will persist. In this particular example, Arcumdoes not have the dataflow analysis primitives to perform escapes analysis, but it can detectthe violation of other post-conditions, for example, related to type information, methodscalled, or other operations performed.

The key to Arcum’s support for matching uses of class libraries is the Declaration-Element type, derived from the same term used by Tip et al. [2003] to describe all localvariables, fields, return types, and cast expressions. A DeclarationElement is a syntacticoccurrence of a type in a program that is used to declare something of that type. In Java,almost all type occurrences in a program are declaration elements: types for variables,for parameters, for casts and for return types are all declaration elements. The notableexception is when a class is declared: in this case, the type used (i.e.: the class name) isnot used to declare that something has a type—it is used to declare the type itself, and soit is not a declaration element. The pattern used to specify DeclarationElements in theprogram is a type pattern.

In addition to matching all DeclarationElements in the program, support for migrationmust allow for the description of operations such as: class instantiations, method invoca-tions, and conversion operations. Instantiations and method invocations can be matchedusing various Expr patterns. To match conversion operations, Arcum defines a copiedTorelation: copiedTo relates expressions to declaration elements, and the relation holds whenACM Journal Name, Vol. V, No. N, Month 20YY.

Page 31: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 31

the value of the expression is copied to a location declared by the declaration element.Copy operations include: assignment, initialization, argument passing, and value return-ing. The copiedTo relation can be used together with predicates on types to match andrefactor boxing and unboxing operations.

One use we found for class library migration was when we started to employ the GoogleCollections library [Google 2007]. The library includes extra support for programmingwith generics in Java, including interfaces and operations to support functional program-ming styles. For example, we had a need in Arcum to support operations that are lazilyexecuted. This division of definition and execution allowed us to separate the knowledgeof how to initialize an object from the knowledge of when to initialize it. We initiallydefined a parameterized Thunk<T> interface to achieve this, which declared a single, no-argument method with a return type of T. Looking into the Collections library, we foundthat the Supplier<T> interface fit our needs exactly. By using an interface defined in an-other library, we were able to make our use of the interface less mysterious compared to theoriginal solution. By writing code that conforms to a more standardized interface there is abetter chance to integrate independently developed code that followed the same standards.

However, it is sometimes necessary to keep two similar-looking solutions separate inorder to properly communicate the intentions behind the design of a program. For example,when two different methods accept an instance of Supplier<String>, are they related?Or, would it be better for one to be named DelayedObject<String> with the other namedDefaultValue<String>? This is a dilemma for the design process: On the one hand,a programmer may want to use the general Supplier to keep the design simple, untilneeds are better known. But, on the other hand, a programmer may anticipate additionaloperations that might need to be added later, where the additional operations will onlymake sense in one context but not the other. Or, the interfaces may stay the same, but thesemantics might diverge: For example, DelayedObject might have caching semantics,while DefaultValue would be better served re-computing the result for each request.

Arcum can be employed to resolve this dilemma: Programmers do not have to committo a single solution, because transformation is always an option. In this case, a program-mer wants to distinguish between two different uses of the same library. The solution isto extend the richness of type system by using annotations. For example, two structurallysimilar, but conceptually different, uses of the same interface could be separated by apply-ing different Java meta-data annotations to them, creating a form of qualified types.

For example, a @ReadOnly annotation can be applied to a Map declaration to define read-only look-up tables. Checks can be added to the Arcum code to prevent write operationsfrom being performed on the Maps. Later, this highly idiomized use of Maps could bechanged into a more natural Function interface, because a function can be conceived asa mapping. The employment of such annotations is not possible in previous solutions ofclass library migration, because they do not have idiomatic uses as their primary focus.

When writing an interface and two options two convert between Maps annotated as@ReadOnly and Functions, the author must decide if assignments are allowed betweeninstances belonging to the same type but with different annotations. For example, Ar-cum can be used to allow conversions between such instances, but only when a conversionfunction is called, to make the conversion explicit.

Key to the Arcum style is that programming decisions like this do not have to be madeimmediately. There is always the freedom to change one’s mind later, when needs are

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 32: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

32 · Macneil Shonle et al.

clearer. Using Arcum, a best guess for a design decision can be made, with that decisiondocumented as an option, to be revisited as needed.

5.4 Smart Find and Replace

Software engineers are often faced with complex crosscutting change tasks that, in theirminds, amount to a find-and-replace task, but cannot be performed easily or completelywith a typical text editor. Arcum’s syntactic matching and semantic checking can makethese changes easier. Additionally, for those changes that are temporary—say, for a debug-ging task—Arcum makes it trivial to revert those changes until they are needed again.

5.4.1 Message Log Redirection. For a first find and replace test, we edited the Ar-cum plug-in code base. The plug-in has a mode for sending debugging information toSystem.out, and we considered a scenario where we wanted this output to be redirectedto a different stream. This change can easily be accomplished by redirecting System.outitself. However, redirection is too blunt of a solution in Eclipse, because it redirects alloutput to the standard System.out steam, including outputs from other plug-ins.

The solution requires that our plug-in uses one stream, while any other plug-ins continueto use System.out. Eclipse can perform this change more thoroughly than a standard tex-tual find and replace: Eclipse can locate all references to the field (which numbered justover 1,000) regardless of the whitespace formatting or scope issues (such as when staticimports are used). However, despite Eclipse’s semantic level search, all source code mod-ifications still needed to be made using a textual find and replace. This global replaceoperation caught most instances, but repeating the semantic search revealed the rare syn-tactic exceptions missed by the search pattern.

AspectJ was better suited at performing the change than just Eclipse alone. AspectJ hasa get pointcut that can match all references to a specific field. The pointcut can also benarrowed down to match classes contained in a specific set of packages. A simple aroundadvice applied to this pointcut can replace the value used for System.out in every locationin the project. The AspectJ solution also had the advantage that the stream returned by theadvice could be either the value of a stored stream or the result of a method call.

Finally, the same change was made using Arcum. A simple interface was written thathad one abstract concept with only one member (of type Expr) in it. Then, an option waswritten to match this concept with all accesses to System.out. To test the option, weused Arcum’s search view to display all program fragments that belonged to the concept.Once we were convinced the results were as expected, we wrote an alternative option thataccessed a different field instead. Similar to the AspectJ solution, it was a simple matterto change the stream used to the result of a method call instead, just by adding yet anotheroption.

One advantage of the Arcum solution over the AspectJ solution is that it refactors theprogram itself, as opposed to only modifying the program’s semantics through byte-codeweaving. As a result, design decisions are more visible and can better reflect the nature ofthe program. The prior disadvantages of such crosscutting code are no longer disadvan-tages with Arcum: for example, even though the calls to a helper method may crosscut theprogram, this crosscutting is not a liability because the code can easily be changed backshould the need arise.

5.4.2 Remove Control Coupling. For a second change task, we considered refactoringcalls to a method that took on the duty of two different operations: the operation to performACM Journal Name, Vol. V, No. N, Month 20YY.

Page 33: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 33

was determined based on whether or not one of the arguments was null. This argumentessentially became a flag, and a usage pattern emerged as a result where calls to this methodwould pass null into this argument. Such a usage pattern increases the coupling betweenmodules and it would be better to refactor the source code so that these calls would invokea separate method that just performs the expected operation. Our goal was to perform thisrefactoring using Arcum.

The Eclipse ‘Change Signature’ feature is useful for introducing a new argument orremoving one, but it’s not suited for the task of changing some but not all method calls.In Arcum we were able to match all special null argument cases and change them intocalls to the new method instead. One limitation with the current Arcum approach (andsimilarly for AspectJ) is that a dataflow analysis is not performed. For example, instead ofsyntactically matching when null is an argument it would be more flexible to categorizethe argument into one of three sets: (1) The set of calls where the argument is known tobe null; (2) The set of calls where the argument is known to be non-null; or (3) The setof calls where the argument may or may not be null (for example, when it can only bedetermined at runtime).

5.5 Discussion of the Arcum Development Process

Several interesting design decisions came up in the process of developing our Arcum code.Based on our experience with these design decision, we highlight here some of the commonissues that we believe developers will have to think about and address when developingArcum code.

We have found that there were two key considerations in the design of a group of relatedoptions. The first is that any resulting transformations should satisfy the specifications forthe crosscutting concept. Analogously, if the programmer edits Arcum code in a way thatviolates the intended use of the specification, then an error should be reported. The secondis how to structure the interface so that it admits a suitable range of options without beingso general as to unnecessarily complicate the implementation of options.

In practice, we found that it was hard to get these right the first time. But we also foundthat it wasn’t necessary. For example, our first version of the AttributeInterface inter-face was correctly parameterized, but its internals omitted extra condition checking. Whenwe wrote an option, which described one particular implementation, we added explicitchecks to the interface.

Similarly, determining what to put in the Arcum interface for the visitor pattern was acoding consideration: The classGraph and traversalGraph relations were only used bythe GangOfFourVisitor option, but were general enough to be defined in the interface.To determine that the visit concept also needed to be in the interface we had to look insample source code for real occurrences of the traditional visitor pattern and the DJ library.Without having these concrete code samples to look at it was too easy to forget aboutspecial cases in the pattern’s implementation.

In fact, the development process we found most effective was to write a mini-programthat demonstrated the pattern and then writing the first option to match the demonstration.We could then test the Arcum code against the mini-program before applying it to the reallife use and testing it again.

Over the development history of our Arcum code, the changes we made to interfaceswere mostly in the form of additional checks or additional predicate definitions. Existingconcept signatures, on the other hand, rarely changed, and thus external clients were unaf-

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 34: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

34 · Macneil Shonle et al.

fected by the numerous improvements. The changes that we did make to interfaces ofteninvolved an interaction between the interface and an option. This is not surprising, as theirinteraction is analogous to the interplay between a superclass and its subclasses, whichoften collaborate intimately.

Another issue that arises in developing Arcum code is the potential for feature interac-tion. There are two kinds of feature interactions that can occur: within the same interfaceand across interfaces. Across interfaces, the issue is that two different concepts from dif-ferent interfaces can overlap in the code that they match. If one of these interfaces switchesfrom one option to another, then the concept that belongs to the changing interface will betransformed, and this may invalidate the other concept, leading to an error. The other issueis that within the same interface, one can have two concepts match the exact same pieceof code. If this interface is switched from one option to another, then the two conceptsmay want to transform to two different pieces of code, which again will lead to an error.Although errors that arise from feature interaction occur dynamically (when the transfor-mations are performed on the program), it would be an interesting avenue of future workto try to detect such errors statically, using some kind of interference analysis.

6. RELATED WORK

The difficulty of coping with crosscutting concerns have been addressed in two generalsolution spaces, some of which overlap: language-based solutions (Section 6.1) and tool-based solutions (Section 6.2). Language-based solutions improve the expressiveness ofthe source programming language, allowing concerns that would previously be crosscut-ting to be encapsulated. Tool-based solutions help programmers find, match, visualize,refactor, and/or transform crosscutting concerns (note that many such tools, even thoughthey don’t change the source language do introduce a secondary programming languagefor expressing things like regular expressions, patterns, checks or configurations).

Broadly speaking, Arcum differs from previous approaches in that it is a tool-based so-lution for crosscutting that uses two key concepts of modularity to achieve several of thebenefits of the language-based solutions. In particular, Arcum provides modular checkingand modular substitution of crosscutting concepts. Furthermore, Arcum’s use of stableinterfaces with options that implement them is a novel approach for specifying transfor-mations when compared to previous work on program analyses and transformations (asexplained more in Section 6.3): transformations and checks are always performed fromthe option to the interface, and then from the interface to the alternative option, rather thanfrom one option directly to the other. As a result, even though crosscutting concept im-plementations cannot be explicitly modularized in the program, programmers can still getseveral of the benefits of modularity.

We now give more detailed comparisons with related work on language-based solutions(Section 6.1), tool-based solutions (Section 6.2), and finally program analyses and trans-formations (Section 6.3).

6.1 Language-Based Solutions

A language can be a solution for crosscutting code when it can provide better expressionsof the kind of designs that lead to crosscutting. Often, such languages are created as exten-sions to existing languages.

Examples of such language-based solutions can be found in the field of aspect-orientedsoftware development (AOSD), which has introduced a host of aspect-oriented program-ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 35: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 35

ming (AOP) languages such as AspectJ [Kiczales et al. 2001b]. AspectJ addresses cross-cutting through new abstractions, called aspects. Program reasoning is improved with thehelp of aspects, because code related to one concern, which would otherwise be cross-cutting, can now be reasoned about in isolation. For example, Hannemann and Kiczaleshave shown that aspects can improve the design of many crosscutting concepts, includingdesign patterns [2002]. However, aspect-oriented solutions often have difficulties whencrosscutting concerns are encapsulated but not modularized; that is, aspects can createdependencies that make the code more brittle and harder to reason about. One solutionfor fully modularizing aspects in an aspect-oriented language is to employ crosscuttinginterfaces, or XPIs, which explicitly state the stable assumptions that aspects can dependupon [Sullivan et al. 2005; Griswold et al. 2006]. The work on XPIs, which shares commonauthors with this work, was partially the inspiration for Arcum’s interfaces.

Other language-based solutions focus on means for programmers to better express theirintentions to the programming environment. For example, Explicit Programming withElide [Bryant et al. 2002] and the static metaprogramming system of von Dincklage [2003]allow user-defined modifiers to be applied to program elements. These modifiers canchange the semantics of program element, so that, for example, a class marked with appro-priate serialization modifiers can have serialization methods automatically added to it. Thiskind of modification is something that Arcum cannot do, because the program’s semanticsare based entirely on the Java compiler. However, Arcum can check for the presence ofsuch supplemental code (like serialization methods): if the code was expected, an errormessage will show the missing code, which could then be pasted into the program. Theadvantage of code generation techniques over Arcum is that unnecessary implementationdetails can be elided from the programmer’s view. In contrast, Arcum can only elide detailsif some implementation makes it possible (for example, by using reflection in the case ofthe DJ library with the visitor pattern).

DRIVEL is a program enhancement system that, like Elide, also employs generativetechniques [Tilevich and Back 2008]. DRIVEL is unique because it does not extend thesyntax of the programming language; instead, programmers write Java programs that as-sume the presence of certain program elements. If the element is not present, DRIVELwill generate it automatically. This technique is well suited for design patterns, becausethe code that needs to be generated can be inferred from the context based on role us-age. Again, there are trade-offs between having extra code generated and having the codepresented inline in pure Java.

All of the programming language extensions discussed thus far are general purpose intheir aims. In contrast, a different approach is to design domain-specific language exten-sions that are tailored for addressing certain specialized forms of crosscutting. For exam-ple, DemeterJ [Lieberherr and Orleans 1997] has support for the many variations of thevisitor pattern and supports the customization and optimization of traversal paths. Deme-terJ is the foundation for the DJ library that followed it, which enabled the option presentedin Section 5.1.4. As an alternative, the MultiJava language [Clifton et al. 2000] can reducethe need for the visitor pattern in the first place through the use of multi-methods. MultiJavaprovides a direct solution for the domain-specific problem of multiple method dispatch. Itis possible that an idiom using reflection or method tables could simulate multi-methodsin Java, but it the problem remains open if MultiJava’s checks for completeness could beexpressed in Arcum.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 36: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

36 · Macneil Shonle et al.

6.2 Tool-Based Solutions

A long line of programming tools are available to cope with crosscutting. In addition totext editors and the Unix grep command are tools like CScope [Steffen 1985] and IDEs,such as IBM’s Eclipse (which provides automated refactoring transformations derived fromthe Refactoring Browser for Smalltalk [Roberts 1999]). Refactoring tools also have thepotential to improve code by reducing the liabilities associated with using programminglanguage extensions. For example, certain design patterns implemented in Java can berefactored to more flexible AspectJ equivalents through the role-based refactoring tool ofHannemann et al. [2005]. The basic idea is to support the refactoring of crosscutting con-cepts like design patterns by separately recognizing the code for each role in a designpattern (with programmer interaction), and then applying micro-refactorings to each ofthose roles to achieve the macro-refactoring. Marin et al. take a similar approach, althoughthey assemble macro-refactorings from micro-concerns rather than roles [2005].

Refactoring tools can be targeted to address domain-specific problems. For example, toautomatically assist with the specific task of class library migration, Balaban et al. employa rich type system and a constraint solver to automatically retargeting code libraries inlarge codebases [2005]. Arcum’s focus is on idiomatic uses, and can thus capture a relatedsubset of uses of a library as the candidate for transformation.

The Feature Oriented Refactoring (FOR) work of Liu et al. recognizes the crosscuttingand non-modular nature of the implementation of software features, which are often cross-cutting [2006]. With FOR, certain types of programs can be refactored into a base programand modular feature refinements. The features are refactored and composed through theapplication of delegation techniques.

HyperJ is a tool-based approach to crosscutting, where specifications can be used to syn-thesize and compose Java programs [Tarr et al. 2002]. HyperJ operates at the componentlevel, while Arcum can operate on fine-grained crosscutting concerns that are scatteredacross several modules.

The Eclipse Modeling Framework (EMF) is a code generation approach for Java whereprogrammer-supplied descriptions can drive the code generated, using one of several al-ternative implementations [Budinsky et al. 2003]. EMF, like Arcum, makes code develop-ment more fluid and closer to a programmer’s intentions, but is a pure generative system,and not a refactoring (code transformation) system.

Other tools allow programmers to better express changes by understanding the programbetter. For example, Simonyi’s Intentional Programming (IP) [1995] aims to have pro-grammers work at the level of their intentions, allowing for easier change to programs.Instead of being a refactoring system like Arcum, IP utilizes a program-as-database ap-proach: If any linked entry changes, the change follows all links backward. The RE-FINE system also employs a program-as-database approach, in addition to program tem-plates, which can be used for both pattern matching and code transformation [Kotik andMarkosian 1989]. REFINE’s code transformations discussed are directed at uses such as“eliminate redundant multiplies by 1” and code mutations for test suite validation; whereasArcum’s focus is code transformations related to crosscutting idioms.

As a departure from REFINE, Kozaczynski et al. employ semantic pattern matching—including control-flow and data-flow—to recognize “concepts” as part of a code transfor-mation system for software maintenance [1992]. Other work in this area is DMS, which issimilar to Kozaczynski et al. but has a much wider scope [Baxter et al. 2004].ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 37: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 37

Reichenbach et al. present an approach called Program Metamorphosis [2009], whichextends the traditional refactoring paradigm. In particular, Program Metamorphosis ismore flexible than traditional refactoring in two ways: (1) It allows refactorings to be com-posed of small steps that individually don’t preserve semantics, as long as the final programhas the same semantics as the original program; and (2) It permits behavioral evolution ofthe programs, thus not restricting the programmer to strictly semantics-preserving refac-torings. Arcum shares the same philosophy of not restricting the programmer to strictlysemantics-preserving transformations, allowing programmers to preserve the behavior atthe interface level. However, Arcum has a modular approach to maintaining crosscuttingconcerns, which includes the use of common interfaces.

The iXj program transformation system for Java allows for pattern matching of code re-lated to a crosscutting concept [Boshernitsan and Graham 2004; Boshernitsan 2006]. TheiXj system is interactive and allows for programs to be changed at a level more sophisti-cated than a text editor’s find and replace feature. The iXj system could assist the writingof Arcum concepts through its interactive features, while Arcum could complement iXj byproviding a mean of expressing infrastructure related to concepts and by providing contin-uous checking of implementations. Twinning is a similar system, focused on the parallelmaintenance of a family of programs [Nita and Notkin 2010]. Twinning provides mappingsbetween program fragments like Arcum, but does not support a notion for implementation-specific code that does not have a corresponding fragment in the alternative program.

Another class of tools that can address crosscutting are static analysis tools, such asSLAM [Ball et al. 2001], ESP [Das et al. 2002], and PDL [Morgan et al. 2007]. Thesetools can be used to find bugs, which are often crosscutting in nature.

6.3 Program Analyses and Transformations

There has been a long line of research on specifying program analyses and transformations,including Sharlit [Tjiang and Hennessy 1992], SPARE [Venkatesh and Fischer 1992],System-Z [Yi and Harrison III 1993], PAG [Alt and Martin 1995], the k-tuple dataflowanalysis framework [Masticola et al. 1995], Dwyer and Clarke’s system [1998], Whitfieldand Soffa’s Gospel language [1997], and systems based on a variety of technologies, forexample guarded rewrite rules [Lacey et al. 2002; Bravenboer et al. 2008; Lerner et al.2005], attribute grammars [Babich and Jazayeri 1978a; 1978b; Demers et al. 1981; Car-roll and Ryder 1988], regular path queries [Sittampalam et al. 2004; Verbaere et al. 2006],temporal logic [Steffen 1991; Lacey et al. 2002], and Datalog/Prolog [Reps 1994; Whaleyand Lam 2004; Whaley et al. 2005]. These previous systems typically take advantage ofthe stylized nature of the high-level descriptions in order to attain properties that would bedifficult to achieve otherwise. For example, Whitfield and Soffa’s Genesis system [1997]can automatically examine the interactions between different optimizations written in theGospel language to determine the best order in which to run them. Whaley and Lam [2004]can generate highly scalable implementations for their Datalog-like specifications using Bi-nary Decision Diagrams (BDDs) [Bryant 1992]. The Rhodium system [Lerner et al. 2005]allows analyses and transformations expressed in a domain-specific language to be provedcorrect fully automatically.

However, when compared to Arcum’s transformation capabilities, these previous sys-tems all specify the transformations explicitly, typically in a uni-directional way: someform of pattern matching is used to specify places in the original program to transform,and then some action is specified to be performed when a match occurs, either by using

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 38: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

38 · Macneil Shonle et al.

explicit action commands like Replace and CreateNode in JunGL [Verbaere et al. 2006], orby providing transformed code to replace any matches with, as in Rhodium [Lerner et al.2005] or Stratego [Bravenboer et al. 2008]. In contrast, Arcum’s style of transformationsis actually very different from this explicit uni-directional approach. In Arcum, the notionof “original” and “transformed” programs are symmetric, each being tied to an Arcum op-tion that implements the same interface. The patterns in the two options are used both formatching and code generation, allowing for seamless bi-directional transformations.

Of course, there has also been a lot of work specifically on bi-directional transforma-tions. Broadly speaking, most computations are used to produce output from input; some-times, however, we also want to update the output and reflect this change “backward” intothe input. Such bi-directional transformations, sometimes called lenses, have been inves-tigated in a variety settings, including the database view/update problem [Bancilhon andSpyratos 1981; Foster et al. 2007; Barbosa et al. 2010], data transformations [Kennedy2004; Bohannon et al. 2008], XML processing [Hu et al. 2004; Kawanaka and Hosoya2006], and model transformations [Xiong et al. 2007]. Programming languages have evenbeen developed, such as the Boomerang language [Bohannon et al. 2008; Foster et al.2008], to facilitate the development of bi-directional transformations. Arcum differs fromprevious research on bi-directional transformations in two significant ways. First, much ofthe previous work on bi-directional transformations has been done in the context of datatransformers (such as XML or database transformers), not program transformers. Sec-ond, whereas previous approaches focus on the relation between two entities, an original“source” input and a transformed “view” output, Arcum makes the contribution of addinga third entity to the bi-directional transformation paradigm, namely the interface level. In-deed, a transformation like the one in the Attribute example of Figure 5 does not go directlyfrom one concrete option to another. Instead, it goes from one concrete option, up to theinterface level, and then back down to another option. This additional step of lifting tothe interface level is precisely what provides many of the benefits of Arcum, and in par-ticular, this interface level is what allows Arcum to easily switch back and forth from onewell-defined, stable, crosscutting concern implementation to another.

There has also been a long line of work on efficiently executing program analyses andtransformations, for example by using incremental approaches [Sittampalam et al. 2004;Shankar and Bodık 2007], BDDs [Burch et al. 1992; Berndl et al. 2003; Whaley and Lam2004; Whaley et al. 2005], or constraint solvers [Aiken and Fahndrich 1997; Fahndrichet al. 1998]. Although currently the Arcum engine is sufficiently fast for interactive use,the Arcum language could be extended with more sophisticated kinds of capabilities, forexample dataflow analysis as mentioned in Section 7. In such a situation, some of theabove techniques for efficient execution could be adapted to the Arcum domain to makethe new Arcum environment fast enough for interactive use.

7. FUTURE WORK

We see at least two important future lines of inquiry regarding the Arcum approach: oneregarding the practical expressiveness of Arcum, the other increasing automation throughthe use of concept mining.

Expressiveness. Arcum showed itself capable in a variety of applications in Section 5,but these are not comprehensive. As a starting point, we will investigate the use of Ar-cum to capture additional design patterns [Gamma et al. 1995], for example SingletonACM Journal Name, Vol. V, No. N, Month 20YY.

Page 39: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 39

and Model-View-Controller. In doing so, we will also explore what kinds of refactoringsand checking can be done in those settings. An in-depth case study following developersworking on their own projects would also be valuable.

Guided by these studies, we will be exploring ways of making the Arcum language moreexpressive and powerful with the addition of new language features. Using our experienceto date, we have already identified that adding support for dataflow analysis in Arcumwould be beneficial. This could be done either by adding new primitives to the languagefor common pre-computed dataflow facts, or by providing a means for programmers todefine their own dataflow analyses (for example through a domain-specific language orthrough a programmable plug-in architecture). With the addition of dataflow analysis,the Arcum programmer will be able to perform more complicated pattern matching andexpress more sophisticated checks. For instance, when migrating from the old Java Vectorclass (which is always synchronized) to the ArrayList class (which is only synchronizedwhen requested), the Arcum developer would benefit greatly from having a thread-escapeanalysis to determine when explicit synchronization is needed [Balaban et al. 2005].

Concept Mining. If a code base hasn’t been developed with Arcum from the start, or anewly developed option wasn’t anticipated in early development, it is possible that thereare idioms “hidden” in the code that could be managed with an existing Arcum option.Concept mining could find all the code that potentially matches one or more options, ifinstantiated with the right parameters. Once matched, it would be possible to automaticallygenerate mappings like the one in Figure 4. Automatically generating mappings also makesthe task of identifying potential refactorings more mechanical and therefore less prone tooversights by the programmer. Further still, a suite of programs could be queried as a wayto anticipate Arcum options: common patterns could be identified, suggesting either newlibrary abstractions or new Arcum options to develop.

Software Product Lines. The Arcum machinery can be used to create a compilation pro-cess for the generation of software product lines. Under product line architecture [Clementsand Northrop 2001], components can be used to describe a family of applications [Parnas2001] that may have, for example, different scalability or security needs. A programmercould supply a list of mappings for each option present in the program, and then a set ofalternative lists with different options. Each list would represent a software product line’svariation points. Implementation requirements can be specified in the form easiest to ex-press (for example, a Java field) and transformed at compile-time to the target product’sneeds (for example, a database access). A special case would be an in-house product lineinstrumented with performance measurement and debugging support that would not be partof the release version of the software. Any modifications to the software in the process ofimproving and measuring performance would automatically be applied to all versions.

8. CONCLUSION

In this article, we presented Arcum, a novel approach for capturing, manipulating andmanaging crosscutting concepts. Arcum is unique in its ability to declaratively capturecrosscutting concepts, such as programming idioms, while also allowing bi-directionaltransformations. When using Arcum, programmers declaratively specify the crosscuttingconcepts present in their code, using interfaces and options. An interface specifies theconcept at an abstract level and includes behavioral constraints that hold over all imple-mentations. An option provides a concrete implementation of the interface using patterns

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 40: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

40 · Macneil Shonle et al.

that correspond to the abstract concepts of the interface.When the programmer uses a mapping to specify that a given option instantiation is

expected in the program, Arcum matches the option’s patterns and checks the matched ele-ments against the interface’s behavioral constraints. If the programmer specifies that a new,different option should hold in the program, Arcum not only performs these checks for theold option, but then replaces the matched elements with the code specified in the patterns ofthe new option. Due to the declarative nature of the language, and the continuous checkingthat Arcum performs, the transformation process can be run in either direction.

Our case study covered examples of crosscutting encountered “in the wild” and showedthat such crosscutting can be captured and managed through declarations written with Ar-cum. We found that throughout our experiments, Arcum achieved its intended goal: itprovided the feel of modular substitutability for non-modular crosscutting concepts.

APPENDIX

A. ARCUM GRAMMAR

This section presents a grammar for the Arcum language and a reference for Arcum’stypes. Arcum’s lexical structure is a superset of Java’s, allowing for the backtick character(‘‘’) to be recognized. Some of Arcum’s syntactic structure embeds portions of Java code.Given such constructs, the terminals and non-terminals that are used, but not defined, herecan be found in The Java Language Specification [Gosling et al. 2005]. The rules importedfrom Java are: ImportDeclaration, Identifier (abbreviated here as Id), Type, Str-ingLiteral, and Literal.

Here, [x] denotes zero or one occurrences of x; [x]∗ denotes zero or more occurrences ofx; and x | y denotes one of either x or y.

ArcumCompilationUnit ::= [ImportDeclaration]∗ [ArcumDecl]∗

ArcumDecl ::= IntfDecl | OptionDecl | MappingDecl

IntfDecl ::= interface Id [IntfParams] { [IntfMember]∗ }IntfParams ::= ( IntfFormal [, IntfFormal]∗ )IntfFormal ::= Type Id [: Expr] [default Expr]

| Id Formals [: Expr][default Expr]

IntfMember ::= AbstractConcept | PredicateDefinition | CheckAbstractConcept ::= abstract Type Id ConceptConstraints

| abstract Id Formals ConceptConstraintsConceptConstraints ::= ; | { Expr [Check]∗ }Check ::= check [StringLiteral] { Expr }Formals ::= ( [FormalsList] )FormalsList ::= Type Id [, Type Id]∗

PredicateDefinition ::= define Id Formals { Expr }

OptionDecl ::= option Id implements Id { [OptionMember]∗ }OptionMember ::= MatchDecl | PredicateDefinition | CheckMatchDecl ::= match Id Formals { Expr }

| match FormalsList { Expr } [OnFailClause]OnFailClause ::= onfail { StringLiteral [, Id] }

MappingDecl ::= check { [MappingOrPredicateDefinition]∗ }ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 41: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 41

Table II. Arcum Types

Type Program Fragment

AccessSpecifier A subtype of Modifiers: One of either public, private, protected, orthe default ‘package access.’

Annotation A Java metadata annotation.DeclarationElement The declaration of a local variable, field, return type, or a cast ex-

pression. Specified as a type.Expr An expression.Field A subtype of DeclarationElement: A field.Method A method.Modifiers A possibly empty set of modifiers that are applied to methods,

classes, and fields (e.g., static, public, final)Name A name for a type, method, variable, or package.Signature The name and parameter types of a method.Statement A statement.Type A Java type, either primitive or reference.

MappingOrPredicateDefinition ::= Mapping | PredicateDefinitionMapping ::= Id OptionArguments ;OptionArguments ::= ( ) | ( NameValPair [, NameValPair]∗ )NameValPair ::= Id : Literal | Id : Id | Id : Type [. Id]

Expr ::= Term | Expr || TermTerm ::= Factor | Term && FactorFactor ::= Id ( PredicateArgument [, PredicateArgument]∗ )

| Id == VariableVal | ! Factor | ( Expr [<=> Expr]∗ )| ExistsExpr | ForallExpr | true | false

PredicateArgument ::= | Id | Id ? | ImmediatePatternVariableVal ::= Id | SelectExpr | Pattern | ( Pattern [|| Pattern]∗ )ExistsExpr ::= exists ( FormalsList : Expr ) { Expr }ForallExpr ::= forall ( FormalsList : Expr ) { Expr [OnFailClause] }SelectExpr ::= select { SelectCase [, SelectCase]∗ default : VariableVal }SelectCase ::= Expr : VariableValPattern ::= SearchPattern | ImmediatePatternUnquotedVariable ::= ‘ Id | ‘ | ‘ ...EmbeddedArcumExpr ::= ‘ [Ordering :] [ Type Id : Expr ] | UnquotedVariableOrdering ::= anyOrder | strictOrder

A SearchPattern is a sequence of Java tokens with matched brackets and parenthesescontained within a pair of square brackets ([. . .]). Identifiers in the sequence can bepreceded with a backtick “‘”, which is the escape mechanism used to refer to Arcumvariables. The special variable “ ” matches anything, and the special variable “...”matches any sequence of constructs (such as arguments in a method call, or statementsin a block). An ImmediatePattern follows the same rules as SearchPattern, exceptthe sequence is contained within a pair of angle brackets (<. . .>). A SearchPatternmay have EmbeddedArcumExprs within it, but an ImmediatePattern can only haveUnquotedVariables.

Table II lists the types available in Arcum for matching against program fragments.ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 42: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

42 · Macneil Shonle et al.

B. FORMALIZATION

This appendix gives a formal semantics to Featherweight Arcum, a simplified version ofthe Arcum language that captures the essence of this article’s ideas. This semantics putsthe informal description given in Section 4 on a sound theoretical footing. As is typicallydone in many existing formalisms, Featherweight Arcum tries to capture the most impor-tant features of Arcum, but it does make certain simplifications for the sake of brevity. Inparticular, Featherweight Arcum assumes that there are no overlapping matches (matcheswhere two Arcum variable map to overlapping pieces of syntax) and that there is no nega-tion (negation can be handled using stratification, as outlined in Section 4).

We start by defining the language of programs manipulated by Featherweight Arcum(Section B.1), and then the actual syntax of Featherweight Arcum (Section B.2). We thencontinue with the solver semantics of Featherweight Arcum (Section B.3) and the trans-formation semantics of Featherweight Arcum (Section B.4). Finally, we present a recapexample (Section B.5) that shows all the components of the formalism together workingon a simple example.

B.1 Source Programs

We define the source language to be the language that Featherweight Arcum manipulates.The source language in our implementation is Java, but in our formalism of FeatherweightArcum we can abstract away the details of the source language. We represent a program inthe source language as an Abstract Syntax Tree (AST). We define an AST node n to have:

—A label L(n) indicating what kind of node n is, for example a plus expression (in whichcase the children are the arguments of the “plus”), an individual statement (in which casethe children are the left-hand side and the right-hand side), or a sequence of statements(in which case the children are individual statements).

—A list C(n) of AST children nodes. If by starting at a node n1, and following childrenlinks transitively we reach a node n2, then we say that n1 is an ancestor of n2, and n2 isa descendant of n1. An AST must be acyclic, meaning that no child of n is allowed toalso be an ancestor of n.

We denote by AST the set of all AST nodes. A source language program π is a pair〈r, loc〉, where r ∈ AST is an AST node representing the root of the program, and loc :AST ⇀ Loc is a function from each AST node in the program to a unique program locationwhere the AST node occurs. These program locations are abstract versions of concreteprogram locations, such as line or character numbers in a file. Each AST node in a programmust have its own unique program location, but program locations can be shared acrossprograms. Given a program π = 〈r, loc〉, and a program location l, we use π(l) to denotethe AST node of π at location l (namely the node n that is a descendant of r and for whichloc(n) = l). We denote by Π the set of all source programs.

B.2 Featherweight Arcum

We formalize a Featherweight Arcum program as a set A of rules of the following form:

def p(V1, . . . ,Vk){ψ}

where def is either match or define. In the case where def is match, then p represents aconcept definition, such as attrSet in Figure 5, and in the case where def is define, thenp represents an internal predicate definition, such as hasA in Figure 6.ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 43: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 43

Given an Featherweight Arcum program A, we define PredNameA to be the set of allpredicate names p that occur in A, and MatchPredNameA to be the set of predicate namesin A defined using match. We model different options by using separate FeatherweightArcum programs, each containing only the match expressions from a given option. Thepredicate-body ψ is a predicate from the following grammar:

ψ ::= ψ && ψ | ψ || ψ t ::= CodePattern| p(t1, . . . , tk) | LocVar| prim(t1, . . . , tk) p ::= identifier| forall(V : τ){ψ} | exists(V : τ){ψ} V ::= identifier| t == t

Where p is a predicate name (such as attrSet or hasA), and prim is a primitive predicatethat the Arcum system provides (such as isA, hasMethod).

The non-terminal V represents identifiers that are Arcum variables, for examplesetExpr, targetExpr, and val in Figure 5. The non-terminal CodePattern (whoseproduction rules are not shown) represents patterns over the source language. In particular,CodePattern is just like the source language, except that it also allows Arcum variables.For example, if the source language had the grammar:

s ::= s;s | x := e e ::= 1 | x | e+ e x ::= identifier

Then the code pattern language would be CodePattern ::= ps | pe | px, where:

ps ::= ps; ps | px := pe |V pe ::= 1 | px | pe+ pe |V px ::= identifier |V

As was explained in Section 3.1, the first argument to a concept captures the programlocation of a match (but not the syntactic content), whereas the remaining arguments cap-ture the syntactic content of a match (but not the program location). This distinctionbetween the first argument and the remaining arguments of an option is reflected in amatch p(V1, . . . ,Vk){ψ} expression as follows: the first argument V1 captures locations,whereas the remaining arguments capture syntactic content. To make the presentation sim-pler, we define a special non-terminal LocVar that represents the use of a variable whichwas defined as the first parameter of a concept, meaning that this variable only captures thelocation of a match.

Substitutions

We say that a ground term is either an AST node or a program location, and we denote byGroundTerm the set of ground terms. In particular, GroundTerm = AST∪Loc. A groundterm is simply a term t, but with no Arcum variables in it.

We use θ to denote a substitution mapping Arcum variables to ground terms, and weuse Θ to represent the set of all substitutions. Given a variable V , we use θ(V ) to denotethe ground term that θ maps V to. We also use θ(·) to represent substitution applicationfor patterns. In particular, given a pattern p and a substitution θ, we use θ(p) to representthe ground term produced by taking p and replacing each variable V in p with θ(V ). Forexample, if θ is [A 7→ a+b] and p is x:=A, then θ(p) is the AST for x:=a+b. We also useθ[x 7→ y] to represent the substitution identical to θ, but with x mapping to y.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 44: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

44 · Macneil Shonle et al.

B.3 Predicate-Solver Semantics

Given a Featherweight Arcum program A, the predicate solver computes a result-set, whichis a set of facts f , with each f taken from the set of all facts FactA:

FactA = {p(t1, . . . , tk) | p ∈ PredNameA∧ (t1, . . . , tk) ∈ GroundTermk}

A result-set d is therefore just a subset of FactA. The set of all result-sets is DA = P (FactA),that is to say the powerset of FactA. The predicate-solver semantics for A is a functionJAK : Π → DA, which given a source program π computes the set of facts that hold for it.

JAK operates by starting with an empty result-set, and iteratively adding more and morefacts to this set. The operation of adding facts to the result set is formalized using a functionFA : Π→DA →DA. Given a source program π, FA(π) is a function of type DA →DA. ThisFA(π) function takes the current result set, and returns the “next” result set, which includesnewly inferred facts. Intuitively, FA adds a fact to the result-set if there is a definitiondef p(. . .){ψ} in the Featherweight Arcum program A for which ψ holds given the currentresult-set. This is formalized in the following definition:

FA(π)(d) = {p(θ(t1), . . . ,θ(tk)) | (def p(. . .){ψ}) ∈ A∧ JψK(θ,d,π)}

The meaning of a predicate-body ψ is given by the function JψK : Θ×DA ×Π → bool.Intuitively, JψK(θ,d,π) is true iff the predicate resulting from applying θ to ψ holds onthe program π, given the current result-set d. The following definition makes this notionprecise (recall that π(l) is the AST node at location l):

DEFINITION 1. The meaning function JψK : Θ×DA×Π→ bool of a predicate-body ψ

is defined as:

Jψ1 && ψ2K(θ,d,π) = Jψ1K(θ,d,π)∧ Jψ2K(θ,d,π)Jψ1 || ψ2K(θ,d,π) = Jψ1K(θ,d,π)∨ Jψ2K(θ,d,π)Jp(t1, . . . , tk)K(θ,d,π) = p(Jt1K(θ,π), . . . ,JtkK(θ,π)) ∈ dJprim(t1, . . . , tk)K(θ,d,π) = prim(Jt1K(θ,π), . . . ,JtkK(θ,π)) ∈ Prims(π)Jforall(V : τ){ψ}K(θ,d,π) = ∀t : τ . JψK(θ[V 7→ t],d,π)Jexists(V : τ){ψ}K(θ,d,π) = ∃t : τ . JψK(θ[V 7→ t],d,π)Jt1 == t2K(θ,d,π) = Jt1K(θ,π) = Jt2K(θ,π)

where the semantics of a term t on a program π under substitution θ is given by the functionJtK : Θ×Π → GroundTerm, which is defined as:

JCodePatternK(θ,π) = θ(CodePattern)JLocVarK(θ,π) = π(θ(LocVar))

In the above definition, Prims(π) is the set of primitive predicates for the source programπ. For example, it would contain all the isA, hasMethod, etc. relations for the program π.

Least Fixed Point Semantics

Given a function F : D → D, where D is a partially ordered set with ordering ≤, we uselfp≤(F) to denote the least fixed point of F , which is the least element x (according to ≤)satisfying x = F(x).

Finally, we are ready to define the predicate-solver semantics, which is given as follows:

JAK(π) = KeepMatchFacts(lfp⊆(FA(π)))ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 45: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 45

where KeepMatchFacts(d) = {p(t1, . . . , tk) | p(t1, . . . , tk) ∈ d∧ p ∈ MatchPredNameA}.In the above definition, KeepMatchFacts is used to filter out all computed facts that are

not concepts (that is to say, filter out all internal predicates, such as hasA in Figure 6).In practice, one can implement JAK(π) by starting with the empty set of facts, and thenrepeatedly applying FA until no more changes occur.

B.4 Transformation-Engine Semantics

We now define the semantics of transforming a source program from one option to another.Let A1 be the Featherweight Arcum program that corresponds to original option, and A2 bethe Featherweight Arcum program that corresponds to the option we are transforming to(recall that we model different options by using separate Featherweight Arcum programs,each containing only the match expressions from a given option).

Let π1 = 〈r, loc1〉 be the original program, and let M be the set of program locationsmentioned in JA1K(π1), namely M = {l | p(l, . . .) ∈ JA1K(π1)}. The program locations inM are the ones that will potentially be modified. Starting with π1, the program producedby going from option A1 to A2 is the program π2 = 〈r′, loc2〉 that satisfies the followingtwo properties:

(1) JA1K(π1) = JA2K(π2)

(2) r ∼ r′, where ∼ is a relation on AST nodes defined as follows:

n ∼ n′ ,

{L(n) = L(n′)∧C(n)∼C(n′) if loc1(n) 6∈ Mloc1(n) = loc2(n′) if loc1(n) ∈ M

Note that we implicitly lift ∼ to lists in the natural way, so that C(n) ∼C(n′) is the con-junction of pairwise application of ∼ on the children of n and n′. The intuition in the abovedefinition is that for locations that are not part of any concepts (locations not in M), wesimply enforce deep structural equality, whereas for locations that are part of a concept(locations in M), we force the locations to be equal. The fact that the locations of thosenodes are forced to be equal, combined with JA1K(π1) = JA2K(π2), forces the transforma-tions to be performed. This is best clarified with an example, which we cover next.

B.5 Example

As an example, consider the following two Arcum programs A1 and A2 with a single con-cept PlusConcept for which there are two options (represented by A1 and A2):

A1 = match PlusConcept(E,A,B) { E == [A + B] }A2 = match PlusConcept(E,A,B) { E == [Plus(A,B)] }

Now consider π1 to be the simple program x := 1+2; y := 3+4. This is formalizedas π1 = 〈r, loc1〉, where the following defines node r (as well as the other nodes n0 through

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 46: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

46 · Macneil Shonle et al.

n9 of the program), and the locations loc1 of all these nodes:

L(r) = “Sequence” C(r) = [n0,n5] loc1(r) = l0L(n0) = “Assign” C(n2) = [n1,n2] loc1(n0) = l1L(n1) = “x” C(n1) = [] loc1(n1) = l2L(n2) = “+ ” C(n2) = [n3,n4] loc1(n4) = l3L(n3) = “1” C(n3) = [] loc1(n3) = l4L(n4) = “2” C(n4) = [] loc1(n4) = l5L(n5) = “Assign” C(n5) = [n6,n7] loc1(n7) = l6L(n6) = “y” C(n6) = [] loc1(n6) = l7L(n7) = “+ ” C(n7) = [n8,n9] loc1(n9) = l8L(n8) = “3” C(n8) = [] loc1(n8) = l9L(n9) = “4” C(n9) = [] loc1(n9) = l10

The solver would find the following solution for A1 running on π1:

JA1K(π1) = {PlusConcept(l3,n3,n4),PlusConcept(l8,n8,n9)}

According to the definition in Section B.4, the transformed program π2 = 〈r′, loc2〉 needsto satisfy JA2K(π2) = JA1K(π1) and r ∼ r′. The program π2 that satisfies this is:

L(r′) = “Sequence” C(r′) = [n′0,n′5] loc(r′) = l′0

L(n′0) = “Assign” C(n′2) = [n′1,n′2] loc(n′0) = l′2

L(n′1) = “x” C(n′1) = [] loc(n′1) = l′3L(n′2) = “Call Plus” C(n′2) = [n3,n4] loc(n′2) = l3L(n3) = “1” C(n3) = [] loc(n3) = l′4L(n4) = “2” C(n4) = [] loc(n4) = l′5L(n′5) = “Assign” C(n′5) = [n′6,n

′7] loc(n′5) = l′6

L(n′6) = “y” C(n′6) = [] loc(n′6) = l′7L(n′7) = “Call Plus” C(n′7) = [n8,n9] loc(n′7) = l8L(n8) = “3” C(n8) = [] loc(n8) = l′9L(n9) = “4” C(n9) = [] loc(n9) = l′10

The set of locations mentioned in JA1K(π1) is M = {l3, l8}, and so according to thedefinition of ∼, the condition r ∼ r′ expands to the following constraints:

L(r′) = L(r)∧L(n0) = L(n′0)∧L(n1) = L(n′1)∧ loc1(n2) = loc2(n′2) ∧L(n5) = L(n′5)∧L(n6) = L(n′6)∧ loc1(n7) = loc2(n′7)

Note that from loc1(n2) = loc2(n′2), we get loc1(n′2) = l3, which forces n′2 to be at lo-cation l3. Furthermore, from JA2K(π2) = JA1K(π1), we know that PlusConcept(l3,n3,n4)must belong to the set JA2K(π2) – in other words, in the transformed program, there must bea PlusConcept at location l3 according to A2. This is what forces the “Call Plus” node atlocation l3 in the transformed program. A similar situation forces there to be a “Call Plus”node at location l8.

REFERENCES

ABITEBOUL, S., HULL, R., AND VIANU, V. 1995. Foundations of Databases. Addison-Wesley.AIKEN, A. AND FAHNDRICH, M. 1997. Program analysis using mixed term and set constraints. In Proceedings

of the 4th International Symposium on Static Analysis (SAS). Vol. 1503. Paris France.ALT, M. AND MARTIN, F. 1995. Generation of efficient interprocedural analyzers with PAG. In Proceedings of

the Second International Static Analysis Symposiu m. LNCS, vol. 983. Springer-Verlag, 33–50.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 47: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 47

BABICH, W. AND JAZAYERI, M. 1978a. The method of attributes for data flow analysis, part I: Exhaustiveanalysis. Acta Informatica 10, 3 (Oct.), 245–264.

BABICH, W. AND JAZAYERI, M. 1978b. The method of attributes for data flow analysis, part II: Demandanalysis. Acta Informatica 10, 3 (Oct.), 265–272.

BALABAN, I., TIP, F., AND FUHRER, R. 2005. Refactoring support for class library migration. In OOPSLA’05: Proceedings of the 20th annual ACM SIGPLAN conference on Object oriented programming, systems,languages, and applications. ACM Press, New York, NY, USA, 265–279.

BALL, T., MAJUMDAR, R., MILLSTEIN, T., AND RAJAMANI, S. K. 2001. Automatic predicate abstraction ofC programs. In Proceedings of the ACM SIGPLAN 2001 Conference on Programming Language Design andImplementation. Snowbird, Utah.

BANCILHON, F. AND SPYRATOS, N. 1981. Update semantics of relational views. ACM Trans. DatabaseSyst. 6, 4, 557–575.

BARBOSA, D. M. J., CRETIN, J., FOSTER, N., GREENBERG, M., AND PIERCE, B. C. 2010. Matching lenses:Alignment and view update. In ACM SIGPLAN International Conference on Functional Programming (ICFP),Baltimore, Maryland.

BAXTER, I. D., PIDGEON, C., AND MEHLICH, M. 2004. Dms: Program transformations for practical scalablesoftware evolution. In ICSE ’04: Proceedings of the 26th International Conference on Software Engineering.IEEE Computer Society, Washington, DC, USA, 625–634.

BERNDL, M., LHOTAK, O., QIAN, F., HENDREN, L., AND UMANEE, N. 2003. Points-to analysis using BDDs.In PLDI ’03: Proceedings of the ACM SIGPLAN 2003 Conference on Programming Language Design andImplementation. ACM Press, 103–114.

BOHANNON, A., FOSTER, J. N., PIERCE, B. C., PILKIEWICZ, A., AND SCHMITT, A. 2008. Boomerang:Resourceful lenses for string data. In ACM SIGPLAN–SIGACT Symposium on Principles of ProgrammingLanguages (POPL), San Francisco, California.

BOSHERNITSAN, M. 2006. Program manipulation via interactive transformations. Ph.D. thesis, University ofCalifornia at Berkeley, Berkeley, CA, USA.

BOSHERNITSAN, M. AND GRAHAM, S. L. 2004. ixj: interactive source-to-source transformations for java. InOOPSLA ’04: Companion to the 19th annual ACM SIGPLAN conference on Object-oriented programmingsystems, languages, and applications. ACM, New York, NY, USA, 212–213.

BRAVENBOER, M., KALLEBERG, K. T., VERMAAS, R., AND VISSER, E. 2008. Stratego/xt 0.17. a languageand toolset for program transformation. Sci. Comput. Program. 72, 1-2, 52–70.

BRYANT, A., CATTON, A., VOLDER, K. D., AND MURPHY, G. C. 2002. Explicit programming. In AOSD ’02:Proceedings of the 1st international conference on Aspect-oriented software development. 10–18.

BRYANT, R. E. 1992. Symbolic boolean manipulation with ordered binary-decision diagrams. ACM ComputingSurveys 24, 3 (Sept.), 293–318.

BUDINSKY, F., BRODSKY, S. A., AND MERKS, E. 2003. Eclipse Modeling Framework. Pearson Education.BURCH, J., CLARKE, E., MCMILLAN, K., DILL, D., AND HWANG, L. 1992. Symbolic model checking: 1020

states and beyond. Information and Computation 98, 2, 142–170.CARROLL, M. D. AND RYDER, B. G. 1988. Incremental data flow analysis via dominator and attribute updates.

In Proceedings of the 15th SIGPLAN-SIGACT Symposium on Principles of Programming Languages.CLEMENTS, P. AND NORTHROP, L. 2001. Software product lines: practices and patterns. Addison-Wesley

Longman Publishing Co., Inc., Boston, MA, USA.CLIFTON, C., LEAVENS, G. T., CHAMBERS, C., AND MILLSTEIN, T. 2000. Multijava: modular open classes

and symmetric multiple dispatch for java. In OOPSLA ’00: Proceedings of the 15th ACM SIGPLAN conferenceon Object-oriented programming, systems, languages, and applications. ACM, New York, NY, USA, 130–145.

COLYER, A. AND CLEMENT, A. 2004. Large-scale aosd for middleware. In Proceedings of the 3rd internationalconference on Aspect-oriented software development. AOSD ’04. ACM, New York, NY, USA, 56–65.

COUSOT, P. AND COUSOT, R. 1977. Abstract interpretation: A unified lattice model for static analysis of pro-grams by construction or approximation of fixpoints. In Proceedings of the 4th ACM Symposium on Principlesof Programming Languages. Los Angeles CA, 238–252.

COUSOT, P. AND COUSOT, R. 1979. Systematic design of program analysis frameworks. In Proceedings of the6th ACM Symposium on Principles of Programming Languages. San Antonio, Texas, 269–282.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 48: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

48 · Macneil Shonle et al.

DAS, M., LERNER, S., AND SEIGLE, M. 2002. Esp: Path-sensitive program verification in polynomial time. InProceedings of the ACM SIGPLAN 2002 Conference on Programming Language Design and Implementation.

DEMERS, A., REPS, T., AND TEITELBAUM, T. 1981. Incremental evaluation for attribute grammars withapplication to syntax-directed editors. In Proceedings of the 8th SIGPLAN-SIGACT Symposium on Principlesof Programming Languages. Williamsburg VA.

DENNETT, D. C. 1992. Consciousness Explained. Back Bay Books.DWYER, M. B. AND CLARKE, L. A. 1998. A flexible architecture for building data flow analyzers. In 18th

International Conference on Software Engineering. Berlin, Germany, 554–564.FAHNDRICH, M., FOSTER, J. S., SU, Z., AND AIKEN, A. 1998. Partial online cycle elimination in inclu-

sion constraint graphs. In PLDI ’98: Proceedings of the ACM SIGPLAN 1998 conference on Programminglanguage design and implementation. 85–96.

FOSTER, J. N., GREENWALD, M. B., MOORE, J. T., PIERCE, B. C., AND SCHMITT, A. 2007. Combinatorsfor bidirectional tree transformations: A linguistic approach to the view-update problem. ACM Transactionson Programming Languages and Systems 29, 3 (May), 17.

FOSTER, J. N., PILKIEWICZ, A., AND PIERCE, B. C. 2008. Quotient lenses. In ACM SIGPLAN InternationalConference on Functional Programming (ICFP), Victoria, Canada.

GAFTER, N. 2006. Super type tokens. http://gafter.blogspot.com/2006/12/super-type-tokens.html.GAMMA, E., HELM, R., JOHNSON, R., AND VLISSIDES, J. 1995. Design Patterns: Elements of Reusable

Object-Oriented Software. Addison-Wesley.GOOGLE. 2007. Google collections library 0.5 (alpha). http://code.google.com/p/google-collections/.GOSLING, J., JOY, B., STEELE, G., AND BRACHA, G. 2005. The Java Language Specification, Third ed.

Addison-Wesley.GRISWOLD, W. G. 2001. Coping with crosscutting software changes using information transparency. In RE-

FLECTION ’01: Proceedings of the Third International Conference on Metalevel Architectures and Separa-tion of Crosscutting Concerns. Springer-Verlag, London, UK, 250–265.

GRISWOLD, W. G., SULLIVAN, K., SONG, Y., SHONLE, M., TEWARI, N., CAI, Y., AND RAJAN, H. 2006.Modular software design with crosscutting interfaces. IEEE Software 23, 1, 51–60.

HANNEMANN, J. AND KICZALES, G. 2002. Design pattern implementation in java and aspectj. In OOPSLA ’02:Proceedings of the 17th ACM SIGPLAN conference on Object-oriented programming, systems, languages, andapplications. 161–173.

HANNEMANN, J., MURPHY, G. C., AND KICZALES, G. 2005. Role-based refactoring of crosscutting concerns.In AOSD ’05. 135–146.

HU, Z., MU, S.-C., AND TAKEICHI, M. 2004. A programmable editor for developing structured documentsbased on bidirectional transformations. In PEPM ’04: Proceedings of the 2004 ACM SIGPLAN symposium onPartial evaluation and semantics-based program manipulation. ACM, New York, NY, USA, 178–189.

KAWANAKA, S. AND HOSOYA, H. 2006. biXid: a bidirectional transformation language for XML. In ICFP ’06:Proceedings of the 11th ACM SIGPLAN International Conference on Functional Programming. 201–214.

KENNEDY, A. J. 2004. Functional pearl pickler combinators. J. Funct. Program. 14, 6, 727–739.KICZALES, G., HILSDALE, E., HUGUNIN, J., KERSTEN, M., PALM, J., AND GRISWOLD, W. 2001a. Getting

started with aspectj. Commun. ACM 44, 10, 59–65.KICZALES, G., HILSDALE, E., HUGUNIN, J., KERSTEN, M., PALM, J., AND GRISWOLD, W. G. 2001b. An

overview of AspectJ. In ECOOP 2001. 327–353.KICZALES, G., LAMPING, J., MENDHEKAR, A., MAEDA, C., LOPES, C., LOINGTIER, J., AND IRWIN, J.

1997. Aspect-oriented programming. In ECOOP. 220–242.KOTIK, G. AND MARKOSIAN, L. 1989. Automating software analysis and testing using a program transforma-

tion system. In TAV3: Proceedings of the ACM SIGSOFT ’89 third symposium on Software testing, analysis,and verification. ACM Press, New York, NY, USA, 75–84.

KOZACZYNSKI, W., NING, J., AND ENGBERTS, A. 1992. Program concept recognition and transformation.IEEE Trans. Softw. Eng. 18, 12, 1065–1075.

LACEY, D., JONES, N. D., WYK, E. V., AND FREDERIKSEN, C. C. 2002. Proving correctness of compiler op-timizations by temporal logic. In Proceedings of the 29th ACM SIGPLAN-SIGACT Symposium on Principlesof Programming Languages. Portland, Oregon.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 49: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

A Framework for the Checking and Refactoring of Crosscutting Concepts · 49

LERNER, S., MILLSTEIN, T., RICE, E., AND CHAMBERS, C. 2005. Automated soundness proofs for dataflowanalyses and transformations via local rules. In POPL ’05: Proceedings of the 32nd ACM SIGPLAN-SIGACTSymposium on Principles of Programming Languages. ACM Press, New York, NY, USA, 364–377.

LIEBERHERR, K. J. 1996. Adaptive Object-Oriented Software: The Demeter Method with Propagation Patterns.PWS Publishing Company, Boston.

LIEBERHERR, K. J. AND ORLEANS, D. 1997. Preventive program maintenance in Demeter/Java (researchdemonstration). In International Conference on Software Engineering. ACM Press, Boston, MA, 604–605.

LIU, J., BATORY, D., AND LENGAUER, C. 2006. Feature oriented refactoring of legacy applications. In ICSE’06: Proceeding of the 28th international conference on Software engineering. 112–121.

MARIN, M., MOONEN, L., AND VAN DEURSEN, A. 2005. An approach to aspect refactoring based on cross-cutting concern types. In MACS ’05: Proceedings of the 2005 workshop on Modeling and analysis of concernsin software. ACM Press, New York, NY, USA, 1–5.

MARTIN, M., LIVSHITS, B., AND LAM, M. S. 2005. Finding application errors and security flaws using pql: aprogram query language. SIGPLAN Not. 40, 10, 365–383.

MASTICOLA, S. P., MARLOWE, T. J., AND RYDER, B. G. 1995. Lattice frameworks for multisource andbidirectional data flow problems. ACM Transactions on Programming Langauges and Systems 17, 5 (Sept.),777–803.

METSKER, S. AND WAKE, W. C. 2006. Design Patterns in Java. Addison-Wesley.MOOR, O. D., VERBAERE, M., HAJIYEV, E., AVGUSTINOV, P., EKMAN, T., ONGKINGCO, N., SERENI, D.,

AND TIBBLE, J. 2007. Keynote address: .ql for source code analysis. Source Code Analysis and Manipulation,2007. SCAM 2007. Seventh IEEE International Working Conference on, 3–16.

MORGAN, C., VOLDER, K. D., AND WOHLSTADTER, E. 2007. A static aspect language for checking designrules. In AOSD ’07. 63–72.

NITA, M. AND NOTKIN, D. 2010. Using twinning to adapt programs to alternative apis. In ICSE ’10: Proceed-ings of the 32nd ACM/IEEE International Conference on Software Engineering. 205–214.

NYSTROM, N., CLARKSON, M., AND MYERS, A. 2003. Polyglot: An extensible compiler framework for java.ORLEANS, D. AND LIEBERHERR, K. J. 2001. Dj: Dynamic adaptive programming in java. In REFLECTION

’01: Proceedings of the Third International Conference on Metalevel Architectures and Separation of Cross-cutting Concerns. Springer-Verlag, London, UK, 73–80.

PARNAS, D. L. 1972. On the criteria to be used in decomposing systems into modules. Commun. ACM 15, 12,1053–1058.

PARNAS, D. L. 2001. Software fundamentals: collected papers by David L. Parnas. Addison-Wesley LongmanPublishing Co., Inc., Chapter On the design and development of program families, 193–213.

REICHENBACH, C., COUGHLIN, D., AND DIWAN, A. 2009. Program metamorphosis. In Genoa: Proceedingsof the 23rd European Conference on ECOOP 2009 — Object-Oriented Programming. Springer-Verlag, Berlin,Heidelberg, 394–418.

REPS, T. W. 1994. Demand interprocedural program analysis using logic databases. In Applications of LogicDatabases, R. Ramakrishnan, Ed. Kluwer Academic Publishers, Boston MA, USA, 163–196.

ROBERTS, D. B. 1999. Practical analysis for refactoring. Ph.D. thesis, University of Illinois at Urbana-Champaign, Champaign, IL, USA. Adviser-Johnson, Ralph.

SHANKAR, A. AND BODIK, R. 2007. Ditto: automatic incrementalization of data structure invariant checks (injava). In PLDI ’07: Proceedings of the 2007 ACM SIGPLAN conference on Programming language designand implementation. 310–319.

SHONLE, M. 2007. Modular-like transformations and style checking for crosscutting programming concepts.In ICSE COMPANION ’07: Companion to the proceedings of the 29th International Conference on SoftwareEngineering. IEEE Computer Society, Washington, DC, USA, 95–96.

SHONLE, M., GRISWOLD, W. G., AND LERNER, S. 2007. Beyond refactoring: a framework for modularmaintenance of crosscutting design idioms. In ESEC-FSE ’07: Proceedings of the the 6th joint meeting of theEuropean software engineering conference and the ACM SIGSOFT symposium on The foundations of softwareengineering. ACM, New York, NY, USA, 175–184.

SHONLE, M., GRISWOLD, W. G., AND LERNER, S. 2008a. Addressing common crosscutting problems witharcum. In 8th ACM SIGPLAN-SIGSOFT Workshop on Program Analysis for Software Tools and Engineering.

ACM Journal Name, Vol. V, No. N, Month 20YY.

Page 50: A Framework for the Checking and Refactoring of ...cseweb.ucsd.edu/~wgg/Statements/arcum-journal.pdf · A Framework for the Checking and Refactoring of Crosscutting Concepts ... is

50 · Macneil Shonle et al.

SHONLE, M., GRISWOLD, W. G., AND LERNER, S. 2008b. When refactoring acts like modularity: Keepingoptions open with persistent condition checking. In Second Workshop on Refactoring Tools.

SIMONYI, C. 1995. The death of computer languages, the birth of intentional programming. Tech. Rep. MSR-TR-95-52, Microsoft Research.

SITTAMPALAM, G., DE MOOR, O., AND LARSEN, K. F. 2004. Incremental execution of transformation spec-ifications. In POPL ’04:Proceedings of the 31st ACM SIGPLAN-SIGACT Symposium on Principles of Pro-gramming Languages. ACM, New York, NY, USA, 26–38.

STEFFEN, B. 1991. Data flow analysis as model checking. In Theoretical Aspects of Computer Science (TACS),Sendai (Japan), T. Ito and A. Meyer, Eds. Lecture Notes in Computer Science (LNCS), vol. 526. Springer-Verlag, 346–364.

STEFFEN, J. 1985. Interactive examination of a c program with cscope. In Proceedings of the 1985 WinterUsenix Conference, Dallas, TX.

SULLIVAN, K., GRISWOLD, W. G., SONG, Y., CAI, Y., SHONLE, M., TEWARI, N., AND RAJAN, H. 2005.Information hiding interfaces for aspect-oriented design. In ESEC/FSE-13: Proceedings of the 10th Europeansoftware engineering conference held jointly with 13th ACM SIGSOFT international symposium on Founda-tions of software engineering. New York, NY, USA, 166–175.

TARR, P., OSSHER, H., AND SUTTON, JR., S. M. 2002. Hyper/j: multi-dimensional separation of concerns forjava. In ICSE ’02. 689–690.

TILEVICH, E. AND BACK, G. 2008. “Program, enhance thyself!” – demand-driven pattern-oriented programenhancement,”. In AOSD ’08.

TIP, F., KIEZUN, A., AND BAUMER, D. 2003. Refactoring for generalization using type constraints. In OOPSLA’03. 13–26.

TJIANG, S. W. K. AND HENNESSY, J. L. 1992. Sharlit – A tool for building optimizers. In Proceedings of theACM SIGPLAN 1992 Conference on Programming Language Design and Implementation. 82–93.

VENKATESH, G. A. AND FISCHER, C. N. 1992. SPARE: A development environment for program analysisalgorithms. IEEE Transactions on Software Engineering 18, 4 (Apr.), 304–318.

VERBAERE, M., ETTINGER, R., AND DE MOOR, O. 2006. Jungl: a scripting language for refactoring. In ICSE’06. 172–181.

VON DINCKLAGE, D. 2003. Making patterns explicit with metaprogramming. In GPCE ’03: Proceedings of the2nd international conference on Generative programming and component engineering. Springer-Verlag NewYork, Inc., New York, NY, USA, 287–306.

WHALEY, J., AVOTS, D., CARBIN, M., AND LAM, M. S. 2005. Using Datalog and binary decision diagramsfor program analysis. In Proceedings of the 3rd Asian Symposium on Programming Languages and Systems,K. Yi, Ed. LNCS, vol. 3780. Springer-Verlag.

WHALEY, J. AND LAM, M. S. 2004. Cloning-based context-sensitive pointer alias analysis using binary decisiondiagrams. In Proceedings of the Conference on Programming Language Design and Implementation.

WHITFIELD, D. L. AND SOFFA, M. L. 1997. An approach for exploring code improving transformations. ACMTransactions on Programming Languages and Systems 19, 6 (Nov.), 1053–1084.

XIONG, Y., LIU, D., HU, Z., ZHAO, H., TAKEICHI, M., AND MEI, H. 2007. Towards automatic model synchro-nization from model transformations. In ASE ’07: Proceedings of the twenty-second IEEE/ACM internationalconference on Automated software engineering. ACM, New York, NY, USA, 164–173.

YI, K. AND HARRISON III, W. L. 1993. Automatic generation and management of interprocedural programanalyses. In Proceedings of the 20th ACM SIGPLAN-SIGACT Symposium on Principles of ProgrammingLanguages. 246–259.

Received Month 20XX;

ACM Journal Name, Vol. V, No. N, Month 20YY.