Aspect Oriented Programming and Design

4,972 views

Published on

Published in: Technology, News & Politics
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,972
On SlideShare
0
From Embeds
0
Number of Embeds
2,448
Actions
Shares
0
Downloads
172
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Aspect Oriented Programming and Design

  1. 1. Aspect-Oriented Programming and Design For Java and AspectJ Dean Wampler Object Mentor, Inc. dean@objectmentor.com Friday, September 7, 2007 1
  2. 2. public class Account { public Money getBalance() {...} public void credit(Money m) {...} public void debit(Money m) {...} ... } Friday, September 7, 2007 2
  3. 3. For example... public void credit(Money m) { balance += m; } Friday, September 7, 2007 3
  4. 4. Clean and Simple Friday, September 7, 2007 4
  5. 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. 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. 7. ... } catch (...) { balance = savedBalance; } finally { endTransaction(); } } Friday, September 7, 2007 7
  8. 8. What’s wrong?? Friday, September 7, 2007 8
  9. 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. 10. Aspects restore modularity by encapsulating the intersections. Transaction Transactions Aspect Persistence Persistence Aspect Security Security Aspect Friday, September 7, 2007 10
  11. 11. Obvious uses: Persistence Transactions Security Logging others... Friday, September 7, 2007 11
  12. 12. Back to our example... public void credit(Money m) { balance += m; } Back to what we want... Friday, September 7, 2007 12
  13. 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. 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. 15. Types of advice before after returning after throwing after around Friday, September 7, 2007 15
  16. 16. Other terms • Join point • Pointcut • Advice • Cross-cutting concern • Introduction (a.k.a. Inter-type declaration) • Aspect Friday, September 7, 2007 16
  17. 17. Pure Java AOP Spring AOP JBoss AOP Friday, September 7, 2007 17
  18. 18. Spring AOP @AspectJ Support Friday, September 7, 2007 18
  19. 19. @Aspect class PersistentAccount { @Pointcut (“execution(* Account.*(..))”) private void newBalance() {} @After(“newBalance()”) private void persistChange() {...} } Friday, September 7, 2007 19
  20. 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. 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. 22. Spring’s Dependency Injection can also wire “POJO” aspects Friday, September 7, 2007 22
  23. 23. Recommendation: Use Spring to introduce AOP into your environment. Friday, September 7, 2007 23
  24. 24. JBoss AOP works in similar ways. Friday, September 7, 2007 24
  25. 25. Aspect-Oriented Design (Starting in the early years) Friday, September 7, 2007 25
  26. 26. “Classes should be oblivious to aspects.” Friday, September 7, 2007 26
  27. 27. However, this leads to... Friday, September 7, 2007 27
  28. 28. Persistence Aspect PCD: set (* *.name) X ??? Account Account first_name name last_name Version 1 Version 2 Friday, September 7, 2007 28
  29. 29. Aspects make initial version easier, But subsequent versions harder! Friday, September 7, 2007 29
  30. 30. ! AOP-Evolution x o d a r a P Friday, September 7, 2007 30
  31. 31. Obliviousness ... ... is like that. Friday, September 7, 2007 31
  32. 32. We forgot established OOD Principles. Friday, September 7, 2007 32
  33. 33. 11 Principles of OOD Friday, September 7, 2007 33
  34. 34. #1 Single Responsibility Principle A class should have only one reason to change. Friday, September 7, 2007 34
  35. 35. #2 Open-Closed Principle A module should be open for extension, but closed for modification. Friday, September 7, 2007 35
  36. 36. An Example... Friday, September 7, 2007 36
  37. 37. public interface Shape { public double getArea(); public void draw(); } Friday, September 7, 2007 37
  38. 38. public abstract class Polygon implements Shape { public Point getVertex(int index) {...} public void draw() {...} public String toString() {...} } Friday, September 7, 2007 38
  39. 39. public class Square extends Polygon { public double getArea() {...} } public class Rectangle extends Polygon { public double getArea() {...} } Friday, September 7, 2007 39
  40. 40. Square is a Rectangle? Isn’t it? Friday, September 7, 2007 40
  41. 41. An Aspect Refactoring... public interface Shape { public double getArea(); public void draw(); } Friday, September 7, 2007 41
  42. 42. public abstract class Polygon implements Shape { public Point getVertex(int index) {...} public void draw() {...} public String toString() {...} } Friday, September 7, 2007 42
  43. 43. package shapes.tostring; public aspect PolygonToString { public String Polygon.toString() {...} } Friday, September 7, 2007 43
  44. 44. package drawing; public interface Drawable { void draw(); } Friday, September 7, 2007 44
  45. 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. 46. #3 Liskov Substitution Principle Subtypes must be substitutable for their base types. Friday, September 7, 2007 46
  47. 47. Square is a Rectangle? What do the unit tests say? Friday, September 7, 2007 47
  48. 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. 49. Square is a Rectangle? Apparently, it is!! (at least in this context...) Friday, September 7, 2007 49
  50. 50. Mutability... Friday, September 7, 2007 50
  51. 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. 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. 53. Square is a Rectangle? Friday, September 7, 2007 53
  54. 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. 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. 56. Square is a Rectangle? Prove it! (or not...) Friday, September 7, 2007 56
  57. 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. 58. Square is a Rectangle? Not in this context!! Friday, September 7, 2007 58
  59. 59. LSP Is Context Dependent! Friday, September 7, 2007 59
  60. 60. LSP Is the Basis for Design by Contract Friday, September 7, 2007 60
  61. 61. Shameless Plug... Friday, September 7, 2007 61
  62. 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. 63. #5 Dependency Inversion Principle Abstractions should not depend upon details. Details should depend upon abstractions. Friday, September 7, 2007 63
  64. 64. Client Service Client Service Service Friday, September 7, 2007 64
  65. 65. Service Client Service «aspect» «aspect» Client Client ClientService ClientService Service Service Friday, September 7, 2007 65
  66. 66. New AOD Principles Friday, September 7, 2007 66
  67. 67. package shapes.tostring; public aspect PolygonToString { public String Polygon.toString() {...} } Do introductions violate OCP?? No Friday, September 7, 2007 67
  68. 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. 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. 70. Liskov Substitution Principle: Updated Subtypes and aspects + base types must be substitutable for their base types. Friday, September 7, 2007 70
  71. 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. 72. Advice Substitution Principle Advice must obey the contract of the advised join point. Friday, September 7, 2007 72
  73. 73. public aspect CirclingPolygons { public double Polygon.getRadius() {...} public Point Polygon.getCenter() {...} } Huh?? Friday, September 7, 2007 73
  74. 74. Introduction Substitution Principle Introductions must obey the contract of the module. Friday, September 7, 2007 74
  75. 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. 76. Pointcut Inversion Principle Pointcuts should not depend upon concrete details. Pointcuts should depend upon abstractions. Friday, September 7, 2007 76
  77. 77. The Future of AOP Friday, September 7, 2007 77
  78. 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. 79. «aspect» «aspect» Client Client ClientService ClientService Service Service Friday, September 7, 2007 79
  80. 80. Improved Architectures • High-level defines policy • Low-level defines details Better separation using aspects? Friday, September 7, 2007 80
  81. 81. Improved Architectures • Domain-Specific Languages for the high-level • Connect to low-level details with aspects Friday, September 7, 2007 81
  82. 82. public class PersistenceDSL { public PersistenceDSL() { after() .calling(methodsIn( interface(StateChange.class))) .then(persistChange()); } } (Fanciful, made-up example...) Friday, September 7, 2007 82
  83. 83. Conclusions Friday, September 7, 2007 83
  84. 84. Real applications... mix multiple domains... causing tangled code. Friday, September 7, 2007 84
  85. 85. Objects alone don’t prevent this tangling. Friday, September 7, 2007 85
  86. 86. Aspects modularize the intersection of the domains. Friday, September 7, 2007 86
  87. 87. Obvious uses: Persistence Transactions Security Logging others... Friday, September 7, 2007 87
  88. 88. The future? Better components and frameworks Better architectures (Domain-specific languages) Friday, September 7, 2007 88
  89. 89. Thank You! • dean@objectmentor.com • http://objectmentor.com • http://aspectprogramming.com • http://contract4j.org • http://aquarium.rubyforge.org Friday, September 7, 2007 89

×