Presentation is loading. Please wait.

Presentation is loading. Please wait.

A Formal Model of Modularity in Aspect-Oriented Programming Jonathan Aldrich 15-819: Objects and Aspects Carnegie Mellon University.

Similar presentations


Presentation on theme: "A Formal Model of Modularity in Aspect-Oriented Programming Jonathan Aldrich 15-819: Objects and Aspects Carnegie Mellon University."— Presentation transcript:

1 A Formal Model of Modularity in Aspect-Oriented Programming Jonathan Aldrich 15-819: Objects and Aspects Carnegie Mellon University

2 Outline AOP Modularity Challenges Open Modules A Bit of Formality Comparison to Aspect-Aware Interfaces Lessons Learned and Discussion

3 Modularity and Encapsulation Parnas’ advice: Modularize a system to hide information that may change Encapsulation A mechanism for enforcing information hiding Java classes & packages, ML modules… Aspect-oriented Programming More flexible ways of modularizing a system

4 Is AOP Modular? Back to Parnas: Does AOP hide information that is likely to change? Yes, within the aspect Aspect code can be evolved separately No, not within the base code Minor changes to base code break the aspect

5 Example: Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... }

6 Example: Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1x += dx; p1y += dy; p2x += dx; p2y += dy;... }

7 Example: Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1x += dx; p1y += dy; p2x += dx; p2y += dy;... } aspect AssureShapeInvariants { }

8 Example: Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1x += dx; p1y += dy; p2x += dx; p2y += dy;... } aspect AssureShapeInvariants { pointcut moves() = call(Shape+.moveBy(..)); }

9 Example: Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1x += dx; p1y += dy; p2x += dx; p2y += dy;... } aspect AssureShapeInvariants { pointcut moves() = call(Shape+.moveBy(..)); after(): moves() { scene.checkInvariants(); }

10 Example: Broken Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1x += dx; p1y += dy; p2x += dx; p2y += dy;... } aspect AssureShapeInvariants { pointcut moves() = call(Shape+.moveBy(..)); after(): moves() { scene.checkInvariants(); } Change representation to use Point

11 Example: Broken Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1.moveBy(dx, dy); p2.moveBy(dx, dy);... } aspect AssureShapeInvariants { pointcut moves() = call(Shape+.moveBy(..)); after(): moves() { scene.checkInvariants(); } Change representation to use Point

12 Example: Broken Assurance Aspect class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1.moveBy(dx, dy); p2.moveBy(dx, dy);... } aspect AssureShapeInvariants { pointcut moves() = call(Shape+.moveBy(..)); after(): moves() { scene.checkInvariants(); } Change representation to use Point Now the scene invariants are checked in the middle of a Rectangle move—when they might be broken!

13 Analysis Aspects can violate information hiding Assurance aspect depends on Shape internals Similar to OO Fragile Base Class Problem Observing impl. dependant calling patterns Can fix each individual problem Better: use modules to forestall issue

14 Fix #1: external advice class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1x += dx; p1y += dy; p2x += dx; p2y += dy;... } aspect AssureShapeInvariants { pointcut moves(): call(Shape+.moveBy(..)) && !within(shape.*); after(): moves() { scene.checkInvariants(); } Only specifies calls that are external to the shape package

15 Fix #2: semantic pointcut class Point extends Shape { void moveBy(int dx, int dy) { x += dx; y += dy;... } class Rectangle extends Shape { void moveBy(int dx, int dy) { p1x += dx; p1y += dy; p2x += dx; p2y += dy;... } class Shape { public pointcut moves(): call(Shape+.moveBy(..)); } aspect AssureShapeInvariants { after(): Shape.moves() { scene.checkInvariants(); } Move pointcut to the shape package Now the shape maintainer is responsible for preserving its semantics when shapes evolve

16 Open Modules void moveBy(int, int); void animate(Motion); Open Module Ordinary functional interface

17 Open Modules void moveBy(int, int); void animate(Motion); pointcut moves; Open Module Ordinary functional interface Semantic Pointcut Denotes some internal event Promise to maintain event semantics as code evolves [Gudmunson & Kiczales]

18 Open Modules void moveBy(int, int); void animate(Motion); pointcut moves; Open Module Clients can call interface functions

19 Open Modules void moveBy(int, int); void animate(Motion); pointcut moves; Open Module Clients can call interface functions Clients can advise external calls to interface functions

20 Open Modules void moveBy(int, int); void animate(Motion); pointcut moves; Open Module Clients can call interface functions Clients can advise external calls to interface functions Clients can advise pointcuts in interface

21 Open Modules void moveBy(int, int); void animate(Motion); pointcut moves; Open Module Clients can call interface functions Clients can advise external calls to interface functions Clients can advise pointcuts in interface Clients cannot advise any internal calls (not even to exported functions) X

22 Open Module Properties: Equivalence Motivation Rules describe when changes could affect clients Can be used to prove correctness of refactorings Bisimulation-based equivalence All functions map args to same results Invoke internal pointcuts in same way Same sequence, same context

23 Open Module Properties: Abstraction Verifies correctness of equivalence rules Shows that information hiding works Informal statement of theorem Consider two module implementations that are equivalent according to the bisimulation rules No client code can distinguish the behavior of these modules (even by using aspects) Note: this would fail for AspectJ!

24 Comparison to Aspect-Aware Interfaces AAI: more obliviousness, extensibility Don’t have to anticipate semantic pointcuts OM: truly separate development AAI cannot be computed in this case OM: shows technical properties of AAI AAI is an OM interface computed by tools Abstraction supports evolvability Not all information in AAI is needed Don’t need exact advice Don’t need pointcuts for external calls to interface functions

25 Tool and Language Implications Tools: Provide editable interface pointcuts Change base code and affected pointcuts at the same time Tools: Support dependency tracking Let you know when you’re depending on impl. Warn you to re-check pointcuts when impl. Changes Language Make it easier to write non-invasive pointcuts

26 Discussion Extensibility vs. Reasoning Tool vs. Language-based reasoning Open Modules into real AOP systems Analysis based on Open Modules

27 End of Presentation/Extra Slides

28 TinyAspect Example (* fibonacci function *) val fib = fn x:int => 1 around call(fib) (x:int) = if (x > 2) then fib(x-1) + fib(x-2) else proceed x (* caching library *) val inCache = fn... val lookupCache = fn... val updateCache = fn... (* advice to cache calls to fib *) pointcut cacheFunction = call(fib) around cacheFunction(x:int) = if (inCache x) then lookupCache x else let v = proceed x in updateCache x v; v

29 TinyAspect: Syntax

30 Evaluation Environment captures advice Declarations add labels to environment Functions are looked up just before application

31 Evaluation Environment captures advice Declarations add labels to environment Advice updates environment

32 TinyAspect: Values and Contexts

33 TinyAspect: Reduction Rules

34 TinyAspect: Expression Typing

35 TinyAspect: Declaration Typing

36 TinyAspect: Properties

37 Open Modules: Syntax

38 Open Modules: Example structure Math = struct val fib = fn x:int => 1 around call(fib) (x:int) = … structure cacheFib = Cache(struct pointcut f = call(fib) end) end :> sig fib : int->int end structure Cache = functor(X : sig f : pc(int->int) end) => struct around X.f(x:int) =... (* same definition *) end

39 Open Modules: Semantics Standard type system Signature subtyping permitted Runtime semantics mostly standard E.g, functor application uses substitution

40 Sealing has operational effect Value bindings given fresh labels External advice doesn’t affect internal calls C.f. “freeze” operator in Jigsaw, other systems Pointcuts are unchanged Open Modules: Semantics

41 Reynolds’ Abstraction Property No client can distinguish two modules that are “observationally equivalent” (c.f. Pi-calculus) calling functions in interface advising external calls to interface advising pointcuts in interface Means that information hiding works You can change the internals of a module w/o affecting clients

42 Observational Equivalence Functions behave equivalently for all args Expression evaluation must be bisimilar w.r.t. a set of available labels  Can take any step other than looking up  Can both look up the same label in 

43 Formal Abstraction Theorem Proof insight Client can only advise labels in  Libraries treat these labels equivalently Key invariant Clients are structurally identical Except for embedded equivalent values


Download ppt "A Formal Model of Modularity in Aspect-Oriented Programming Jonathan Aldrich 15-819: Objects and Aspects Carnegie Mellon University."

Similar presentations


Ads by Google