aspect oriented programming and design

89
Aspect-Oriented Programming and Design For Java and AspectJ Dean Wampler Object Mentor, Inc. [email protected] 1 Friday, September 7, 2007

Upload: manikanda-kumar

Post on 12-May-2015

4.441 views

Category:

Technology


5 download

TRANSCRIPT

public class Account { public Money getBalance() {...} public void credit(Money m) {...} public void debit(Money m) {...} ... }

2Friday, September 7, 2007

public void credit(Money m) { balance += m;}

For example...

3Friday, September 7, 2007

Cleanand

Simple4Friday, September 7, 2007

However,

Real applications need:

public class BankAccount {

public Money getBalance(){...}

public void credit(Money m) {...}

public void debit(Money m) {...}

...

}

Transactions

Persistence

Security

5Friday, September 7, 2007

public void credit(Money m) { if (unauthorized()) throw new ...(); Money saveBalance = balance; try { beginTransaction(); balance += m; persistBalance(balance); } ...

Back to our example...

6Friday, September 7, 2007

... } catch (...) { balance = savedBalance; } finally { endTransaction(); }}

7Friday, September 7, 2007

What’s wrong??

8Friday, September 7, 2007

We’re mixing multiple domains,

Transactions

Persistence

Security

with fine-grained intersections.

“Problem Domain”

“tangled” code

“scattered” logic

9Friday, September 7, 2007

Aspects restore modularity byencapsulating the intersections.

Transactions

Persistence

Security

TransactionAspect

PersistenceAspect

SecurityAspect

10Friday, September 7, 2007

Obvious uses:

PersistenceTransactions

SecurityLogging

others...

11Friday, September 7, 2007

public void credit(Money m) { balance += m;}

Back to our example...

Back to what we want...

12Friday, September 7, 2007

public aspect PersistentAccount{ pointcut newBalance ( Account a, Money newBal): set (Money Account.balance) && args (newBal) && this (a); ...

Back to our example...class-like declaration

named set of “join points”

bind variables

any time “balance” is setremember new value

remember “this”

13Friday, September 7, 2007

... after ( Account a, Money newBal) : newBalance(a, newBal) { persist(a, newBal);}

Back to our example...

“after advice” same arguments

same pointcut

body of the advice

14Friday, September 7, 2007

Types of advice

beforeafter returningafter throwing

afteraround

15Friday, September 7, 2007

Other terms

• Join point

• Pointcut

• Advice

• Cross-cutting concern

• Introduction (a.k.a. Inter-type declaration)

• Aspect

16Friday, September 7, 2007

Pure Java AOPSpring AOPJBoss AOP

17Friday, September 7, 2007

Spring AOP@AspectJ Support

18Friday, September 7, 2007

@Aspect class PersistentAccount { @Pointcut (“execution(* Account.*(..))”) private void newBalance() {}

@After(“newBalance()”) private void persistChange() {...}}

19Friday, September 7, 2007

<aop:aspectj-autoproxy/>...<bean id=”persistantAccount” class=”...PersistentAccount”> <!-- properties of bean --></bean>

auto-configure @Aspects

The usual Spring bean stuff...

20Friday, September 7, 2007

<aop:config> <aop:advisor pointcut="....newBalance()" advice-ref="tx-advice"/> </aop:config>

<tx:advice id="tx-advice"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>

Wire another advice using XML

21Friday, September 7, 2007

Spring’sDependency Injection

can also wire “POJO” aspects

22Friday, September 7, 2007

Recommendation:Use Spring to introduce AOP into your environment.

23Friday, September 7, 2007

JBoss AOP works in similar ways.

24Friday, September 7, 2007

Aspect-Oriented Design(Starting in the early years)

25Friday, September 7, 2007

“Classes should be oblivious to aspects.”

26Friday, September 7, 2007

However, this leads to...

27Friday, September 7, 2007

Persistence Aspect

PCD: set (* *.name)

Account

name

Account

first_namelast_name

Version 1 Version 2

???X

28Friday, September 7, 2007

Aspects make initial version easier,

But subsequent versions harder!

29Friday, September 7, 2007

AOP-Evolution

Paradox!

30Friday, September 7, 2007

Obliviousness ...

... is like that.

31Friday, September 7, 2007

We forgot established

OOD Principles.

32Friday, September 7, 2007

Principles of OOD

11

33Friday, September 7, 2007

Single Responsibility Principle

A class should have only one reason to change.

#1

34Friday, September 7, 2007

Open-Closed Principle

A module should be open for extension, but closed

for modification.

#2

35Friday, September 7, 2007

An Example...

36Friday, September 7, 2007

public interface Shape { public double getArea(); public void draw(); }

37Friday, September 7, 2007

public abstract class Polygon implements Shape { public Point getVertex(int index)

{...} public void draw() {...} public String toString() {...} }

38Friday, September 7, 2007

public class Square extends Polygon { public double getArea() {...} }

public class Rectangle extends Polygon { public double getArea() {...}}

39Friday, September 7, 2007

Square is a Rectangle?

Isn’t it?

is a

40Friday, September 7, 2007

public interface Shape { public double getArea(); public void draw(); }

An Aspect Refactoring...

41Friday, September 7, 2007

public abstract class Polygon implements Shape { public Point getVertex(int index)

{...} public void draw() {...} public String toString() {...} }

42Friday, September 7, 2007

package shapes.tostring;public aspect PolygonToString { public String Polygon.toString() {...} }

43Friday, September 7, 2007

package drawing;public interface Drawable { void draw(); }

44Friday, September 7, 2007

package shapes.drawing;import drawing.Drawable;

abstract aspect DrawableShape { declare parents:

Shape implements Drawable;

public void Shape.draw() { String cmd = makeDrawCmd();getGraphics().sendCmd(cmd);

}abstract String makeDrawCmd();

} 45Friday, September 7, 2007

Liskov Substitution Principle

Subtypes must be substitutable for their

base types.

#3

46Friday, September 7, 2007

Square is a Rectangle?is a

What do the unit tests say?

47Friday, September 7, 2007

public RectangleDrawTest extends ... {

public void testDraw {Shape[] shapes = new Shapes[] {new Rectangle(...),new Square(...)};

for (Shape s: shapes)s.draw(); // just works...

}}

48Friday, September 7, 2007

Apparently, it is!!

Square is a Rectangle?is a

(at least in this context...)

49Friday, September 7, 2007

Mutability...

50Friday, September 7, 2007

public abstract class Polygon implements Shape { public Point getVertex(int index)

{...} List<Point> getVertices() {...}}

Need to Change Polygon:

Occasionally need to break OCP...

Package private!

51Friday, September 7, 2007

package shapes; // same packageimport ...;

aspect MutablePolygon {

public void Polygon.setHeight(int i) { List<Point> list = getVertices(); // Change appropriate points... } public void Polygon.setWidth(int i) {...} }

52Friday, September 7, 2007

Square is a Rectangle?is a

53Friday, September 7, 2007

public MutableRectangleTest ... {public void testSetWidth{Point p00, p20, p25, p05 = ...;Rectangle rect = new Rectangle(p00,p20,p25,p05);

(0,0)

(0,5) (2,5)

(2,0)

54Friday, September 7, 2007

public MutableRectangleTest ... {public void testSetWidth{Point p00, p20, p25, p05 = ...;Rectangle r = new Rectangle(p00,p20,p25,p05);assertEquals(2, r.getWidth());assertEquals(5, r.getHeight());

}}

r.setWidth(3);assertEquals(3, r.getWidth());assertEquals(5, r.getHeight());

55Friday, September 7, 2007

Square is a Rectangle?

Prove it! (or not...)

is a

56Friday, September 7, 2007

...Rectangle r = new Square(p00,p50,p55,p05);assertEquals(5, r.getWidth());assertEquals(5, r.getHeight());

r.setWidth(3);

assertEquals(3, r.getWidth());assertEquals(5, r.getHeight());

What if I Use a Square?

This won’t pass!

57Friday, September 7, 2007

Square is a Rectangle?

Not inthis context!!

is a

58Friday, September 7, 2007

LSP

Context Dependent!

Is

59Friday, September 7, 2007

LSP Is the Basis for

Design by Contract

60Friday, September 7, 2007

Shameless Plug...61Friday, September 7, 2007

@Contractpublic abstract class Polygon implements Shape { @Pre(“index>=0”)@Post(“$return != null”) public Point getVertex(int index){...}

}

Contract4J: DbC for Javaannotation-based

62Friday, September 7, 2007

Dependency Inversion Principle

Abstractions should not depend upon details.

Details should depend upon abstractions.

#5

63Friday, September 7, 2007

Client

Service

Client Service

Service

64Friday, September 7, 2007

Client «aspec t»ClientService

Service

Client «aspec t»ClientService

Service

Client Service

Service

65Friday, September 7, 2007

New AOD Principles

66Friday, September 7, 2007

package shapes.tostring;public aspect PolygonToString { public String Polygon.toString() {...} } Do introductions violate OCP??

No

67Friday, September 7, 2007

Open-Closed Principle: UpdatedA module should be open for

extension, but closed for source and contract modification.

68Friday, September 7, 2007

public aspect Tracer { before(): call(* Polygon.*(..)) { log(thisJoinPointStaticPart); } }

public class LoggedPolygonDraws { public void draw() { log(“Polygon.draw”); super.draw(); } }

Similar!

69Friday, September 7, 2007

Liskov Substitution Principle: Updated

Subtypes and aspects + base types must be substitutable for

their base types.

70Friday, September 7, 2007

public aspect PolygonMunger { before(Polygon p): target(p) && call(* Polygon.draw(..)) { p.addPoint(new Point(/*...*/)); } }

Does this look safe??

71Friday, September 7, 2007

Advice Substitution Principle

Advice must obey the contract of the advised join point.

72Friday, September 7, 2007

public aspect CirclingPolygons { public double Polygon.getRadius() {...} public Point Polygon.getCenter() {...}}

Huh??

73Friday, September 7, 2007

Introduction Substitution Principle

Introductions must obey the contract of the module.

74Friday, September 7, 2007

public aspect PersistentAccount { after (Account a): target(a) && call(* Account.setName()) { persistName(a.getName()); }}

What happens when “name” is refactored to “firstName” and “lastName”??

75Friday, September 7, 2007

Pointcut Inversion Principle

Pointcuts should not depend upon concrete details.

Pointcuts should depend upon abstractions.

76Friday, September 7, 2007

The Future of AOP

77Friday, September 7, 2007

• Much hyped in the 90s

• All or nothing proposition

• ... due to internal dependencies

Components and Frameworks

Can aspects reduce the coupling and make them more reusable?

78Friday, September 7, 2007

Client «aspec t»ClientService

Service

Client «aspec t»ClientService

Service

79Friday, September 7, 2007

• High-level defines policy

• Low-level defines details

Improved Architectures

Better separation using aspects?

80Friday, September 7, 2007

• Domain-Specific Languages for the high-level

• Connect to low-level details with aspects

Improved Architectures

81Friday, September 7, 2007

public class PersistenceDSL { public PersistenceDSL() { after() .calling(methodsIn( interface(StateChange.class))) .then(persistChange()); }}

(Fanciful, made-up example...)

82Friday, September 7, 2007

Conclusions

83Friday, September 7, 2007

Real applications...

mix multiple domains...

causing tangled code.

84Friday, September 7, 2007

Objects alone don’t prevent this tangling.

85Friday, September 7, 2007

Aspects modularize the intersection

of the domains.intersection

86Friday, September 7, 2007

Obvious uses:

PersistenceTransactions

SecurityLogging

others...

87Friday, September 7, 2007

The future?

Better architectures(Domain-specific languages)

Better components and frameworks

88Friday, September 7, 2007