1
XAspectsAn Extensible System for Domain-
Specific Aspect Languages
Macneil Shonle (UCSD)
Karl Lieberherr (Northeastern University)
Ankit Shah (Northeastern University)
2
Talk Overview
What is Aspect-Oriented Programming Limits of general purpose AOP languages How domain-specific languages can address
these limits The problems with integrating several
domain-specific solutions Solution: Allow principled extensions to a
general purpose AOP language by using XAspects
3
Modular Programming
Every concern goes into its own module
Try to limit coupling between modules
4
Limitations of Modular Programming
Some concerns crosscut module boundaries.
Concerns become tangled. Example: logging, thread synchronization, caching, object marshalling
5
Aspect-Oriented Programming
Encapsulate crosscutting concerns by writing separate aspects.
Aspects then get woven back into the program.
6
Weaving
Can happen at run time or compile time.
weave
7
public class Shape implements ShapeI { protected AdjustableLocation loc; protected AdjustableDimension dim; public Shape() { loc = new AdjustableLocation(0, 0); dim = new AdjustableDimension(0, 0); } double get_x() throws RemoteException { return loc.x(); } void set_x(int x) throws RemoteException { loc.set_x(); } double get_y() throws RemoteException { return loc.y(); } void set_y(int y) throws RemoteException { loc.set_y(); } double get_width() throws RemoteException { return dim.width(); } void set_width(int w) throws RemoteException { dim.set_w(); } double get_height() throws RemoteException { return dim.height(); } void set_height(int h) throws RemoteException { dim.set_h(); } void adjustLocation() throws RemoteException { loc.adjust(); } void adjustDimensions() throws RemoteException { dim.adjust(); }}
class AdjustableLocation { protected double x_, y_; public AdjustableLocation(double x, double y) { x_ = x; y_ = y; } synchronized double get_x() { return x_; } synchronized void set_x(int x) {x_ = x;} synchronized double get_y() { return y_; } synchronized void set_y(int y) {y_ = y;} synchronized void adjust() { x_ = longCalculation1(); y_ = longCalculation2(); }}class AdjustableDimension { protected double width_=0.0, height_=0.0; public AdjustableDimension(double h, double w) { height_ = h; width_ = w; } synchronized double get_width() { return width_; } synchronized void set_w(int w) {width_ = w;} synchronized double get_height() { return height_; } synchronized void set_h(int h) {height_ = h;} synchronized void adjust() { width_ = longCalculation3(); height_ = longCalculation4(); }}
interface ShapeI extends Remote { double get_x() throws RemoteException ; void set_x(int x) throws RemoteException ; double get_y() throws RemoteException ; void set_y(int y) throws RemoteException ; double get_width() throws RemoteException ; void set_width(int w) throws RemoteException ; double get_height() throws RemoteException ; void set_height(int h) throws RemoteException ; void adjustLocation() throws RemoteException ; void adjustDimensions() throws RemoteException ;}
D: The First Aspect Language(Crista Lopes, 1995)
Red text are synchronization concerns
Green text are Remote Method Invocation concerns
In this Java program, the concerns are tangled
8
public class Shape implements ShapeI { protected AdjustableLocation loc; protected AdjustableDimension dim; public Shape() { loc = new AdjustableLocation(0, 0); dim = new AdjustableDimension(0, 0); } double get_x() throws RemoteException { return loc.x(); } void set_x(int x) throws RemoteException { loc.set_x(); } double get_y() throws RemoteException { return loc.y(); } void set_y(int y) throws RemoteException { loc.set_y(); } double get_width() throws RemoteException { return dim.width(); } void set_width(int w) throws RemoteException { dim.set_w(); } double get_height() throws RemoteException { return dim.height(); } void set_height(int h) throws RemoteException { dim.set_h(); } void adjustLocation() throws RemoteException { loc.adjust(); } void adjustDimensions() throws RemoteException { dim.adjust(); }}
class AdjustableLocation { protected double x_, y_; public AdjustableLocation(double x, double y) { x_ = x; y_ = y; } synchronized double get_x() { return x_; } synchronized void set_x(int x) {x_ = x;} synchronized double get_y() { return y_; } synchronized void set_y(int y) {y_ = y;} synchronized void adjust() { x_ = longCalculation1(); y_ = longCalculation2(); }}class AdjustableDimension { protected double width_=0.0, height_=0.0; public AdjustableDimension(double h, double w) { height_ = h; width_ = w; } synchronized double get_width() { return width_; } synchronized void set_w(int w) {width_ = w;} synchronized double get_height() { return height_; } synchronized void set_h(int h) {height_ = h;} synchronized void adjust() { width_ = longCalculation3(); height_ = longCalculation4(); }}
interface ShapeI extends Remote { double get_x() throws RemoteException ; void set_x(int x) throws RemoteException ; double get_y() throws RemoteException ; void set_y(int y) throws RemoteException ; double get_width() throws RemoteException ; void set_width(int w) throws RemoteException ; double get_height() throws RemoteException ; void set_height(int h) throws RemoteException ; void adjustLocation() throws RemoteException ; void adjustDimensions() throws RemoteException ;}
public class Shape { protected double x_= 0.0, y_= 0.0; protected double width_=0.0, height_=0.0;
double get_x() { return x_(); } void set_x(int x) { x_ = x; } double get_y() { return y_(); } void set_y(int y) { y_ = y; } double get_width(){ return width_(); } void set_width(int w) { width_ = w; } double get_height(){ return height_(); } void set_height(int h) { height_ = h; } void adjustLocation() { x_ = longCalculation1(); y_ = longCalculation2(); } void adjustDimensions() { width_ = longCalculation3(); height_ = longCalculation4(); }}
coordinator Shape { selfex adjustLocation, adjustDimensions; mutex {adjustLocation, get_x, set_x, get_y, set_y}; mutex {adjustDimensions, get_width, get_height, set_width, set_height};}
portal Shape { double get_x() {} ; void set_x(int x) {}; double get_y() {}; void set_y(int y) {}; double get_width() {}; void set_width(int w) {}; double get_height() {}; void set_height(int h) {}; void adjustLocation() {}; void adjustDimensions() {};}
D: The First Aspect Language(Crista Lopes, 1995)
Instead of writing this
Write this
Concerns are now separated
9
From D to AspectJ
While the D language only handled synchronization and marshalling concerns it was the inspiration for the AspectJ language.
AspectJ is targeted for general crosscutting concerns…
10
A General Purpose AOPL
AspectJ is an aspect-oriented extension to Java that allows for crosscutting concerns to be decomposed into aspects.
AspectJ supports two models of separation of concerns: The Join-Point Model (dynamic) Inter-Type Declarations (static)
11
The AspectJ Language
aspect Logging {pointcut publicMethods():
execution(public * mypackage..*(..));Object around(): publicMethods() {
System.out.println("Entering " + thisJoinPointStaticPart);Object o = proceed();System.out.println("Leaving " + thisJoinPointStaticPart
+ " returning " + o);return o;
}}
Join Point Model: Pick out dynamic events when program is running and advise these events.
12
The AspectJ Language
Inter-Type Declarations – makes classes “open.” Keep similar methods and data together. Can make
parts of the implementation aspect private.
aspect Rendering {public void Particle.draw(Graphics g) { …}
public void Wall.draw(Graphics g) { …}
public void Vector.draw(Graphics g) { …}
}
13
Separating a Concern:The Visitor Pattern
We want to visit every Book instance from a University instance. This requires two new methods.
AspectJ can encapsulate the visitor pattern in a single aspect by using inter-type declarations.
University
Library
Book
University.visitBooks(BookVisitor v)Library.visitBooks(BookVisitor v)
14
The Visitor Pattern
When the class graph is changed, new methods need to be added, and existing ones modified.
University
College
Library
Shelve
Book
University.visitBooks(BookVisitor v)College.visitBooks(BookVisitor v)Library.visitBooks(BookVisitor v)Shelve.visitBooks(BookVisitor v)
15
The Visitor Pattern
Even though the aspect is encapsulated its still highly coupled to the class graph.
It is coupled because the visitor concern duplicates information found in the class graph.
University
College
Library
Shelve
Book
University.visitBooks(BookVisitor v)College.visitBooks(BookVisitor v)Library.visitBooks(BookVisitor v)Shelve.visitBooks(BookVisitor v)
16
The DAJ Language
A domain-specific aspect language can solve the structure dependence problem.
University
Library
Book
University
College
Library
Shelve
Book
declare traversal: void visitBooks(): “from University to Book” (BookVisitor);
One declaration for this concern instead of four methods.
Reduced redundant information.
17
The DAJ Language
Only by using reflection can a structure-shy solution for visitors in AspectJ work because the class graph needs to be known.
The DAJ compiler itself is able to compute the class graph at compile time.
The user of DAJ needs only specify the traversal requirements (e.g. where to start/end the path, what fields to bypass, what fields a visitor must go through, etc. )
Karl:
Delete this slide.
Karl:
Delete this slide.
18
Domain-Specific Solutions
Domain-specific solutions allow decomposition on a level unachievable with object-oriented or even general purpose aspect-oriented languages.
When applied to the right problems these solutions increase productivity, the problems can be more complex, and the quality can be improved.
One highly successful example are parser generator tools.
19
Karl remarks
Parser Generator Tool? Is this the right word?
Data Binding Tool seems better: JAXB is in this category and won the 2003 Java World Editor’s Choice Award (along with AspectJ)
Data Binding Tool: schema (domain-specific language) defines classes and a language along with a parser and visitors (Print, Equal, Copy, …) to process the parsed object descriptions.
20
( = depends on)
Using Multiple Solutions
Most problems cannot be solved entirely with a single domain-specific language.
Yet, using multiple domain-specific languages is also difficult unless they are all tightly integrated or are highly orthogonal.
E.g. a parser generator can be orthogonal to the rest of a program, while a traversal through the program cannot.
Parser GeneratorSynchronization
LanguageTraversal
21
Circular Dependencies
When a domain-specific solution is not orthogonal to the program then it can create circular dependencies.
Parser GeneratorSynchronization
LanguageTraversal
Multi-methods
Karl J. Lieberherr:
Example for multimethods and circular dependency on Traversal
Karl J. Lieberherr:
Example for multimethods and circular dependency on Traversal
22
Karl
We position the existence of circular dependencies as the main motivation for XAspects? Is this a good strategy? Maybe you are right.
In addition: need multiple communicating tools? other examples:
we have two traversals and the visitors refer to the “other” traversal?
We have two plug-ins, each adding to the class graph and both having traversals influenced by the addition.
tool = plug-in are synonyms
23
What Causes Circular Dependencies?
When a domain-specific plug-in needs to both create new interfaces (e.g. new types or methods) and use interfaces generated by other plug-ins.
Tool A uses interfaces generated by Tool B, but Tool B uses interfaces generated by Tool A. If A goes first, it will have compilation errors and vice versa.
If A and B are not tightly integrated, how can they both be used for the same project?
Karl J. Lieberherr:
solution = plug-in = tool? All are synonyms
Karl J. Lieberherr:
solution = plug-in = tool? All are synonyms
Karl:2
What is the difference between the two paragraphs?
Karl:2
What is the difference between the two paragraphs?
24
A Plug-In Architecture
The circular dependency problem of tools can be solved by creating a framework such that the tools communicate using the same language.
The XAspects model is a plug-in architecture to achieve this.
In XAspects, tools read Java code and write AspectJ code as the only means of communication among each other.
25
Karl
Why did we not do this 8 years ago? DemeterJ (1997) did this with the DemeterJ
weaving language but the extensibility currently in XAspects was lacking.
It is now easier with AspectJ, a more powerful weaving language.
26
Removing Dependencies
XAspects splits the two different semantics of a domain-specific language:
1. The language’s external interfaces (structural meaning)
2. The language’s generated code (behavioral meaning)
27
Karl2
Structural meaning = external interfaces: Information for other plug-ins Includes all the information other plug-ins should
know to produce their proper behavioral meaning. Could be class graph information
Behavioral meaning using information from other plug-ins Might also produce more interfaces but only
private interfaces that other plug-ins don’t have to know about.
28
Karl2
Each plug-in needs to clearly specify which context it needs because other plug-ins might modify the context.
Example: A plug-in might add nodes and edges to the class graph that a traversal should not traverse.
Open problem: How to specify the range of applicability of an aspect.
29
Compilation Phases
The XAspects model breaks compilation up into six phases:
1. Source code identification
2. Generation of external interfaces
3. Initial bytecode generation
4. Crosscutting analysis
5. Generation of semantics
6. Final bytecode generation
Karl:
External interfaces = structural meaning. Use only structural meaning.
Instead of “semantics” use behavioral meaning
Karl:
External interfaces = structural meaning. Use only structural meaning.
Instead of “semantics” use behavioral meaning
30
AJC: XAJC: PLUG-INS:
Source Code Identification
Generation of STRUCTURAL MEANING
Initial Bytecode Generation
Crosscutting Analysis
Generation of Behavioral meaning
Final Bytecode Generation
Sequence diagram for XAspects model
Karl:
Mention two phases with consistent terminology
Karl:
Mention two phases with consistent terminology
Karl:
Mention passive collaboration
Limited approach: how far does it go is a research topic
Karl:
Mention passive collaboration
Limited approach: how far does it go is a research topic
31
Source Code Identification
The XAspects compiler identifies in the source code all program text that belongs to the plug-in and provides that text to the plug-in.
aspect(Traversal) BookCollections {declare strategy: everyBook:
“from University to Book”;declare traversal: void visitBooks():
everyBook (BookVisitor);}
Traversalplug-in
32
Generation of External Interfaces
The plug-in generates source files that define the external interface introduced by the language that the plug-in implements.
aspect(Traversal) BookCollections {declare strategy: everyBook:
“from University to Book”;declare traversal: void visitBooks():
everyBook (BookVisitor);}
Traversalplug-in
XAspectsCompiler
void University.visitBooks() {} ;
Karl:
Empty impl {}
Karl:
Empty impl {}
33
Initial Bytecode Generation
The AspectJ compiler generates bytecodes from the plug-in defined external interfaces and the remainder of the program.
XAspectsCompiler
AspectJCompiler
source code+ interfacestubs
Java bytecodes
34
Crosscutting Analysis
The XAspects compiler provides each plug-in the binary of the program to perform reflection or other analysis on it.
XAspectsCompiler
AspectJCompiler
TraversalPlug-in
Java bytecodes
35
Generation of Semantics
The plug-in generates behavioral changes to the generated program in a restricted form of AspectJ code.
XAspectsCompiler
AspectJ code
TraversalPlug-in
Karl:
What can we say about the restriction? No structural meaning is generated in phase 2!
Karl:
What can we say about the restriction? No structural meaning is generated in phase 2!
36
Final Bytecode Generation
Finally, the new behavioral code is woven into the existing code to create the complete program.
XAspectsCompiler
AspectJCompiler
source code+ new AspectJcode
Final Java bytecodes
37
Implications
A plug-in only needs to know how to read Java bytecodes (or a class graph, or other slices of a whole program) and how to write AspectJ code in order to cooperate with other plug-ins.
With this technique the AspectJ language is extensible, allowing constructs to be added as if they were new language features.
38
The Need for DSALs?
We conjecture that the gap between domain-specific aspect languages and general purpose aspect languages will always exist because any general solution cannot cover all possible ways an aspect can crosscut a system. Thus, domain-specific aspect languages can be the route for better separation of concerns.
39
Related Work
Crista Lopes: COOL (ECOOP 94) and RIDL (OO in Operating Systems 95).
Czarnecki and Eisenecker: Generative Programming Book (GP)
40
Domain Specific Language (DSL)
A domain-specific language is a specialized, problem-oriented language.
Need several DSLs to specify a complete application. General modeling DSLs (e.g., synchronization) Application oriented DSL (e.g. authorization
policy)
From: GP 5.5
41
DSLs
Fixed, Separate DSLs SQL, TEX
Embedded DSLs Embedded in a general purpose language, e.g.
embedded SQL Modularly composable DSLs (component)
Encapsulated DSLs (e.g., embedded SQL) Aspectual DSLs (e.g., synchronization)
42
Aspectual DSLs
An aspectual DSL specification influences the semantics of other DSL specifications.
Implementation of modularly composable DSLs requires a common language implementation providing the necessary infrastructure for the language plug-ins (we use AspectJ).
43
Advantages
Of modularly composable over monolithic DSLs Reusability Scalability Fast feature turnover
Have to survive based on their merits
44
Related Work (continued)
Jim Hugunin: while aspect libraries can provide some domain-
specific support in a general purpose AOP language, … some domains warrant the creation of domain-specific languages …
How to extend AspectJ: XAspects is one way
45
Conclusions: XAspects
An extensible tool to use multiple AOP approaches simultaneously.
An extensible version of DemeterJ and DAJ. Works well with aspects: Data Binding, Traversal,
Visitor, Synchronization. More experimentation is needed with other aspects.
Future work: How to protect an aspect from misapplication. add more plug-ins, e.g. a multi-dispatch plug-in, re-engineer
JAXB, JAXP, JAXM, etc. Re-engineer Quo. Connections to other aspect implementations: AspectWerkz,
Nanning, JBoss, AOP Alliance, AspectC++, Jac.
Karl: drop first few slides on modularity etc. (Pengcheng)
Compare with Eclipse plug-ins.
Karl: drop first few slides on modularity etc. (Pengcheng)
Compare with Eclipse plug-ins.
Karl:
Sergei: main difference between Eclipse plug-ins and XAspect plug-ins is that in Eclipse there are fewer extension points while in XAspects we have a finely grained net of extension points (because AspectJ allows more extension points than Java does).
Karl:
Sergei: main difference between Eclipse plug-ins and XAspect plug-ins is that in Eclipse there are fewer extension points while in XAspects we have a finely grained net of extension points (because AspectJ allows more extension points than Java does).