Aspect Oriented Programming and Design

  • 4,307 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
4,307
On Slideshare
0
From Embeds
0
Number of Embeds
5

Actions

Shares
Downloads
156
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Aspect-Oriented Programming and Design For Java and AspectJ Dean Wampler Object Mentor, Inc. dean@objectmentor.com Friday, September 7, 2007 1
  • 2. public class Account { public Money getBalance() {...} public void credit(Money m) {...} public void debit(Money m) {...} ... } Friday, September 7, 2007 2
  • 3. For example... public void credit(Money m) { balance += m; } Friday, September 7, 2007 3
  • 4. Clean and Simple Friday, September 7, 2007 4
  • 5. However, Real applications need: Transactions public class BankAccount { public Money getBalance(){...} public void credit(Money m) {...} Persistence public void debit(Money m) {...} ... } Security Friday, September 7, 2007 5
  • 6. Back to our example... public void credit(Money m) { if (unauthorized()) throw new ...(); Money saveBalance = balance; try { beginTransaction(); balance += m; persistBalance(balance); } ... Friday, September 7, 2007 6
  • 7. ... } catch (...) { balance = savedBalance; } finally { endTransaction(); } } Friday, September 7, 2007 7
  • 8. What’s wrong?? Friday, September 7, 2007 8
  • 9. We’re mixing multiple domains, with fine-grained intersections. “tangled” code Transactions Persistence Security “Problem Domain” “scattered” logic Friday, September 7, 2007 9
  • 10. Aspects restore modularity by encapsulating the intersections. Transaction Transactions Aspect Persistence Persistence Aspect Security Security Aspect Friday, September 7, 2007 10
  • 11. Obvious uses: Persistence Transactions Security Logging others... Friday, September 7, 2007 11
  • 12. Back to our example... public void credit(Money m) { balance += m; } Back to what we want... Friday, September 7, 2007 12
  • 13. Back to our example... class-like declaration public aspect PersistentAccount{ pointcut newBalance ( bind variables Account a, Money newBal): set (Money Account.balance) && args (newBal) && this (a); remember “this” ... named set of “join points” remember new value any time “balance” is set Friday, September 7, 2007 13
  • 14. Back to our example... “after advice” ... same arguments after ( Account a, Money newBal) : same newBalance(a, newBal) { pointcut persist(a, newBal); } body of the advice Friday, September 7, 2007 14
  • 15. Types of advice before after returning after throwing after around Friday, September 7, 2007 15
  • 16. Other terms • Join point • Pointcut • Advice • Cross-cutting concern • Introduction (a.k.a. Inter-type declaration) • Aspect Friday, September 7, 2007 16
  • 17. Pure Java AOP Spring AOP JBoss AOP Friday, September 7, 2007 17
  • 18. Spring AOP @AspectJ Support Friday, September 7, 2007 18
  • 19. @Aspect class PersistentAccount { @Pointcut (“execution(* Account.*(..))”) private void newBalance() {} @After(“newBalance()”) private void persistChange() {...} } Friday, September 7, 2007 19
  • 20. auto-configure @Aspects <aop:aspectj-autoproxy/> ... <bean id=”persistantAccount” class=”...PersistentAccount”> <!-- properties of bean --> </bean> The usual Spring bean stuff... Friday, September 7, 2007 20
  • 21. <aop:config> Wire another advice using XML <aop:advisor pointcut=quot;....newBalance()quot; advice-ref=quot;tx-advicequot;/> </aop:config> <tx:advice id=quot;tx-advicequot;> <tx:attributes> <tx:method name=quot;*quot; propagation=quot;REQUIREDquot;/> </tx:attributes> </tx:advice> Friday, September 7, 2007 21
  • 22. Spring’s Dependency Injection can also wire “POJO” aspects Friday, September 7, 2007 22
  • 23. Recommendation: Use Spring to introduce AOP into your environment. Friday, September 7, 2007 23
  • 24. JBoss AOP works in similar ways. Friday, September 7, 2007 24
  • 25. Aspect-Oriented Design (Starting in the early years) Friday, September 7, 2007 25
  • 26. “Classes should be oblivious to aspects.” Friday, September 7, 2007 26
  • 27. However, this leads to... Friday, September 7, 2007 27
  • 28. Persistence Aspect PCD: set (* *.name) X ??? Account Account first_name name last_name Version 1 Version 2 Friday, September 7, 2007 28
  • 29. Aspects make initial version easier, But subsequent versions harder! Friday, September 7, 2007 29
  • 30. ! AOP-Evolution x o d a r a P Friday, September 7, 2007 30
  • 31. Obliviousness ... ... is like that. Friday, September 7, 2007 31
  • 32. We forgot established OOD Principles. Friday, September 7, 2007 32
  • 33. 11 Principles of OOD Friday, September 7, 2007 33
  • 34. #1 Single Responsibility Principle A class should have only one reason to change. Friday, September 7, 2007 34
  • 35. #2 Open-Closed Principle A module should be open for extension, but closed for modification. Friday, September 7, 2007 35
  • 36. An Example... Friday, September 7, 2007 36
  • 37. public interface Shape { public double getArea(); public void draw(); } Friday, September 7, 2007 37
  • 38. public abstract class Polygon implements Shape { public Point getVertex(int index) {...} public void draw() {...} public String toString() {...} } Friday, September 7, 2007 38
  • 39. public class Square extends Polygon { public double getArea() {...} } public class Rectangle extends Polygon { public double getArea() {...} } Friday, September 7, 2007 39
  • 40. Square is a Rectangle? Isn’t it? Friday, September 7, 2007 40
  • 41. An Aspect Refactoring... public interface Shape { public double getArea(); public void draw(); } Friday, September 7, 2007 41
  • 42. public abstract class Polygon implements Shape { public Point getVertex(int index) {...} public void draw() {...} public String toString() {...} } Friday, September 7, 2007 42
  • 43. package shapes.tostring; public aspect PolygonToString { public String Polygon.toString() {...} } Friday, September 7, 2007 43
  • 44. package drawing; public interface Drawable { void draw(); } Friday, September 7, 2007 44
  • 45. 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(); } Friday, September 7, 2007 45
  • 46. #3 Liskov Substitution Principle Subtypes must be substitutable for their base types. Friday, September 7, 2007 46
  • 47. Square is a Rectangle? What do the unit tests say? Friday, September 7, 2007 47
  • 48. public RectangleDrawTest { extends ... public void testDraw { Shape[] shapes = new Shapes[] { new Rectangle(...), new Square(...)}; for (Shape s: shapes) s.draw(); // just works... } } Friday, September 7, 2007 48
  • 49. Square is a Rectangle? Apparently, it is!! (at least in this context...) Friday, September 7, 2007 49
  • 50. Mutability... Friday, September 7, 2007 50
  • 51. Need to Change Polygon: public abstract class Polygon implements Shape { public Point getVertex(int index) {...} List<Point> getVertices() {...} } Occasionally need to break OCP... Package private! Friday, September 7, 2007 51
  • 52. package shapes; // same package import ...; aspect MutablePolygon { public void Polygon.setHeight(int i) { List<Point> list = getVertices(); // Change appropriate points... } public void Polygon.setWidth(int i) {...} } Friday, September 7, 2007 52
  • 53. Square is a Rectangle? Friday, September 7, 2007 53
  • 54. public MutableRectangleTest ... { public void testSetWidth{ Point p00, p20, p25, p05 = ...; Rectangle rect = new Rectangle(p00,p20,p25,p05); (0,5) (2,5) (0,0) (2,0) Friday, September 7, 2007 54
  • 55. 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()); } } Friday, September 7, 2007 55
  • 56. Square is a Rectangle? Prove it! (or not...) Friday, September 7, 2007 56
  • 57. What if I Use a Square? ... 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()); This won’t pass! Friday, September 7, 2007 57
  • 58. Square is a Rectangle? Not in this context!! Friday, September 7, 2007 58
  • 59. LSP Is Context Dependent! Friday, September 7, 2007 59
  • 60. LSP Is the Basis for Design by Contract Friday, September 7, 2007 60
  • 61. Shameless Plug... Friday, September 7, 2007 61
  • 62. Contract4J: DbC for Java annotation-based @Contract public abstract class Polygon implements Shape { @Pre(“index>=0”) @Post(“$return != null”) public Point getVertex(int index) {...} } Friday, September 7, 2007 62
  • 63. #5 Dependency Inversion Principle Abstractions should not depend upon details. Details should depend upon abstractions. Friday, September 7, 2007 63
  • 64. Client Service Client Service Service Friday, September 7, 2007 64
  • 65. Service Client Service «aspect» «aspect» Client Client ClientService ClientService Service Service Friday, September 7, 2007 65
  • 66. New AOD Principles Friday, September 7, 2007 66
  • 67. package shapes.tostring; public aspect PolygonToString { public String Polygon.toString() {...} } Do introductions violate OCP?? No Friday, September 7, 2007 67
  • 68. Open-Closed Principle: Updated A module should be open for extension, but closed for source and contract modification. Friday, September 7, 2007 68
  • 69. public aspect Tracer { before(): call(* Polygon.*(..)) { log(thisJoinPointStaticPart); } Similar! } public class LoggedPolygonDraws { public void draw() { log(“Polygon.draw”); super.draw(); } } Friday, September 7, 2007 69
  • 70. Liskov Substitution Principle: Updated Subtypes and aspects + base types must be substitutable for their base types. Friday, September 7, 2007 70
  • 71. public aspect PolygonMunger { before(Polygon p): target(p) && call(* Polygon.draw(..)) { p.addPoint(new Point(/*...*/)); } } Does this look safe?? Friday, September 7, 2007 71
  • 72. Advice Substitution Principle Advice must obey the contract of the advised join point. Friday, September 7, 2007 72
  • 73. public aspect CirclingPolygons { public double Polygon.getRadius() {...} public Point Polygon.getCenter() {...} } Huh?? Friday, September 7, 2007 73
  • 74. Introduction Substitution Principle Introductions must obey the contract of the module. Friday, September 7, 2007 74
  • 75. public aspect PersistentAccount { after (Account a): target(a) && call(* Account.setName()) { persistName(a.getName()); } } What happens when “name” is refactored to “firstName” and “lastName”?? Friday, September 7, 2007 75
  • 76. Pointcut Inversion Principle Pointcuts should not depend upon concrete details. Pointcuts should depend upon abstractions. Friday, September 7, 2007 76
  • 77. The Future of AOP Friday, September 7, 2007 77
  • 78. Components and Frameworks • Much hyped in the 90s • All or nothing proposition • ... due to internal dependencies Can aspects reduce the coupling and make them more reusable? Friday, September 7, 2007 78
  • 79. «aspect» «aspect» Client Client ClientService ClientService Service Service Friday, September 7, 2007 79
  • 80. Improved Architectures • High-level defines policy • Low-level defines details Better separation using aspects? Friday, September 7, 2007 80
  • 81. Improved Architectures • Domain-Specific Languages for the high-level • Connect to low-level details with aspects Friday, September 7, 2007 81
  • 82. public class PersistenceDSL { public PersistenceDSL() { after() .calling(methodsIn( interface(StateChange.class))) .then(persistChange()); } } (Fanciful, made-up example...) Friday, September 7, 2007 82
  • 83. Conclusions Friday, September 7, 2007 83
  • 84. Real applications... mix multiple domains... causing tangled code. Friday, September 7, 2007 84
  • 85. Objects alone don’t prevent this tangling. Friday, September 7, 2007 85
  • 86. Aspects modularize the intersection of the domains. Friday, September 7, 2007 86
  • 87. Obvious uses: Persistence Transactions Security Logging others... Friday, September 7, 2007 87
  • 88. The future? Better components and frameworks Better architectures (Domain-specific languages) Friday, September 7, 2007 88
  • 89. Thank You! • dean@objectmentor.com • http://objectmentor.com • http://aspectprogramming.com • http://contract4j.org • http://aquarium.rubyforge.org Friday, September 7, 2007 89