modeling crosscutting in aspect-oriented mechanisms Hidehiko Masuhara (University of Tokyo) joint work with Gregor Kiczales (University of British Columbia) 1
aspect-oriented programming • AOP supports modularization of crosscutting concerns [Kiczales et al.1997] Display Display • e.g., a drawing editor & update(FigureElement) update(FigureElement) display a concern: update display when figure moves elements FigureElement FigureElement Figure Figure moveBy(int,int) moveBy(int,int) w/o AOP vs. ⇓ w/ AOP • Point Line Point Line DisplayUpdating DisplayUpdating getX() getP1() getX() getP1() update(FigElm) update(FigElm) getY() getP2() getY() getP2() after(e) : update(FigElm) { after(e) : update(FigElm) { setX(int) setP1(Point) setX(int) setP1(Point) e.display.update(e) e.display.update(e) setY(int) setP2(Point) setY(int) setP2(Point) } } (so called) components aspects 2
what’s the essence of AOP? • a naïve model does not capture – symmetric mechanism in Hyper/J – dynamic mechanism in AspectJ – more specialized mechanisms (e.g., Demeter) NG NG – … a naïve model • we’d like to find a model compo- – general enough to capture aspect nent many mechanisms – not too general so that we can see the nature of AOP crosscutting! 3
contributions & approach Aspect 1. provide a common real AOP SandBox • components modeling framework languages & aspects are impl. impl. parallel AspectJ AspectJ impl. impl. Hyper/J Hyper/J impl. impl. • weaving Demeter Demeter happens in impl. 2. explain impl. the third modular crosscutting [Kiczales + 01] thru simplified space [Ossher&Tarr01] [Lieberherr + 96,97] implementations 4
talk outline • implementations of core AOP mechanisms – PA: an AspectJ-like (dynamic) mechanism – COMPOSITOR: a Hyper/J-like mechanism – ( TRAV: a Demeter-like mechanism ) – ( OC: an AspectJ-like (static) mechanism ) • the modeling framework • modular crosscutting in terms of the modeling framework 5
PA – pointcuts and advice • simplified from (dynamic part of) AspectJ [Kiczales01] an example advice: • key elements: update display – join point: point in execution after moving any element i.e., a method call after( ): after( ): – pointcut: specifies when Display Display update(FigureElement) update(FigureElement) call(void Point.setX(int)) call(void Point.setX(int)) display – advice: specifies || call(void Point.setY(int)) || call(void Point.setY(int)) elements Figure FigureElement what to do Figure FigureElement || call(void Line.setP1(Point)) || call(void Line.setP1(Point)) • asymmetric : || call(void Line.setP2(Point)) { || call(void Line.setP2(Point)) { Point Line Point Line getX() getP1() getX() getP1() display.update(); display.update(); getY() getP2() getY() getP2() dominant / inferior setX(int) setP1(Point) setX(int) setP1(Point) setY(int) setP2(Point) } setY(int) setP2(Point) } moveBy(int,int) moveBy(int,int) moveBy(int,int) moveBy(int,int) modularity 6
PA: implementation an interpreter (à la EOPL) an interpreter (à la EOPL) (define eval-exp (define eval-exp (lambda (exp env) a join point represents a (lambda (exp env) a join point represents a (cond ((call-exp? exp) (cond ((call-exp? exp) method call method call (call-method (call-exp-mname exp) (call-method (call-exp-mname exp) (eval-exp (call-exp-obj exp) env) (eval-exp (call-exp-obj exp) env) (eval-rands (call-exp-rands exp) env))) (eval-rands (call-exp-rands exp) env))) a method call is to: …))) …))) • create a join point • create a join point (define-struct call-jp (mname target args)) (define-struct call-jp (mname target args)) • identify a method • identify a method (define call-method (define call-method • identify • identify (lambda (mname obj args) (lambda (mname obj args) (let*((jp (make-call-jp mname obj args)) advice decls. (let*((jp (make-call-jp mname obj args)) advice decls. (method (lookup-method jp)) (method (lookup-method jp)) • execute • execute (advice (lookup-advice jp))) (advice (lookup-advice jp))) advice decls. advice decls. (execute-advice advice jp (execute-advice advice jp • execute method • execute method (lambda ( ) (lambda ( ) (execute-method method jp)))))) (execute-method method jp)))))) 7
observations from PA implementation NG NG • method and advice a naïve model are treated similarly: compo- aspect nent lookup & execute � symmetric model • join points come from execution � “weaving into components” is not good � weaving in the third space (i.e., execution) 8
COMPOSITOR – class composition simplified from Hyper/J [Ossher01] • class hierarchy for each concern Display Display update(FigureElement) update(FigureElement) (no dominant modularity) display display elements elements Figure FigureElement Figure FigureElement • composition of class hierarchies to get an executable m m a a t t c m c h Point Line m h Point Line a P a t P o t c o m c h i n m h i getX() getP1() a n t P getX() getP1() a t t . P s t c o . s m c o i e h n m i e t a h n t t X getY() getP2() • composition specification a L t t . X getY() getP2() L i s t c n . i s e w c h n e e t w h i e . t Y t L s i . Y t h setX(int) setP1(Point) L i s e h setX(int) setP1(Point) i n e w t O n e w t P i O e . t P 1 i b s t h . 1 b s setY(int) setP2(Point) s e w h s e e t w O setY(int) setP2(Point) e t P i O r t b P i r v 2 t h b s v a 2 h s e a b moveBy(int,int) moveBy(int,int) w O e b moveBy(int,int) moveBy(int,int) w O r l i b e t r v l i b e t h s v a . m h s e a b . m O e b o r l O e o v b r v l e b v a . v e s m a b . e d s e m b o d e l r e o v l r v e . v m e v a . e d a b m o d b l o v e l v e e . e Observable m d . Observable m d o o v v e e d d moved() { moved() { display.update(this); Display display.update(this); Display } } update(FigureElement) update(FigureElement) 9
COMPOSITOR: implementation Display Display update(FigureElement) source-to-source update(FigureElement) display display elements translation elements Figure FigureElement Figure FigureElement Observable Observable moved() { Display moved() { Display display.update(this); update(FigureElement) display.update(this); update(FigureElement) } } 1. computes all possible Point Line Point Line getX() getP1() getX() getP1() getY() getP2() getY() getP2() combinations * setX(int) setP1(Point) setX(int) setP1(Point) setY(int) setP2(Point) setY(int) setP2(Point) moveBy(int,int) moveBy(int,int) moveBy(int,int) moveBy(int,int) 2. determines whether ... each should be merged (compositor:weave <program-a> (compositor:weave <program-a> <program-b> <program-b> 3. merges bodies & "match Point.setX with Observable.moved "match Point.setX with Observable.moved match Point.setY with Observable.moved match Point.setY with Observable.moved match Line.setP1 with Observable.moved match Line.setP1 with Observable.moved match Line.setP2 with Observable.moved") match Line.setP2 with Observable.moved") adds to program ... elements Display elements Display Figure FigureElement Figure FigureElement update(FigureElement) (* very naïve approach; update(FigureElement) display display Point Line Point Line just for explanation) getX() getP1() getX() getP1() getY() getP2() getY() getP2() setX(int) setP1(Point) setX(int) setP1(Point) setY(int) setP2(Point) setY(int) setP2(Point) moveBy(int,int) moveBy(int,int) moveBy(int,int) moveBy(int,int) 10
COMPOSITOR: implementation generate combinations generate combinations (define compositor:weave (define compositor:weave of methods of methods (lambda (pgm-a pgm-b relationships) (lambda (pgm-a pgm-b relationships) (let loop ((pgm (make-program '()) ) (let loop ((pgm (make-program '()) ) (seeds (compute-seeds pgm-a pgm-b) )) (seeds (compute-seeds pgm-a pgm-b) )) (if (not (null? seeds)) (if (not (null? seeds)) test all methods test all methods (let ((signature (all-match (car seeds) (let ((signature (all-match (car seeds) have matching have matching relationships) )) relationships) )) signatures signatures (if signature (if signature (let* ((jp (car seeds)) (let* ((jp (car seeds)) merge method merge method (decl (merge-decls jp relationships ) )) (decl (merge-decls jp relationships ) )) bodies bodies (loop (add-decl-to-pgm decl pgm signature ) (loop (add-decl-to-pgm decl pgm signature ) and install and install (remove-subsets jp (cdr seeds)))) (remove-subsets jp (cdr seeds)))) (loop pgm (cdr seeds)))) (loop pgm (cdr seeds)))) pgm)))) pgm)))) 11
observations from COMPOSITOR implementation NG NG • no dominant modularity a naïve model � symmetric model compo- aspect nent • join points are not only from pgm-a (nor pgm-b) � “weaving into components” is not good � weaving in the third space • matching rule can be modified � weaving parameters 12
Recommend
More recommend