Aspect-Oriented Programming and Modular Reasoning G. KiczalesM. Mezini Presented by Alex Berendeyev

Preview:

Citation preview

Aspect-Oriented Programming

and Modular ReasoningG. Kiczales M. Mezini

Presented by Alex Berendeyev

2

Overview Goals Example Aspect-aware Interfaces and Their

Properties Modular Reasoning in AOP Reasoning about Change Open Issues

3

Goals

To identify the key properties of aspect-aware interfaces and their effect on modularity

Show that full power of AOP is compatible with modular reasoning

4

Example: Javainterface Shape { public moveBy(int dx, int dy); }

class Point implements Shape {

int x, y; //intentionally package public

public int getX() { return x; }

public int getY() { return y; }

public void setX(int x) { this.x = x; Display.update(); }

public void setY(int y) { this.y = y; Display.update(); }

public void moveBy(int dx, int dy) { x += dx; y += dy; Display.udpate(); }

}

class Line implements Shape {

private Point p1, p2;

public Point getP1() { return p1; }

public Point getP2() { return p2; }

public void moveBy(int dx, int dy) {

p1.x += dx; p1.y += dy;

p2.x += dx; p2.y += dy; Display.update ();

}

}

5

Example: AspectJinterface Shape { public moveBy(int dx, int dy); } class Point implements Shape {

int x, y; //intentionally package public public int getX() { return x; } public int getY() { return y; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void moveBy(int dx, int dy) { x += dx; y += dy; }

} class Line implements Shape {

private Point p1, p2; public Point getP1() { return p1; } public Point getP2() { return p2; } public void moveBy(int dx, int dy) {

p1.x += dx; p1.y += dy; p2.x += dx; p2.y += dy;

} } aspect UpdateSignaling {

pointcut change(): execution(void Point.setX(int)) || execution(void Point.setY(int))

|| execution(void Shape+.moveBy(int, int)); after() returning: change() {

Display.update(); }

}

6

Definition of Aspect-aware Interfaces

Aspect-aware interfaces are conventional interfaces augmented with information about the pointcuts and advice that apply to a module.

7

Example: Aspect-aware Interfaces

Shape void moveBy(int, int) : UpdateSignaling

– after UpdateSignaling.move();Point implements Shape

int x; int y; int getX(); int getY(); void setX(int) : UpdateSignaling

– after returning UpdateSignaling.move(); void setY(int) : UpdateSignaling

– after returning UpdateSignaling.move(); void moveBy(int, int) : UpdateSignaling

– after returning UpdateSignaling.move(); Line implements Shape

void moveBy(int, int) : UpdateSignaling – after returning UpdateSignaling.move();

UpdateSignaling after returning: UpdateSignaling.move(): Point.setX(int), Point.setY(int), Point.moveBy(int, int), Line.moveBy(int, int);

8

Properties of Aspect-aware Interfaces Interfaces depend on deployment

Aspects contribute to interface of classes Classes contribute to interface of aspects

Therefore, A complete system configuration is necessary

to define interfaces A system may have different interfaces

9

Statements Modules remain the same Composition leads to new crosscutting

interfaces Modular Reasoning requires a global

analysis of deployment configuration

10

Formulation of Aspect-Aware Interfaces(1) Intensional descriptions

Line implements Shape void moveBy(int, int) : UpdateSignaling – after returning UpdateSignaling.move();

11

Formulation of Aspect-Aware Interfaces(2) Extensional descriptions

UpdateSignaling after returning: UpdateSignaling.move():

Point.setX(int), Point.setY(int), Point.moveBy(int, int),

Line.moveBy(int, int);

12

Formulation of Aspect-Aware Interfaces(3) Point abstraction or reduction

UpdateSignaling after returning: UpdateSignaling.move():

Point.setX(int), Point.setY(int), Point.moveBy(int, int), Line.moveBy(int, int);

Including advice kindLine implements Shape

void moveBy(int, int) : UpdateSignaling – after returning UpdateSignaling.move();

13

Modular Reasoning: Criteria Localized implementation

Code is textually local Descriptive well-defined interface

Describes how a module interacts with the rest of the system

Abstraction abstracts implementation

Interface enforcement Type checking (e.g. by a compiler)

Composability Modules can be composed automatically (e.g.

by a class loader)

14

Modularity Analysis: Non-AOP Localized implementation

Textually local, but the boundary also includes display update

Descriptive well-defined interface Interfaces are clearly defined, but they fail to say

anything about the included display update behavior Abstraction

The internal details of the classes could change without changing the interface. The coordinates of a Point could be stored differently for example

Interface enforcement The interfaces are enforced in that the Java type

checker, loader and virtual machine ensure type safety Composability

The Java loader can load these with other classes in different configurations

15

Example: Javainterface Shape { public moveBy(int dx, int dy); }

class Point implements Shape {

int x, y; //intentionally package public

public int getX() { return x; }

public int getY() { return y; }

public void setX(int x) { this.x = x; Display.update(); }

public void setY(int y) { this.y = y; Display.update(); }

public void moveBy(int dx, int dy) { x += dx; y += dy; Display.udpate(); }

}

class Line implements Shape {

private Point p1, p2;

public Point getP1() { return p1; }

public Point getP2() { return p2; }

public void moveBy(int dx, int dy) {

p1.x += dx; p1.y += dy;

p2.x += dx; p2.y += dy; Display.update();

}

}

16

Modularity Analysis: AOP Localized implementation

Locality is improved over the non-AOP implementation because the update signaling behavior is not tangled into the Point and Line classes

Descriptive well-defined interface The interfaces are now a more accurate

reflection of their behavior – update signaling is reflected in the interfaces as arising from the interaction between the aspects and the classes

17

Example: AspectJinterface Shape { public moveBy(int dx, int dy); } class Point implements Shape {

int x, y; //intentionally package public public int getX() { return x; } public int getY() { return y; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void moveBy(int dx, int dy) { x += dx; y += dy; }

} class Line implements Shape {

private Point p1, p2; public Point getP1() { return p1; } public Point getP2() { return p2; } public void moveBy(int dx, int dy) {

p1.x += dx; p1.y += dy; p2.x += dx; p2.y += dy;

} } aspect UpdateSignaling {

pointcut change(): execution(void Point.setX(int)) || execution(void Point.setY(int))

|| execution(void Shape+.moveBy(int, int)); after() returning: change() {

Display.update(); }

}

18

Modularity Analysis: AOP (2) Abstraction

There is room for material variation in how each is implemented. For example, a helper method could be called to do the signaling, or the signaling could be logged

Interface enforcement Type checking works in the usual way, and in addition

the advice is called when it should be and at no other times.

Composability It is possible to automatically produce a configuration

that includes the shape classes but not the UpdateSignaling aspect.

19

Modularity Analysis: Comparison

20

Definitions Modular reasoning means being able to

make decisions about a module while looking only at its implementation, its interface and the interfaces of modules referenced in its implementation or interface

Expanded modular reasoning means also consulting the implementations of referenced modules

Global reasoning means having to examine all the modules in the system or sub-system

21

Reasoning about Change: Non-AOP int x, y; //intentionally package public private int x, y;

Step 1: Global Reasoning

public void moveBy(int dx, int dy) { p1.x += dx; p1.y += dy; p2.x += dx; p2.y += dy; Display.update();

}

TO

public void moveBy(int dx, int dy) { p1.setX(p1.getX() + dx); p1.setY(p1.getY() + dy); p2.setX(p2.getX() + dx); p2.setY(p2.getY() + dy); Display.update(); //double update

}

22

Reasoning about Change: Non-AOP(2)Step 2: Reasoning about the change A description of the invariant

Implementation of the Display class or it’s documentation

expanded modular reasoning

Structure of update signaling global reasoning – to find all calls to update

and discover the complete structure of display update signalingOR

expanded modular reasoning – to just find the calls from setX and setY

23

Reasoning about Change: AOP int x, y; //intentionally package public private int x, y;

Step 1: Global Reasoning

public void moveBy(int dx, int dy) { p1.setX(p1.getX() + dx); p1.setY(p1.getY() + dy); p2.setX(p2.getX() + dx); p2.setY(p2.getY() + dy);

}

after() returning: change() && !cflowbelow(change()) { Display.update();

}

24

Reasoning about Change: AOP(2)Step 2: Reasoning about the change A description of the invariant

Documented in UpdateSignaling one-step expanded modular reasoning

Documented in Display two-step expanded modular reasoning

Structure of update signaling The interface of UpdateSignaling is enough

modular reasoning

25

Reasoning about Change: Comparison global reasoning is

required to find all the references to the x and y fields.

documenting and allowing the programmer to discover the invariant

discovering the structure of update signaling

Non-AOP AOP

one-step expanded modular reasoning

one (two)-step expanded modular reasoning

global reasoningORexpanded modular reasoning

modular reasoning

26

Open Issues expand our concept of aspect-aware

interfaces and the analysis here to full AspectJ (call, get and set join points)

higher-order value typing like generic types, state typing, behavioral specification

increase the expressive power and abstraction of pointcuts

Support for use of annotations

Recommended