Demeter and Aspects1 AOSD 2002 Tutorial: Demeter Aspect-Oriented Programming of Traversal Related...
-
Upload
alexina-mcdowell -
Category
Documents
-
view
231 -
download
7
Transcript of Demeter and Aspects1 AOSD 2002 Tutorial: Demeter Aspect-Oriented Programming of Traversal Related...
Demeter and Aspects 1
AOSD 2002 Tutorial:Demeter
Aspect-Oriented Programming of Traversal Related Concerns in
JavaDemeter Research Group
Demeter and Aspects 2
Overview
• DJ introduction
• AspectJ and DJ
• Aspect-oriented Programming in pure Java using the DJ library
Demeter and Aspects 3
Problem addressed
• Encapsulation of traversal-related concerns– Those are concerns that involve a group of
collaborating objects that are connected by has-a relationships or zero-argument methods.
– Control scattering of traversal-related concerns and tangling with other concerns
• Construct useful programs without knowing exactly what data types are involved
Demeter and Aspects 4
How is the problem solved?
• Need to talk about a traversal join point model:– sets of points (called join points) in the
execution of a traversal where additional behavior is executed (called hooks or pointcuts).
– the behavior to be executed (called an enhancement or advice).
Demeter and Aspects 5
An AOP System
• has 3 critical elements
– what are the join points• in AspectJ
– points in runtime– means of identifying join points
• in AspectJ– signatures (plus …)
– means of specifying semantics at join points• in AspectJ
– advice– define members
Demeter and Aspects 6
An AOP System (in more detail)
• what is the set of all join points (SJP) • means of identifying join points (IJP)• means of specifying semantics at join points (SJP)• encapsulated units combining JPS and BJP (CSB)• method of attachment of units (AU)
JPS and BJP are sometimes overlapping. JPS might already definean initial behavior plus a set of join points in that behavior.
Demeter and Aspects 7
AP
• Late binding of data structures
• Programming without accidental data structure details yet handling all those details on demand without program change
• Reducing representational coupling
Demeter and Aspects 8
Concepts needed(DJ classes)
• ClassGraph
• Strategy
• Visitor
• TraversalGraph
• ObjectGraph
• ObjectGraphSlice
important
for advanced programming
Demeter and Aspects 9
AOSD: not every concern fits into a component: crosscutting
CM1 CM2 CM3 CM4 CM5 CM6
CR1 x
CR2 x
CR3 x
CR4 x x x x
Goal: find new component structures that encapsulate “crosscutting” concerns
Demeter and Aspects 10
a reusable aspectabstract public aspect RemoteExceptionLogging { abstract pointcut logPoint(); after() throwing (RemoteException e): logPoint() { log.println(“Remote call failed in: ” + thisJoinPoint.toString() + “(” + e + “).”); }}
public aspect MyRMILogging extends RemoteExceptionLogging { pointcut logPoint(): call(* RegistryServer.*.*(..)) || call(private * RMIMessageBrokerImpl.*.*(..));}
abstract
Demeter and Aspects 11
DJ: Counting Pattern:Abstract Pointcut
class BusRoute { int countPersons(TraversalGraph WP) { Integer result = (Integer) WP.traverse(this, new Visitor(){ int r ; public void before(Person host){ r++; } public void start() { r = 0;} public Object getReturnValue() {return new Integer ( r);} }); return result.intValue();}}
Demeter and Aspects 12
DJ: Counting Pattern:Concrete Pointcut
// Prepare the traversal for the current class graphClassGraph classGraph = new ClassGraph();TraversalGraph WPTraversal = new TraversalGraph (“from BusRoute via BusStop to Person”, classGraph);
int r = aBusRoute.countPersons(WPTraversal);
Demeter and Aspects 13
Example : Count Aspect Pattern
collaboration Counting { role SourceSource { in TraversalGraph getT(); public int count (){ // traversal/visitor weaving getT().traverse(this, new Visitor(){ int r; public void before(Target host){ r++; } public void start() { r = 0;} …) } }role Target {}
}
Base:Meta variable: bold Keywords: underscore
Demeter and Aspects 14
AP history
• Programming with partial data structures = propagation patterns
• Programming with participant graphs = high-level class graphs
• Programming with object slices– partial objects = all the constraints imposed by
visitors
Demeter and Aspects 15
Collaborating Classes
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
find all persons waiting at any bus stop on a bus route
OO solution:one methodfor each redclass
Demeter and Aspects 16
Traversal Strategy
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
from BusRoute through BusStop to Person
find all persons waiting at any bus stop on a bus route
Demeter and Aspects 17
Robustness of Strategy
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
busesbusStops
waiting
0..*
0..*
0..*
from BusRoute through BusStop to Person
VillageList
Village
villages
0..*
find all persons waiting at any bus stop on a bus route
Demeter and Aspects 18
Writing Adaptive Programs with Strategies (DJ=pure Java)
class BusRoute { int countPersons(TraversalGraph WP) { Integer result = (Integer) WP.traverse(this, new Visitor(){ int r ; public void before(Person host){ r++; } public void start() { r = 0;} public Object getReturnValue() {return new Integer ( r);} }); return result.intValue();}}
String WPStrategy=“from BusRoute through BusStop to Person”
Demeter and Aspects 19
Writing Adaptive Programs with Strategies (DJ=pure Java)
// Prepare the traversal for the current class graphClassGraph classGraph = new ClassGraph();TraversalGraph WPTraversal = new TraversalGraph (WPStrategy, classGraph);
int r = aBusRoute.countPersons(WPTraversal);
String WPStrategy=“from BusRoute through BusStop to Person”
Demeter and Aspects 20
Writing Adaptive Programs with Strategies (DJ=pure Java)
class BusRoute { int countPersons(TraversalGraph WP) { Integer result = (Integer) WP.traverse(this, new Visitor(){...}); return result.intValue();}}
String WPStrategy=“from BusRoute through BusStop to Person”
ObjectGraph objectGraph = new ObjectGraph(this, classGraph);ObjectGraphSlice objectGraphSlice = new ObjectGraphSlice(objectGraph, WP);objectGraphSlice.traverse(visitor);
WP.traverse(this,visitor) <===>
Demeter and Aspects 21
ObjectGraph: in UML notation
Route1:BusRoute
:BusStopListbusStops
CentralSquare:BusStop
:PersonList
waiting
Paul:Person Seema:Person
:BusListbuses
Bus15:Bus
:PersonList
passengers
Joan:Person
Eric:Person
Demeter and Aspects 22
TraversalGraph
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
from BusRoute through BusStop to Person
find all persons waiting at any bus stop on a bus route
Demeter and Aspects 23
ObjectGraphSlice
Route1:BusRoute
:BusStopListbusStops
CentralSquare:BusStop
:PersonList
waiting
Paul:Person Seema:Person
BusListbuses
Bus15:Bus
:PersonList
passengers
Joan:Person
Eric:Person
Demeter and Aspects 24
Applications of Traversal Strategies
• Program Kinds in DJ – AdaptiveProgramTraditional(ClassGraph)
• strategies are part of program: DemeterJ, Demeter/C++
– AdaptiveProgramDynamic(Strategies, ClassGraph)• strategies are a parameter. Even more adaptive.
– AdaptiveProgram TraditionalOptimized (TraversalGraphs)• strategies are a parameter. Reuse traversal graphs.
– AdaptiveProgramDJ(ObjectGraphSlices)• strategies are a parameter. Reuse traversal graph slices.
Demeter and Aspects 25
Example
• For data member access:
• C c = (C) Main.cg.fetch(this, “from A via B to C”);
Demeter and Aspects 26
Understanding the meaning of a strategy
• Classes involved: Strategy, ObjectGraph, ObjectGraphSlice, ClassGraph
• We want to define the meaning of a Strategy-object for an ObjectGraph-object as an ObjectGraphSlice-object (a subgraph of the ObjectGraph-object). Minimal attention necessary will be given to ClassGraph-object.
Demeter and Aspects 27
Simple case: from A to B
• See lecture: Navigation in object graphs navig-object-graphs-1205-w02.ppt
Demeter and Aspects 28
Graphs and paths
• Directed graph: (V,E), V is a set of nodes, E VV is a set of edges.
• Directed labeled graph: (V,E,L), V is a set of nodes, L is a set of labels, E VLV is a set of edges.
• If e = (u,l,v), u is source of e, l is the label of e and v is the target of e.
Demeter and Aspects 29
Graphs and paths
• Given a directed labeled graph: (V,E,L), a node-path is a sequence p = <v0v1…vn> where viV and (vi-1,li,vi)E for some liL.
• A path is a sequence <v0 l1 v1 l2 … ln vn>, where <v0 …vn> is a node-path and (v i-1, li, vi )E.
Demeter and Aspects 30
Graphs and paths
• In addition, we allow node-paths and paths of the form <v0> (called trivial).
• First node of a path or node-path p is called the source of p, and the last node is called the target of p, denoted Source(p) and Target(p), respectively. Other nodes: interior.
Demeter and Aspects 31
Strategy definition:embedded, positive strategies
• Given a graph G, a strategy graph S of G is any subgraph of the transitive closure of G. Source s, Target t.
• The transitive closure of G=(V,E) is the graph G*=(V,E*), where E*={(v,w): there is a path from vertex v to vertex w in G}.
32Demeter and Aspects
A = s A
B BC C
D DE E
F=t F
G
S
S is a strategy for G
pink edge must implyblack path
Demeter and Aspects 33
Transitive Closure
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
Demeter and Aspects 34
Key concepts
• Strategy graph S with source s and target t of a base graph G. Nodes(S) subset Nodes(G) (Embedded strategy graph).
• A path p is an expansion of path p’ if p’ can be obtained by deleting some elements from p.
Strategy graph and base graph are directed graphs
Demeter and Aspects 35
A simple view of traversals
• When a traversal reaches a target node in the object graph, the path traversed from the source, with suitable substitution of subclasses by superclasses, must be an expansion of an s-t path in the strategy graph. s is the source and t is the target of the strategy. Each edge in the strategy graph corresponds to at least one edge in the object graph.
Demeter and Aspects 36
A simple view of traversals
• When a traversal reaches a final node in the object graph without being at a target, the path traversed from the source, with suitable substitution of subclasses by superclasses, must be a prefix of an expansion of an s-t path in the strategy graph. The prefix is the longest prefix such that there is still a possibility of success as determined by the class graph.
Demeter and Aspects 37
Example 1strategy:{A -> B B -> C}
A
B
C
X
xx
b
c
class graph
A B C
Strategy s t
c
BOpt
Empty
Object graph
OG : A X R X COG’: A X B X CSG : A B C(CG: A X Bopt B X C)
:A
c2:C
x1:X
:R
x2:X
c1:C
c3:C
e1:Empty SR
Only node paths shown for space reasons
Demeter and Aspects 38
Example 1Astrategy:{A -> S S -> C}
A
B
C
X
xx
b
c
class graph
A S C
Strategy s t
c
BOpt
Empty
Object graph
OG : A X R X OG’: A X B X SG : A (CG: A X Bopt B X)
:A
c2:C
x1:X
:R
x2:X
c1:C
c3:C
e1:Empty SR
Only node paths shown for space reasons
early termination
Demeter and Aspects 39
Example 2
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
S = from BusRoute through Bus to Person
NGasPowered
DieselPowered
Demeter and Aspects 40
Example 2
Route1:BusRoute
:BusStopListbusStops
CentralSquare:BusStop
:PersonList
waiting
Paul:Person Seema:Person
BusListbuses
Bus15:DieselPowered
:PersonList
passengers
Joan:Person
Eric:Person
OG : BR BL DP PL POG’: BR BL B PL PSG : BR B P
Only node paths shown for space reasons
S = from BusRoute through Bus to Person
Demeter and Aspects 41
Example 3
Route1:BusRoute
:BusStopListbusStops
CentralSquare:BusStop
:PersonList
waiting
Paul:Person Seema:Person
BusListbuses
Bus15:DieselPowered
:PersonList
passengers
Joan:Person
Eric:Person
OG : BR BLOG’: BR BLSG : BR
Only node paths shown for space reasons
S = from BusRoute via NGasPowered to Person
early termination
Demeter and Aspects 42
Allow
• strategy: {A -> B B -> C}• class graph: A : B. B : C. C = .• object graph: C
Demeter and Aspects 43
ObjectGraphSlice
• The object graph slice starting with o1 is the slice built by following the edges POSS(Class(o1), t, o1) starting at o1 and continuing until every path terminates (at an object of type t or it terminates prematurely).
Demeter and Aspects 44
Example
A
R
BX
S
D
0..1
0..1
0..1
C
T0..1
A -> TT -> D
A = [“x” X] [“r” R].B = [“b” B] D.R = S.S = [“t” T] CC = D.X = B.T = R.D = .
:A
:R :S
:C :D
classgraph
strategyclass dictionary
object graph “r”
Demeter and Aspects 45
Example
A
R
BX
S
D
0..1
0..1
0..1
C
T0..1
A -> TT -> D
A = [“x” X] [“r” R].B = [“b” B] D.R = S.S = [“t” T] CC = D.X = B.T = R.D = .
a1:A
r1:R s1:S
:C :D
classgraph
strategyclass dictionary
object graph “r”
POSS(A,T,a1) = 1 edgePOSS(R,T,r1) = 1 edgePOSS(S,T,s1) = 0 edges
Demeter and Aspects 46
DJ
• An implementation of AP using only the DJ library (and the Java Collections Framework)
• All programs written in pure Java
• Intended as prototyping tool: makes heavy use of introspection in Java
• Integrates Generic Programming (a la C++ STL) and Adaptive programming
Demeter and Aspects 47
Integration of Generic and Adaptive Programming
• A traversal specification turns an object graph into a list.• Can invoke generic algorithms on those lists. Examples:
contains, containsAll, equals, isEmpty, contains, etc. add, remove, etc. throws operation not supported exception.
• What is gained: genericity not only with respect to data structure implementations but also with respect to class graph
Demeter and Aspects 48
Sample DJ code
// Find the user with the specified uid
List libUsers = classGraph.asList(library,
"from Library to User");
ListIterator li = libUsers.listIterator();
// iterate through libUsers
Demeter and Aspects 49
Methods provided by DJ
• On ClassGraph, ObjectGraph, TraversalGraph, ObjectGraphSlice: traverse, fetch, gather
• traverse is the important method; fetch and gather are special cases
• TraversalGraph– Object traverse(Object o, Visitor v)– Object traverse(Object o, Visitor[] v)
Demeter and Aspects 50
Traverse method: excellent support for Visitor Pattern
// class ClassGraph
Object traverse(Object o,
Strategy s, Visitor v);
traverse navigates through Object o following traversal specification s and executing the before and after methods in visitor v
ClassGraph is computed using introspection
Demeter and Aspects 51
Fetch Method
• If you love the Law of Demeter, use fetch as your shovel for digging:– Part k1 = (K) classGraph.fetch(a,”from A to K”);
• The alternative is (digging by hand):– Part k1 = a.b().c().d().e().f().g().h().i().k();
• DJ will tell you if there are multiple paths to the target (but currently only at run-time).
Demeter and Aspects 52
Gather Method
• Returns a list of objects.
• Object ClassGraph.gather(Object o, String s)– List ks = classGraph.gather(a,”from A to K”);
returns a list of K-objects.
Demeter and Aspects 53
Using DJ
• traverse(…) returns the v[0] return value. Make sure the casting is done right, otherwise you get a run-time error. If “public Object getReturnValue()” returns an Integer and traverse(…) casts it to a Real: casting error at run-time.
• Make sure all entries of Visitor[] array are non-null.
Demeter and Aspects 54
Using multiple visitors
// establish visitor communicationaV.set_cV(cV);aV.set_sV(sV);rV.set_aV(aV); Float res = (Float) whereToGo. traverse(this, new Visitor[] {rV, sV, cV, aV});
Demeter and Aspects 55
DJ binary construction operations
cg s tg o og ogscg * tg,cg * og * *s * * * ogs *tg * * ogs *o * * *og * *ogs *
Demeter and Aspects 56
Who has traverse, fetch, gather?(number of arguments of traverse)
cg(3) s tg(2) o og(2) ogs(1)cg * tg,cg * og * *s * * * ogs *tg * * ogs *o * * *og * *ogs *
Demeter and Aspects 57
Methods returning an ObjectGraphSlice
• ClassGraph.slice(Object, Strategy)
• ObjectGraph.slice(Strategy)
• TraversalGraph.slice(Object)
• ObjectGraphSlice(ObjectGraph,Strategy)
• ObjectGraphSlice(ObjectGraph,TraversalGraph)
Blue: constructors
Demeter and Aspects 58
Traverse method arguments
• ClassGraph– Object, Strategy, Visitor
• TraversalGraph– Object, Visitor
• ObjectGraph– Strategy, Visitor
• ObjectGraphSlice– Visitor
Demeter and Aspects 59
Traverse method arguments. Where is collection framework
used?• ClassGraph
– gather(Object, Strategy) / asList(Object, Strategy)• TraversalGraph
– gather(Object) / asList(Object)• ObjectGraph
– gather(Strategy) / asList(Strategy)• ObjectGraphSlice
– gather() / asList()
Demeter and Aspects 60
Where is collection framework used?
• ObjectGraphSlice.asList()– a fixed-size List backed by the object graph
slice. Is write-through: modifying list will modify object and modifying object will modify list. (Similar to Arrays.asList() in Java.)
• gather copies the pointers to the objects.
Demeter and Aspects 61
a:Au:U
v:V
c3:C c4:C
x:X
w:W
c2:Cc1:C
gather()
List v
v.get(1).set_j(5);v.set(4, new C());
asList()
List v
c5:C
Demeter and Aspects 62
Interfaces
• Interface List– ListIterator listIterator()– Object set(int index, Object element)
• Interface ListIterator– void set(Object o): replaces the last element
returned by next or previous with the specified element.
Demeter and Aspects 63
Why is asList useful?
• from Application to X: want to change all F-objects to D-objects.
• From Application to “predecessors” of D: put in a new object.– This is not structure-shy: all the predecessors of
X also need to be mentioned.
Demeter and Aspects 64
Why is asList useful?
• from Application to X: want to change all X-objects to D-objects.
Application = <es> List(E).
E = X D.
D = X F.
X : F | D.
F = .
D = List(X).
List(S) ~ {S}.
Sketch:from Application to E: aE.set_x(new D());aE.get_d().set_x(new D());from E to D: update list elements
from Application to X: set(new D())
Demeter and Aspects 65
Why is asList useful?
• From A to B: want to change a B-object that satisfies some property. Does not matter whether it is in a list.
A = B C.
C = List(B).
Demeter and Aspects 66
Some more theory
• Explaining paths in class graphs:– strategy S for a class graph G: S is subgraph of
the transitive closure of G.– S defines path set in G as follows:
PathSetst(S,G) is the set of all s-t paths in G that are expansions of any s-t path in S.
– A path p is an expansion of path p’ if p’ can be obtained by deleting some elements from p.
Demeter and Aspects 67
Relational Formulation
From object o of class c1, to get to c2, follow edges in the set
POSS(c1,c2,o)={e | c1 <=.e.=> (<=.C.=>)* <= c2 }
Can easily compute these sets for every c1, c2 via transitive-closure algorithms.POSS = abbreviation for: following these edges it is still possible to reach a c2-object.
the following slides explain this view graph
Demeter and Aspects 68
What is a path?
• If we only have concrete classes: no problem.
• Use the standard graph theoretic definition.
Demeter and Aspects 69
A Path
• (A,B,E)
A
E
B
Demeter and Aspects 70
Traversals withAbstract Classes
• from A to E
• from A to B
• from A to C
• from A to D
A
E
B
DC
Demeter and Aspects 71
Traversals to Abstract Classes
• from A to B =• includes =>B,C and :>C,B etc.
• Motivation:– from A to E also includes subclasses of B
A
E
B
DC
Demeter and Aspects 72
Path concept
• Path from A to B– include construction edges (forward) – inheritance edge implies subclass edge in
opposite direction.– include inheritance edges (backward and
forward). Backward inheritance edges are called subclass edges.
– follow rule: after an inheritance edge, you are not allowed to follow a subclass edge.
Demeter and Aspects 73
Path concept in flat class graphs
• Path from A to B:
• In flat class graph there is never a construction edge following an inheritance edge: (<=.C) = C
From object o of class c1, to get to c2, follow edges in the set
POSS(c1,c2,o)={e | c1 <=.e.=> (<=.C.=>)* <= c2 }
Demeter and Aspects 74
Requirements: for flat class graphs
• Paths in class graph turn into paths in object graph by deleting alternation edges and nodes and inheritance edges (Def. of corresponding path).
A EB
DC
A -> B => C -> EA -> C -> E
Demeter and Aspects 75
Requirements: for flat class graphs
• If there is a path in the class graph then there is a legal object of the class graph that has the same corresponding path.
A EB
DC
A -> B => C -> EA -> C -> E
Path in class graph=> Exists object with path in object graph
Demeter and Aspects 76
Requirements: for flat class graphs
d1:Da1:A b1:B
A
B
C
D
Path in object graph=> Exists corresponding path in class graph
Demeter and Aspects 77
Requirements: for flat class graphs
• For a class graph G and legal object O, if there is a path p in the object graph then there is a path P in the class graph such that p corresponds to P.
A EB
DC
A -> B => C -> EA -> C -> E
Demeter and Aspects 78
More on semantics of DJ with abstract classes
• What is the meaning of a visitor on an abstract class?
Demeter and Aspects 79
Traversals to Abstract Classes
• Class graph
A
E
B
DC
visitor:before (B){p(“b”);}before (C){p(“c”);}
Demeter and Aspects 80
Visitor Methods onAbstract Classes
• from A to E: b, c
• from A to B: b, c
• from A to C: b, c
• visitor:– before (B){p(“b”);}– before (C){p(“c”);}
:A
:E
:C
Demeter and Aspects 81
Visitor Methods onAbstract Classes
• from A to E: b
• from A to B: b
• from A to C:
• visitor:– before (B){p(“b”);}– before (C){p(“c”);}
:A
:E
:D
Demeter and Aspects 82
Visitor Rule
• When an object of class X is visited, all visitors of ancestor classes of X will be active.
• The before visitors in the downward order and the after visitors in the upward order.
Demeter and Aspects 83
Traversals to Abstract Classes
• From A to C
A
E
B
DC
visitor: void before (X host){p(“x”);}
void before (B host){p(“b”);}void before (C host){p(“c”);}
X
Demeter and Aspects 84
Example in DemeterJ
class graph in program.cd:
A = B.
X : B.
B : C | D common E.
C = “c”.
D = “d”.
E = .
Demeter and Aspects 85
Behavior basically in DJprogram.beh:
Main { {{ // all Java code
public static void main(Sring args[] … {
A c = A.parse(“c”); A d = A.parse(“d”);
ClassGraph cg = new ClassGraph(true,false);
Visitor v = new Visitor() {
void before (X host) {System.out.println(“x”);}
void before (B host) {System.out.println(“b”);}
void before (C host) {System.out.println(“c”);} };
System.out.println(“C-object:”);
cg.traverse(c,”from A to C”,v);
System.out.println(“D-object:”);
cg.traverse(d,”from A to C”,v); }
System.out.println(“Done.”); }} // end all Java code
}
Demeter and Aspects 86
Output
C-object:
x
b
c
D-object:
Done.
Demeter and Aspects 87
Alternative Visitor Rule:not what programmers want
• When an object of class X is visited, all visitors of ancestor classes of X and in the path set of the current traversal will be active.
• The before visitors in the downward order and the after visitors in the upward order.
Demeter and Aspects 88
Guidelines
IF you use the combination of the following pairs and triples for multiple traversals, fetch or gather, introduce the following computation saving objects:
(cg,s,o)->ogs
(cg,s)->tg
(cg,o)->og
(tg,o)->ogs
cg class graph
s strategy
tg traversal graph
o object
og object graph
ogs object graph slice
v visitor
Abbreviations
In principle can express programsonly with ClassGraph and Strategy andVisitor:cg.traverse(o,s,v);cg.fetch(o,s);cg.gather(o,s);cg.asList(o,s);
Demeter and Aspects 89
DJ unary construction operations
• Class graph from Strategy– ClassGraph(Strategy): make a class graph with
just the classes and edges in traversal graph determined by strategy. Interpret path set as a graph. Maintain several class graphs cg1, cg2, cg3 that are suitable for expressing what you need.
• Class graph from all classes in package
Demeter and Aspects 90
ClassGraph construction
• make a class graph from all classes in default package– ClassGraph()
• include all fields and non-void no-argument methods. Static members are not included.
– ClassGraph(boolean f, boolean m)• If f is true, include all fields; if m is true, include all
non-void no-argument methods.
Demeter and Aspects 91
Dynamic features of DJ ClassGraph construction
• When a class is defined dynamically from a byte array (e.g., from network) ClassGraph.addClass(Class cl) has to be called explicitly. Class cl is returned by class loader.
• ClassGraph() constructor examines class file names in default package and uses them to create class graph.
Demeter and Aspects 92
Dynamic features of DJ ClassGraph construction
• ClassGraph.addPackage(String p)– adds the classes of package p to the class graph.
The package is searched for in the CLASSPATH. How can we control (f,m) options? Uses the same rule as used for the original class graph construction.
• Java has no reflection for packages. Motivates above solution.
Demeter and Aspects 93
Adding Nodes and Edges to ClassGraph
• addClass(Class cl)– add cl and all its members to the class graph, if
it hasn’t already been added.
• addClass(Class cl, boolean aF, boolean aM)– add cl to the class graph. If aF, add all its non-
static fields as construction edges. If aM, add all its non-static non-void methods with no arguments as derived construction edges.
Demeter and Aspects 94
Adding Nodes and Edges to ClassGraph
• Part addConstructionEdge(Field f)– add f as a construction edge.
• Part addConstructionEdge(Method m)– add a no-args method as a construction edge.
• addConstructionEdge may have in addition a String argument called source. For Impl.
• And also a Class argument called target. Also for Impl. Should not be public.
Demeter and Aspects 95
Add other repetition edges
• void ClassGraph.addRepetitionEdge(String source, String target)– add a repetition edge from source to target
• Questions– what about subclass and inheritance edges– what happens if class graph contains edges not
in program. Error will occur.
Demeter and Aspects 96
Design and Implementation
• Until summer 1999: Josh Marshall
• Since then: Doug Orleans
• Available on the Web from DJ home page
• Quite complex
• Viewing an object as a list is done through coroutines to simulate continuation
Demeter and Aspects 97
Problem with DJ
• What is coming is not about a problem of DJ but about a problem with Java: the lack of parameterized classes.
• The lack of parameterized classes forces the use of class Object which, as the mother of all classes, is too well connected.
• This leads to unnecessary traversals and traversal graphs that are too big.
Demeter and Aspects 98
Lack of parameterized classes in Java makes DJ harder to use
• Consider the traversal: from A to B
• Let’s assume that in the class graph between A and B there is a Java collection class. The intent is: A = List(B) which we cannot express in Java. Instead we have: A = Vector(Object). Object : A | B. Let’s assume we also have a class X=B.
Demeter and Aspects 99
Lack of parameterized classes in Java makes DJ harder to use
• We have: A = Vector(Object). Object : A | B | X. X = B.
• If the vector contains an X object it will be traversed!!!
A
X
Object
B
Vector*
Demeter and Aspects 100
A
X
Object
B
Vector*
A
X B
*
No X-object is allowed to be in vector
Demeter and Aspects 101
Moral of the story
• If the Collection objects contain only the objects advertised in the nice class graph of the application the traversal done by DJ will be correct. But unecessary traversals still happen.
• However, if the Collection objects contain additional objects (like an X-object) they will be traversed accidentally.
Demeter and Aspects 102
Moral of the story
• Java should have parameterized classes.
• Workaround: Use a JSR (Java Specification Request) 31 approach: use a schema notation with parameterization to express class graph and generate Java code from schema. For traversal computation, the schema will be used.
Demeter and Aspects 103
Size of traversal graph
• DJ might create big traversal graphs when collection classes are involved. DJ will plan for all possibilities even though only a small subset will be realized during execution.
• To reduce the size of the traversal graph, you need to use bypassing. In the example: from A bypassing {A,X} to B.
Demeter and Aspects 104
Technical Details
• Using DJ and DemeterJ
Demeter and Aspects 105
Combining DJ and DemeterJ• DJ is a 100% Java solution for adaptive
programming.
• DemeterJ has – XML style data binding facilities: code generation
from schema (class dictionary).– Its own adaptive programming language.
• We attempt an optimal integration giving us the strong advantages of both and only few small disadvantages.
Demeter and Aspects 106
Optimal DJ and DemeterJ Integration
• Take all of DJ
• Take all of DemeterJ class dictionary notation
• Take a very tiny bit of DemeterJ adaptive programming language (basically only part that allows us to weave methods).
Demeter and Aspects 107
Combining DJ and DemeterJ
• Pros (advantages)– Java class generation
from class dictionary (getters, setters, constructors).
– Parser generation.– Better packaging of Java
code into different files.– MUCH MORE
POWERFUL.
• Cons (disadvantages)– No longer pure Java
solution.
– need to learn Demeter notation for class dictionaries (similar to XML DTD notation).
– need to learn how to call DemeterJ and how to use project files.
Demeter and Aspects 108
Combining DJ and DemeterJ
• What do we have to learn about DemeterJ?– Class dictionaries: *.cd files– Behavior files: *.beh files. Very SIMPLE!
•A { {{ … }} } defines methods … of class A
– Project files: *.prj• list behavior files *.beh that you are using
– Commands:•demeterj new, demeterj test,
demeterj clean
Demeter and Aspects 109
Combining DJ and DemeterJ
• What you might forget in class dictionaries that are used with DJ:– import edu.neu.ccs.demeter.dj.*;– visitors need to inherit from Visitor– parts of visitors need to be defined in class
dictionary
Demeter and Aspects 110
Combining DJ and DemeterJ
• Structuring your files– put reusable visitors into separate behavior files.– put each new behavior into a separate behavior file.
Visitors that are not planned for reuse should also go into same behavior file. Update the class dictionary with required structural information for behavior to work.
– List all *.beh files in .prj file.
Demeter and Aspects 111
End
Demeter and Aspects 112
Hierarchical Traversals
• Computation : SimpleC | CompoundC.
• CompoundC = [<what> Object] [<where_to_go> StrategyString] [Kind] <sub> List(Computation).
• Kind : Ordered | Unordered.
• SimpleC = [what> Object] [<where_to_go> StrategyString] <result> Object <what_to_do> Visitor.
Demeter and Aspects 113
traversal-related concerns with AC
• traversal AC– participants: ClassGraph, Strategy,
TraversalGraph– provides a traversal following strategy– expects traversal strategy– expects class graph compatible with traversal
strategy
Demeter and Aspects 114
collaboration GEN_TRAVClassGraph expects .class provides ClassGraph() provides traverse(Object this, String where)
collaboration SUM int s = 0; Source Target replace traverse(…) {s++; next()} provide Object getReturnValue()
DifferenceVisitorDJ {{{// stack handling public void start() { stack = new Stack(); } public void before(Container o) { stack.push(sV.getReturnValue()); }
public void after(Container o) { difference = ((Integer) sV.getReturnValue()).intValue() - ((Integer) stack.pop()).intValue(); } public Object getReturnValue() {return new Integer(difference);}}}
collaboration DIFF Stack s = new Stack(); Target replace traverse(…) { stack.push(get_sb()); next(); diff =((Integer) get_se().intValue()- ((Integer) s.pop()).intValue; } expect Integer getsb(); expect Integer getse();
cdGEN_TRAV SUM need instances of
collaborations
Demeter and Aspects 115
collaboration GEN_TRAVClassGraph expects .class provides ClassGraph() provides traverse(Object this, String where)
collaboration SUM int s = 0; Source Target replace traverse(…) {s++; next()}Object getReturnValue()
DifferenceVisitorDJ {{{// stack handling public void start() { stack = new Stack(); } public void before(Container o) { stack.push(sV.getReturnValue()); }
public void after(Container o) { difference = ((Integer) sV.getReturnValue()).intValue() - ((Integer) stack.pop()).intValue(); } public Object getReturnValue() {return new Integer(difference);}}}
collaboration DIFF expect Collaboration sum; int difference; Stack s = new Stack(); Source replace traverse(…) { stack.push(sum.getReturnValue()); next(); difference =((Integer) sum.getReturnValue().intValue()- ((Integer) s.pop()).intValue; } Object getReturnValue() {return new Integer(difference);}
cdGEN_TRAV sum:SUM
CheckingVisitorDJ {{{ public void start() { violations=0; System.out.println("begin"); } public void before(Container o) { System.out.println(" start new container ");}
public void after(Container host) { int cap = host.get_capacity().get_i().intValue(); int diff = ((Integer) iV.getReturnValue()).intValue(); if (diff > cap) { this.set_violations(get_violations() + 1);
System.out.println(" total weight " + diff + " but limit is = " + cap + " OVER CAPACITY "); };
System.out.println(" end container "); } public Object getReturnValue() {return new Integer(violations);}}}}
collaboration CHECK expect Collaboration diff; int violations = 0; Source expect int get_capacity(); replace traverse(…) {next(); cap = host.get_capacity().get_i().intValue(); int d = ((Integer) diff. getReturnValue()).intValue(); if (d > cap) violations++; }
in all:traverse:from Source to Target
Demeter and Aspects 116
Traversal Summingbefore Weight
Differencebefore Containerafter Container
Checking
after Container
before Weight
before Container
after Container
before Container
after Container after Container
Event based view of traversals and visitors
s d v
Summary of code
Summary of data flow
Summary of event flow
Demeter and Aspects 117
Traversal Summingbefore Weightreturn s
Differencebefore Containerafter Containerreturn d
Checking
after Containerreturn v
before Weight
before Container
after Container
before Container
after Container after Container
Event based view of traversals and visitors
s d v
Summary of code
Summary of data flow
Summary of event flow
Demeter and Aspects 118
Visitor classes as components
Summing Difference Checking
total diff
s
sum what?get_value
check what?get_capacity
return return
strategy
class graph
visitor classreturn
Demeter and Aspects 119
Container capacity problemtraversal allWeights(CheckingVisitor cV, DifferenceVisitor dV, SummingVisitor sV) {to Weight;}int checkCapacity() {{ CheckingVisitor cV = new CheckingVisitor(); DifferenceVisitor dV = new DifferenceVisitor(); SummingVisitor sV = new SummingVisitor(); cV.set_dV(dV); dV.set_sV(sV); //link behaviors this.allWeights(cV, dV, sV); // call traversal with visitors return (cV.get_return_val()); }}
cannot avoid all tangling, but can localize it. No longer spreadover several classes.
Demeter and Aspects 120
abstract aspect CapabilityChecking {
pointcut invocations(Caller c): this(c) && call(void Service.doService(String));
pointcut workPoints(Worker w): target(w) && call(void Worker.doTask(Task));
pointcut perCallerWork(Caller c, Worker w): cflow(invocations(c)) && workPoints(w);
before (Caller c, Worker w): perCallerWork(c, w) { w.checkCapabilities(c); }}
Demeter and Aspects 121
Declarative Techniques for Improving Aspect Orthogonality
Karl Lieberherr
Demeter and Aspects 122
Why improve orthogonality of aspects?
• Crucial for Aspect Libraries: otherwise aspects require too many modifications for reuse.
• Danger of being too orthogonal? Not really, if the actual parameters are checked carefully for applicability: need good type systems for AOP.
• Improve orthogonality by parameterization.
Demeter and Aspects 123
How we got to Aspect-Oriented Programming
• Started simple: traversal-seeded programs: Law of Demeter dilemma.
• Talk generically about points in the execution of a traversal program.
• Generically means: parameterize program by an abstraction of its execution.
• Some type checking when actual parameter is known.
Demeter and Aspects 124
Modularization ofcrosscutting concerns
Write this
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() {};}
Instead of writing this
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 ;}
Demeter and Aspects 125
Scattering: count number of components to which color goesordinary program
structure-shyfunctionality
object structure
synchronization
aspect-oriented prog.
Concern 1
Concern 2
Concern 3
COM1
COM2
COM3
Demeter and Aspects 126
Language for Examples: AspectJ
• Xerox PARC: Gregor Kiczales et al.: lingua franca of AOP.
• First version: Crista Lopes (member of Demeter group): implementing both COOL and RIDL in a general purpose AO language (early AspectJ version).
• Model: join points, pointcuts, advice.
Demeter and Aspects 127
• Pointcut– set of execution points of
any method, …
– rich set of primitive pointcuts: this, target, call, … + set operations
– where to enhance
• Advice– how to enhance
• Visitor method sig.– set of execution points
of traversals
– specialized for traversals (nodes, edges)
– where to enhance
• Visitor method bodies– how to enhance
Demeter (for C++ or Java) AspectJ
From Demeter to AspectJ
Demeter and Aspects 128
Java+DJ AspectJ
aspect Traversal { // t()
//declare traversal t :
// “from S” + c + “to T”; …
}
aspect Collecting {
pointcut start() : … ;
pointcut visitingT(T h):
call(void t())
&& target(h);
before():start(){ … }
before():visitingT(){ … }
}
class S{
HashSet collect(ClassGraph cg,
String constraint){
String s = “from S” +
constraint + “to T”;
return (HashSet)
cg.traverse(this, s,
new Visitor(){ … ;
public void before
(T h) { … }
public void start() {…}});
}
}
green: pointcutpurple: advice
red = aspect name
From Demeter to AspectJ
Demeter and Aspects 129
AspectJ Java+DJ aspect SimpleTracing{
pointcut traced():
call(void D.update()}||
call(void D.repaint();
before():traced(){
println(“Entering:”+
thisJoinPoint);}
}
class Source{
HashSet collect(ClassGraph cg,
String constraint){
String s = “from Source” +
constraint + “to Target”;
return (HashSet)
cg.traverse(this, s,
new Visitor(){ … ;
public void before
(Target h) { … }
public void start() {…}});
}
}
AspectJ: refers to existingjoin points
Demeter: defines newjoin points in traversal
green: pointcutpurple: advice
red = aspect name
Demeter and Aspects 130
Parameterization by abstraction of program execution
pointcut AaB(A a1, B b1):
cflow(vis_A(a1)) && vis_B(b1);
pointcut vis_A(A a1):
call(void t (..)) && target(a1);
pointcut vis_B(B b1): …
Pointcut AaB can be used with many different base programs.Parameterization is implicit.
Demeter and Aspects 131
Parameterization by abstraction of program execution
pointcut AaBaC(A a1,B b1,C c1):
cflow(cflow(vis_A(a1)) &&
vis_B(b1)) && vis_C(c1);
pointcut vis_A(A a1):
call(void t (..)) && target(a1);
pointcut vis_B(B b1): …
pointcut vis_C(C c1): …
A=CompilationUnit B=MetaSetRule C=Name: Verizon 24*7 app.
Demeter and Aspects 132
Equation SystemusedThings = from EquationSystem through Expression to Variable
EquationSystem
Equation_List
Equation Variable
equations
*lhs
rhs
ExpressionSimple
Compound
Numerical
Expression_List*
Addop
args
Ident
S
D
T
B
Demeter and Aspects 133
Adding Demeter to AspectJ
• Adding more flow constructs; Demeter traversals
• flow construct for object graphs: – declare traversal t = …
• flow construct for class graphs: type patterns: – nodes(t): all nodes in scope of t
• Adding grammar aspect … (a la JAXB)
Demeter and Aspects 134
Adding Demeter Traversals to AspectJ
• Because the AspectJ join point model is a generalization of Demeter’s join point model, we can use the AspectJ pointcuts to express the traversal pointcuts.
• However, this would expose the traversal implementation.
• Extend AspectJ with two new pointcut primitives: traversal(t) and crossing(e).
Demeter and Aspects 135
New pointcuts
• Traversal(t = from A via B to C): The set of all join points in the traversal that finds all C-objects contained in a B-object contained in an A-object.
• pointcut visiting_C(C c1): traversal(t) && target(c1);
• pointcut visiting_e(S s,T t): traversal(t) && && crossing(e) && this(s) && target(t);
Demeter and Aspects 136
Traversal(t) pointcut
• picks out all join points between the start and the end of the traversal that are needed for the traversal only, i.e. the node visits and the edge visits.
Demeter and Aspects 137
How to define a traversal
• AspectJ declare form
• declare traversal t: traversal specification;
• traversal specification: an automaton
Demeter and Aspects 138
Conclusions
• AspectJ is well-aligned with Demeter. Need only a small extension to add the Demeter traversals.
• Pointcuts become more verbose. Could also use traversals with visitors and extend them with AspectJ (use the args pointcut).
Demeter and Aspects 139
more integration
• traversal(t) && crossing(“xyz”) && this(a) && target(b) && args(v1, tS)
• explanation: traversal t through edge xyz with source a and target b. The visitor is v1 and the token set is tS. tS allows us to query the state of the traversal: we can ask which strategy graph edges are currently active.
Demeter and Aspects 140
• traversal(t) && cflow(call( * f(..)): all join points
• join(traversal(t1), traversal(t2))• traversal(t1) || traversal(t2)• traversal(t1) && !traversal(t2)• traversal(“from A to B”) && !
traversal( “from A via X to B”) = from A bypassing X to B
Demeter and Aspects 141
cflow
• is traversal the only pcd where we want nesting with advice?
Demeter and Aspects 142
• difference between visiting(a) and this(a) and target(a)
• traversal(t): target(a) = visiting(a)
• this(a) where traversal was before getting to a-object
Demeter and Aspects 143
dynamic call graph
aCompany.t() aCompany.t_domesticDivisions()
aCompany.t_foreignDivisions()
aCompany.domesticDivisions
a_d_DivisionList.t()
aCompany.foreignDivisionsa_f_DivisionList.t()
1
2
1
2
1
2
Demeter and Aspects 144
dynamic call graph
a_d_DivisionList.t()
a1Division.t ()
a1Division.departments
aDepartmentList.t()
1
2
a1Division.t_departments ()
a2Division.t ()
etc.
2 1
Demeter and Aspects 145
From Adaptive to Aspect-Oriented Programming
• Object-graphs are turned into dynamic call graphs by traversal methods produced from the class graph and a traversal specification.
• As we go through dynamic call graph, we want to collect information from arguments and return values of method calls.
• Exploit regularities in call graphs.
Demeter and Aspects 146
Motivation
• Declarative techniques used in existing AOP systems
• Look at a family of declarative techniques: use one uniform syntax and three different semantics.
Demeter and Aspects 147
Flow Expressions
• D ::= [A,B] | join(D1,D2) | merge(D1,D2)
• We can use them in three different graphs relevant to programming:– call trees: subset of nodes– class graphs: subset of nodes– object trees: subgraph
Demeter and Aspects 148
Flow Expressions and AOP• They are a basic cross-cutting construct for
defining subgraphs.
• merge(join([A,X],[X,C]), join([A,Y],[Y,C])) defines a subgraph of a larger graph whose ad-hoc description cuts across many nodes or edges.
• succinct encapsulations of subgraphs related to some aspect.
A C
X
Y
Demeter and Aspects 149
Flow expressions
• are abstractions of some aspect whose ad-hoc description would cut across many nodes or edges of a graph.
• define sets of join points based on connectivity in graph.
• offer pointcut designator reduction (high-level pointcut designator): free programmer from details of some graph representing some aspect.
Demeter and Aspects 150
Definitions for Flow Expressions
• D ::= [A,B] | join(D1,D2) | merge(D1,D2)
• Source([A,B]) = A
• Target([A,B]) = B
• Source(join(D1,D2) )=Source(D1)
• Target(join(D1,D2) )=Target(D2)
• Source(merge(D1,D2) )=Source(D1)
• Target(merge(D1,D2) )=Target(D1)
Demeter and Aspects 151
Well-formed Flow Expressions
• D ::= [A,B] | join(D1,D2) | merge(D1,D2)
• WF([A,B]) = true // well-formed
• WF(join(D1,D2) )=WF(D1) && WF(D2) && Target(D1) = Source(D2)
• WF(merge(D1,D2) )= WF(D1) && WF(D2) && Source(D1)=Source(D2) && Target(D1)=Target(D2)
Demeter and Aspects 152
Dynamic call tree
• nodes are operation calls: labeled by operation name and arguments
• edges: a operation calls another operation
• nodes = join points
Demeter and Aspects 153
abstract aspect CapabilityChecking {
pointcut invocations(Caller c): this(c) && call(void Service.doService(String));
pointcut workPoints(Worker w): target(w) && call(void Worker.doTask(Task));
pointcut perCallerWork(Caller c, Worker w): cflow(invocations(c)) && workPoints(w);
before (Caller c, Worker w): perCallerWork(c, w) { w.checkCapabilities(c); }}
context-passing aspects
Demeter and Aspects 154
Interpretation of traversal strategies
• D ::= [A,B] | join(D1,D2) | merge(D1,D2)
• A and B are pointcut designators.
• [A,B]: the set of B-nodes reachable from A-nodes.
• join(D1,D2): the set of Target(D2)-nodes reachable from Source(D1)-nodes following D1 and then following D2.
Demeter and Aspects 155
Interpretation of traversal strategies
• merge(D1,D2): the union of the set of Target(D1)-nodes reachable from Source(D1)-nodes following D1 and the set of Target(D2)-nodes reachable from Source(D2)-nodes following D2.
Demeter and Aspects 156
Translation Rules
• t(D1)
• flow(A) && B
• t(D1) || t(D2)
• flow(t(D1)) && t(D2)
• D1
• from A to B
• merge(D1,D2)
• join(D1,D2)
Demeter and Aspects 157
Class graph
• D• [A,B]• join(D1,D2)• merge(D1,D2)
• PathSet(D)• Paths(A,B)• PathSet(D1).PathSet(D2)• PathSet(D1) || PathSet(D2)
we are only interested in the set of nodestouched by the path sets -> subgraph of class graph
flow expressions are called traversal strategies Demeter/C++DJ
Type patterns in AspectJ
Demeter and Aspects 158
Object tree
• D• [A,B]
• subgraph of O• subgraph of O
consisting of all paths from an A-node to a B-node, including prematurely terminated paths.
flow expressions are called traversal strategies Demeter/C++DemeterJDJ
generate traversalsin AspectJ
Demeter and Aspects 159
Object tree
• D• join(D1,D2)
• subgraph of O• subgraph of O
consisting of all paths following D1 and those reaching Target(D1) concatenated with all paths following D2.
Demeter and Aspects 160
Object tree
• D• merge(D1,D2)
• subgraph of O• subgraph of O
consisting of all paths following D1 or following D2.
Demeter and Aspects 161
Purposes of strategies
• DJ• Traversal
– strategy graph
– class graph
– object graph
• Purposes– select og with sg
• extract node labels
– select cg with sg
• AspectJ• General computation
– strategy call graph
– static call graph
– dynamic call graph
• Purposes– select dcg with sycg
• extract node labels
– select scg with sycg
Demeter and Aspects 162
Purposes of strategies
• DJ + method edges• Traversal
– strategy graph
– class graph
– object graph
– argument map
• Purposes– select dcg with sg + am
• extract node labels
Demeter and Aspects 163
Correspondences
• t(D1)
• flow(A) && B
• flow(A)
• flow(flow(A) && B) && C
• flow(flow(flow(A) && B) && C) && E
• (flow(flow(A) && B1) && C) || (flow(flow(A) && B2) && C)
• t(D1) || t(D2)
• flow(t(D1)) && t(D2)
• flow(flow(A) && B) && (flow(B) && C)
• = flow(flow(A) && B) && C
• D1
• from A to B
• from A to *
• from A via B to C
• from A via B via C to E
• merge(from A via B1 to C, from A via B2 to C)
• merge(D1,D2)
• join(D1,D2)
• join (from A to B, from B to C)
subset(flow(B)) && flow(B) = subset(flow(B))
Demeter and Aspects 164
Theme
• Defining high-level artifact in terms of a low-level artifact without committing to details of low-level artifact in definition of high-level artifact. Low-level artifact is parameter to definition of high-level artifact.
• Exploit structure of low-level artifact.
Demeter and Aspects 165
AspectJ adds
• Generalizes from join points of specialized methods to join points of any method, field access, field modification, etc.
• Uses set operations && and ! combined with a rich set set of primitive pointcuts.
• Generalizes from a flow construct for traversals to a flow construct for arbitrary join points.
Demeter and Aspects 166
Discussion with Gregor Kiczales at UBC
• Ontology of AOP
• Ontology is the study of what there is, an inventory of what exists. An ontological commitment is a commitment to an existence claim for certain entities.
Demeter and Aspects 167
basis of crosscutting
• a join point model (JPM) has 3 critical elements
– what are the join points• in AspectJ
– points in runtime– means of identifying join points
• in AspectJ– signatures (plus …)
– means of specifying semantics at join points• in AspectJ
– advice– define members
Demeter and Aspects 168
Range of AOP languagesmeans of … join points
add memberssignaturesclass members static JPM
DemeterJ, Demeter/C++
dynamic JPM 1
static JPM 1
static JPM 2
static JPM 3
AspectJ dynamic JPM
JPM
when traversal reaches object or edgeclass members
class members
class members
points in execution call, get, set…
join points
visitor method signatures
traversal spec. sclass graph g
class names
class graph
signatures w/ wildcards & other properties of JPs
identifying
visitor method bodies
s + g (result = traversal implementation)
add members
class graph with tokens=grammar (result = parsing and printing implementation)
advice
specifying semantics at
Demeter and Aspects 169
Range of AOP languagesmeans of … join points
add memberssignaturesclass members static JPM
DJ
dynamic JPM 1
dynamic JPM 2
static JPM 4
AspectJ dynamic JPM
JPM
when traversal reaches object or edge (method traverse)
when traversal reaches object (methods fetch, gather, asList)
nodes in object graph o
points in execution call, get, set…
join points
visitor method signatures
source and targets of traversal
trav. spec. sclass graph g
signatures w/ wildcards & other properties of JPs
identifying
visitor method bodies
method name (fetch, gather, asList)
s+g (result = traversal impl. = edges to traverse at nodes in object graph o)
advice
specifying semantics at
Demeter and Aspects 170
Combining two join point models• Static JPM 1: In Demeter we use traversal specifications and
the class graph to define a traversal implementation (either static or dynamic)
• Visitor JPM 1: The result of static JPM 1 is used to define a second JPM: – The traversal implementation defines nodes and edge visits. – Visitor signatures define the nodes and edges where
additional advice is needed: they are the means of identifying join points.
– The means of specifying semantics at join points are the visitor bodies.
Demeter and Aspects 171
DJ: static JPM 4
• The join points are nodes in object graphs. They are not dynamic call graph join points nor class members!
• The means of identifying the join points for a given object graph o are a strategy s and the class graph g. o must conform to g.
• The means of specifying the semantics at the join points are again s and g. See paper with Mitch Wand for the formal details behind this JPM.
Demeter and Aspects 172
DemeterJ: static JPM 1
• The means of identifying the join points and of specifying the semantics at the join points are the same.
• The reason is that s+g both – select the classes that will get traversal
semantics– determine the details of the traversal semantics
Demeter and Aspects 173
DemeterJ: static JPM 3
• The means of identifying the join points (class members) is done by the class graph.
• When we add tokens to the class graph we get a grammar that contains instructions for parsing and printing behavior.
• A grammar is an aspect (external representation aspect): the adhoc implementation cuts across all classes.
Demeter and Aspects 174
Software Design and Development with DJ (very brief)
• Functional decomposition into generic behavior– Decomposition into methods
• Decomposition into strategies
• Decomposition into visitors
• Adaptation of generic behavior – Identify class graph– Refine strategies