500 likes | 523 Views
Declarative Techniques for Improving Aspect Orthogonality. Karl Lieberherr. Why improve orthogonality of aspects?. Crucial for Aspect Libraries: otherwise aspects require too many modifications for reuse.
E N D
Declarative Techniques for Improving Aspect Orthogonality Karl Lieberherr PL Day 2002
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. PL Day 2002
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. PL Day 2002
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 ; } publicclass 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 { returnloc.x(); } void set_x(int x) throws RemoteException { loc.set_x(); } double get_y() throws RemoteException { returnloc.y(); } void set_y(int y) throws RemoteException { loc.set_y(); } double get_width() throws RemoteException { returndim.width(); } void set_width(int w) throws RemoteException { dim.set_w(); } double get_height() throws RemoteException { returndim.height(); } void set_height(int h) throws RemoteException { dim.set_h(); } void adjustLocation() throws RemoteException { loc.adjust(); } void adjustDimensions() throws RemoteException { dim.adjust(); } } publicclass Shape { protecteddouble x_= 0.0, y_= 0.0; protecteddouble 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(); } } Write this 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}; } class AdjustableLocation { protecteddouble x_, y_; public AdjustableLocation(double x, double y) { x_ = x; y_ = y; } synchronizeddouble get_x() { return x_; } synchronizedvoid set_x(int x) {x_ = x;} synchronizeddouble get_y() { return y_; } synchronizedvoid set_y(int y) {y_ = y;} synchronizedvoid adjust() { x_ = longCalculation1(); y_ = longCalculation2(); } } class AdjustableDimension { protecteddouble width_=0.0, height_=0.0; public AdjustableDimension(double h, double w) { height_ = h; width_ = w; } synchronizeddouble get_width() { return width_; } synchronizedvoid set_w(int w) {width_ = w;} synchronizeddouble get_height() { return height_; } synchronizedvoid set_h(int h) {height_ = h;} synchronizedvoid adjust() { width_ = longCalculation3(); height_ = longCalculation4(); } } 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() {}; } Modularization of crosscutting concerns Instead of writing this
Scattering: count number of components to which color goes ordinary program aspect-oriented prog. structure-shy functionality COM1 Concern 1 object structure COM2 Concern 2 COM3 synchronization Concern 3 PL Day 2002
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. PL Day 2002
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 From Demeter to AspectJ Demeter (for C++ or Java) AspectJ PL Day 2002
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 (Th) { … } public void start() {…}}); } } From Demeter to AspectJ Java+DJ AspectJ red = aspect name green: pointcut purple: advice PL Day 2002
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() {…}}); } } refers to existing join points Demeter: defines new join points in traversal AspectJ Java+DJ red = aspect name green: pointcut purple: advice PL Day 2002
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. PL Day 2002
A=CompilationUnit B=MetaSetRule C=Name: Verizon 24*7 app. 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): … PL Day 2002
usedThings = from EquationSystem through Expression to Variable Equation System EquationSystem equations Equation_List Ident * lhs Equation Variable Numerical rhs Simple args Expression_List Expression S T * op Add Compound D B PL Day 2002
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) PL Day 2002
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). PL Day 2002
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); PL Day 2002
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. PL Day 2002
How to define a traversal • AspectJ declare form • declare traversal t: traversal specification; • traversal specification: an automaton PL Day 2002
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). PL Day 2002
Conclusions • Adding the proposed flow constructs (to the already existing flow construct) makes aspects more orthogonal. • Otherwise they are all coupled through structural details which severely hinders reuse and the development of aspect libraries. PL Day 2002
Conclusions: Flow expressions AspectJ (sets of nodes) dynamic call graphs Demeter (slices of graphs or path sets) object graphs class graphs PL Day 2002
Center for Software Sciences • Work with BBN on aspects for distributed real-time embedded applications. • extending AspectJ (John Sung) • extending DJ (Pengcheng Wu with Shriram K.) • aspectual collaborations (Johan Ovlinger, Ed M.) • Extensible programming (Doug Orleans) • Work with ABB on enhancing their aspect system for Industrial IT (Theo Skotiniotis) • David Lorenz: Components PL Day 2002
Looking for new opportunities • Former partners: IBM, Citibank, SAIC, Mettler-Toledo, Skyva, etc. • Looking to help apply aspect-oriented software development to industrial projects. • Graduate student support. PL Day 2002
The End PL Day 2002
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. PL Day 2002
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 PL Day 2002
cflow • is traversal the only pcd where we want nesting with advice? PL Day 2002
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 PL Day 2002
dynamic call graph aCompany.t() aCompany.t_domesticDivisions() 1 1 2 2 aCompany.domesticDivisions 2 aCompany.t_foreignDivisions() 1 a_d_DivisionList.t() a_f_DivisionList.t() aCompany.foreignDivisions PL Day 2002
dynamic call graph a1Division.t_departments () a_d_DivisionList.t() 1 2 1 2 a1Division.departments a1Division.t () a2Division.t () aDepartmentList.t() etc. PL Day 2002
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. PL Day 2002
Motivation • Declarative techniques used in existing AOP systems • Look at a family of declarative techniques: use one uniform syntax and three different semantics. PL Day 2002
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 PL Day 2002
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. X A C Y PL Day 2002
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. PL Day 2002
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) PL Day 2002
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) PL Day 2002
Dynamic call tree • nodes are operation calls: labeled by operation name and arguments • edges: a operation calls another operation • nodes = join points PL Day 2002
context-passing aspects 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); } } PL Day 2002
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. PL Day 2002
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. PL Day 2002
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) Translation Rules PL Day 2002
D [A,B] join(D1,D2) merge(D1,D2) PathSet(D) Paths(A,B) PathSet(D1).PathSet(D2) PathSet(D1) || PathSet(D2) flow expressions are called traversal strategies Demeter/C++ DJ Class graph Type patterns in AspectJ we are only interested in the set of nodes touched by the path sets -> subgraph of class graph PL Day 2002
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++ DemeterJ DJ Object tree generate traversals in AspectJ PL Day 2002
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. Object tree PL Day 2002
D merge(D1,D2) subgraph of O subgraph of O consisting of all paths following D1 or following D2. Object tree PL Day 2002
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 Purposes of strategies PL Day 2002
DJ + method edges Traversal strategy graph class graph object graph argument map Purposes select dcg with sg + am extract node labels Purposes of strategies PL Day 2002
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) Correspondences subset(flow(B)) && flow(B) = subset(flow(B)) PL Day 2002
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. PL Day 2002
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. PL Day 2002