1 / 37

Lecture 21: Crosscutting Aspect-Oriented Programming

Explore the concept of Aspect-Oriented Programming and its application in program organization, separation of concerns, and handling crosscutting aspects. Includes examples and discussion on AspectJ and Adaptive Programming.

eaguila
Download Presentation

Lecture 21: Crosscutting Aspect-Oriented Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lecture 21: Crosscutting Aspect-Oriented Programming "...feels like I've died and gone to Java Heaven." Don Asumu, Planning Tools Technical Development Leader, BT Laboratories on StructureBuilder, commercial tool based on Aspect-Oriented Programming, at http://www.webgain.com/Products/Structure_Builder/press_reviews.htm David Evans http://www.cs.virginia.edu/~evans CS655: Programming Languages University of Virginia Computer Science

  2. Menu • Self-Application Answer • Sorting in Linda • Aspect-Oriented Programming “Separation of Concerns” • Examples • D (Distributed Language) • AspectJ • Adaptive Programming University of Virginia CS 655

  3. Programming Paradigms • All the languages we have seen so far are “Generalized Procedure” languages: • Programs organized into procedures • Procedures may be grouped and associated with data • Some programs have properties (“aspects”) that cross-cut procedures • Examples: communication, synchronization, handling interrupts, security, loop fusion, etc. University of Virginia CS 655

  4. Aspect-Oriented Programming Components (Functional Units) Aspect Weaver Procedural Program Aspects (Non-functional Units) Compiler Executable University of Virginia CS 655

  5. Aspect Weaver Slide adapted from Gregor Kiczales ICSE Workshop Talk AO programming vs. idioms class Book { private String title; private String author; private String isbn; private PostScript ps; private User borrower; public Book(String t, String a, String i, PostScript p) { title = t; author = a; isbn = i; ps = p; } public User get_borrower() {return borrower;} public void set_borrower(User u) {borrower = u;} public PostScript get_ps() { return ps; } } class Book { private BookID id; private PostScript ps; private UserID borrower; public Book(String t, String a, String i, PostScript p) { id = new BookID(t,a,i); ps = p; } public UserID get_borrower() {return borrower;} public void set_borrower(UserID u) {borrower = u;} public PostScript get_ps() { return ps; } public BookID get_bid() { return id; } } class BookID { private String title; private String author; private String isbn; public BookID(String t, String a, String i) { title = t; author = a; isbn = i; } public String get_title() {return title;} } class User { private UserID id; Library theLibrary; Printer thePrinter; public User(String n) { id = new UserID(n); } public boolean getBook (String title) { BookID aBook=null; try{ aBook = theLibrary.getBook(id, title); } catch (RemoteException e) {} try { thePrinter.print(id, aBook); } catch (RemoteException e) {} return true; } public UserID get_uid() { return id; } } class UserID { private String name; public UserID(String n) { name = n; } public String get_name() { return name; } } public class PrinterImpl { String status = “Idle” Vector jobs; public PrinterImpl() {} pubilc get_status() { return status } public add_job(int j) { jobs.add(j); } } Classes class User { private String name; Library theLibrary; Printer the; Printer public User(String n) { name = n; } public boolean getBook (String title) { Book aBook = theLibrary.getBook(this, title); thePrinter.print(this,aBook); return true; } } class Library { Hashtable books; Library(){ books = new Hashtable(100); } public Book getBook(User u, String title) { System.out.println("REQUEST TO GET BOOK " + title); if(books.containsKey(title)) { Book b = (Book)books.get(title); System.out.println("getBook: Found it:" + b); if (b != null) { if (b.get_borrower() == null) b.set_borrower(u); return b; } } return null; } } interface PrinterInterface extends Remote { public boolean print (UserID u, BookID b) throws RemoteException; } public class Printer extends UnicastRemoteObject implements PrinterInterface { private Vector jobs = new Vector(10, 10); private Library theLibrary; public Printer() throws RemoteException{} public boolean print (UserID u, BookID b) throws RemoteException{ PostScript ps=null; try{ ps = theLibrary.getBookPS(b); } catch (RemoteException e) {} Job newJob = new Job (ps, u); return queue(newJob); } boolean queue(Job j) { //... return true; } } interface LibraryInterface extends Remote { public BookID getBook(UserID u, String title) throws RemoteException; public PostScript getBookPS(BookID bid) throws RemoteException; } class Library extends UnicastRemoteObject implements LibraryInterface { Hashtable books; Library() throws RemoteException{ books = new Hashtable(100); } public BookID getBook(UserID u, String title) throws RemoteException { System.out.println("REQUEST TO GET BOOK " + title); if(books.containsKey(title)) { Book b = (Book)books.get(title); System.out.println("getBook: Found it:" + b); if (b != null) { if (b.get_borrower() == null) b.set_borrower(u); return b.get_bid(); } } return null; } public PostScript getBookPS(BookID bid) throws RemoteException { if (books.containsKey(bid.get_title())) { Book b = (Book)books.get(bid.get_title()); if (b != null) return b.get_ps(); } return null; } } portal Library { Book find (String title){ return: Book: {copy title, author, isbn;} } } portal Printer { void print(Book book) { book: Book: {direct pages;} } Aspects class Book { private BookID id; private PostScript ps; private UserID borrower; public Book(String t, String a, String i, PostScript p) { id = new BookID(t,a,i); ps = p; } public UserID get_borrower() {return borrower;} public void set_borrower(UserID u) {borrower = u;} public PostScript get_ps() { return ps; } public BookID get_bid() { return id; } } class BookID { private String title; private String author; private String isbn; public BookID(String t, String a, String i) { title = t; author = a; isbn = i; } public String get_title() {return title;} } class User { private UserID id; Library theLibrary; Printer thePrinter; public User(String n) { id = new UserID(n); } public boolean getBook (String title) { BookID aBook=null; try{ aBook = theLibrary.getBook(id, title); } catch (RemoteException e) {} try { thePrinter.print(id, aBook); } catch (RemoteException e) {} return true; } public UserID get_uid() { return id; } } class UserID { private String name; public UserID(String n) { name = n; } public String get_name() { return name; } } interface PrinterInterface extends Remote { public boolean print (UserID u, BookID b) throws RemoteException; } public class Printer extends UnicastRemoteObject implements PrinterInterface { private Vector jobs = new Vector(10, 10); private Library theLibrary; public Printer() throws RemoteException{} public boolean print (UserID u, BookID b) throws RemoteException{ PostScript ps=null; try{ ps = theLibrary.getBookPS(b); } catch (RemoteException e) {} Job newJob = new Job (ps, u); return queue(newJob); } boolean queue(Job j) { //... return true; } } interface LibraryInterface extends Remote { public BookID getBook(UserID u, String title) throws RemoteException; public PostScript getBookPS(BookID bid) throws RemoteException; } class Library extends UnicastRemoteObject implements LibraryInterface { Hashtable books; Library() throws RemoteException{ books = new Hashtable(100); } public BookID getBook(UserID u, String title) throws RemoteException { System.out.println("REQUEST TO GET BOOK " + title); if(books.containsKey(title)) { Book b = (Book)books.get(title); System.out.println("getBook: Found it:" + b); if (b != null) { if (b.get_borrower() == null) b.set_borrower(u); return b.get_bid(); } } return null; } public PostScript getBookPS(BookID bid) throws RemoteException { if (books.containsKey(bid.get_title())) { Book b = (Book)books.get(bid.get_title()); if (b != null) return b.get_ps(); } return null; } } University of Virginia CS 655

  6. Join Points • Aspects defined at “Join Points” • Typically, method invocations, entry and exits • Not limited to that – defined by aspect language • Aspect languages are domain specific • Define code or transformations to occur at join points University of Virginia CS 655

  7. What is an aspect? • Definition 1: • A modular unit that has no stand-alone function • That is, it requires a context in order to function • And, that effects other modular units • Definition 2: • Something that implements properties that are not well-captured by functional units University of Virginia CS 655

  8. D • Jcore – component language (Java subset, removed synchronization) • Cool – aspect language for expressing coordination of threads • Ridl – aspect language for expressing remote access strategies • Join Points – method invocations • Weaver just needs to put code at method entrances and exits • Can produce Java source code to compile normally University of Virginia CS 655

  9. Cool • Define coordinators that specify locking semantics: • selfexclusive (method executed by at most one thread at a time) • mutexclusive (methods in same set cannot be executed concurrently) • Guarded suspension – define monitor-like abstractions separate from implementations • Can access, but not modify instance variables University of Virginia CS 655

  10. Ties aspect to specific implementation! Cool Example coordinator BoundedStackCoord : BoundedStack { selfexclusive { pop, push }; mutexclusive { pop, push }; cond boolean full = false; cond boolean empty = true; push : requires !full; on_exit { empty = false; if (sp == MAX) full = true; } pop : requires !empty; on_exit { full = false; if (sp == 0) empty = true; } } } University of Virginia CS 655

  11. Ridl • Control remote method invocations • Gives programmer control over copying semantics in parameter passing (can elect to copy just parts of object graph) remote Printer { Static print (Document: copy *.int, *.String, documentRepository)); ... } Only copy int and String fields, and reference to documentRepository. University of Virginia CS 655

  12. AspectJ • crosscuts identify events • Can be associated with method calls, exception handlers • advice defines code associated with crosscuts University of Virginia CS 655

  13. Tangled Example: Java API package java.io; public class File implements java.io.Serializable { private String path; ... public boolean exists() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(path); } return exists0(); } public boolean canRead() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead(path); } return canRead0(); } Exact same code, repeated 8 times in java.io.File • Why not make it a procedure? • Performance (method call overhead) • Better error messages (?) University of Virginia CS 655

  14. Cross-cuts • crosscut name(context): event list crosscut fileReaders(java.io.File f): java.io.File & (boolean exists() | boolean canRead() | boolean canRead() | boolean isDirectory() | long lastModified() | long length() | String[] list() | String[] list(FilenameFilter filter)) • Wildcards crosscut nonStatics (): java.io.* & !static * (..); crosscut intMethods (): MyClass & public * (int); crosscut returnObject (): * & Object * (..); crosscut ioHandlers (): Account & * (..) & catch (IOException); University of Virginia CS 655

  15. Advice • advice (Parameters) : crosscut advice checkRead (java.io.File f): fileReaders (f) { before { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead (path); } } } University of Virginia CS 655

  16. AspectJ File Implementation • Aspects shown on previous slides • Simple implementation with security code removed package java.io; public class File implements java.io.Serializable { private String path; ... public boolean exists() { return exists0(); } public boolean canRead() { return canRead0(); } University of Virginia CS 655

  17. Is AspectJ version better? • Advantages • Compact program • Separate concerns without any performance cost • Easier to change and reuse • Easier to understand and analyze policy • Disadvantages • Have to learn a new language • Extra compilation step • Debugging may be difficult (but special-purpose tools) University of Virginia CS 655

  18. Example: Exception Handling • [Lippert & Lopes, 99] • Exception handling code clutters (and often dwarves) normal code • Tangled exceptions limit reuse • Cannot change exceptional behavior without overriding entire method • Tangled exceptions lose abstraction • All methods must handle network failures by retrying is scattered throughout code (and easy to forget) University of Virginia CS 655

  19. JWAM Experiment • Java framework • Designed around design-by-contract with explicit calls to Contract.require and Contract.ensure • Use AspectJ to abstract out crosscut for contracts and exception handling • 11% of original code dealt with exception detection and handling; many handlers do the same thing University of Virginia CS 655

  20. Bank Account public class Account { public Account (String owner, int accNo) { Contract.require (owner != null && owner.length() > 0); Contract.require (accNo > 0); this.owner = owner; this.accNo = accNo; } public void deposit (float amount) { Contract.require (amount > 0.0); balance += amount; } ... } University of Virginia CS 655

  21. Aspect-Oriented Implementation class AccountContract { static advice Account & new(String s, int n) { before { Contract.require (s != null && s.length () > 0); Contract.require (n > 0); } } static advice Account & deposit (float f) { before { Contract.require (f > 0.0); } } } University of Virginia CS 655

  22. Handling Library Exceptions • Typical code: try { registry.put (name, this); } catch (RemoteException e) { ErrorLog.print (“Remote call failed: ” + e); } • Replace with: crosscut remoteHandlers () : * & * *(..) & catch (RemoteException); static advice remoteHandlers () { catch (RemoteException e) { ErrorLog.print (“Remote call failed in ” + thisMethodName + “:” + e); } University of Virginia CS 655

  23. Results • Reduced exception detection and handling code by a factor of 4.5 • Removed many simple conditions (null tests of results and arguments in contracts), common exception handlers • Is resulting code likely to be more reliable and maintainable? University of Virginia CS 655

  24. Adaptive Programming: Demeter • Instance of AOP [Lieberherr92] • Aspects are traversal strategies • Separate the program text and the class structure • Program is independent of class graph • Accomplish tasks by traversals • Specification for what parts of received object should be traversed • Code fragments for what to execute when specific object types are encountered University of Virginia CS 655

  25. Law of Demeter • Law of Demeter: a method should talk only to its friends: • arguments and part objects (computed or stored) • newly created objects • Dilemma: • Small method problem of OO (if followed) • Unmaintainable code (if not followed) • Traversal strategies are the solution to this dilemma • Demeter = Greek Goddess of Agriculture (grow software from small blocks) University of Virginia CS 655

  26. Slide adapted from Karl Lieberherr talk AP Example: UML Class Diagram busStops BusRoute BusStopList buses 0..* BusStop BusList waiting 0..* passengers Bus PersonList Person 0..* AOP/Demeter

  27. Slide adapted from Karl Lieberherr talk Collaborating Classes Find all persons waiting at any bus stop on a bus route busStops BusRoute BusStopList OO solution: one method for each red class buses 0..* BusStop BusList waiting 0..* passengers Bus PersonList Person 0..* AOP/Demeter

  28. Java Solution (excerpt) class BusRoute { BusStopList busstops; void printWaitingPassengers () { busstops->printWaitingPassengers (); } } class BusStopList { BusStop stops[]; void printWaitingPassengers () { for (int i = 0; i < stops.length; i++) stops[i].printWaitingPassengers (); } } University of Virginia CS 655

  29. Java Solution (cont.) class BusStop { PersonList waiting; void printWaitingPassengers () { waiting.print (); } } class PersonList { Person people[]; void print () { for (int i = 0; i < people.length; i++) people[i].print (); } } class Person { String name; void print () { System.stdout.println (name); } } University of Virginia CS 655

  30. Demeter Approach • Devise a traversal strategy • Specify code for different types of objects reached on a traversal • Example: code prints name if object is a Person • Independent of class graph University of Virginia CS 655

  31. Slide adapted from Karl Lieberherr talk Traversal Strategy First try:from BusRoute to Person busStops BusRoute BusStopList BusRoute BusStopList buses 0..* BusStop BusStop BusList BusList waiting 0..* passengers Bus PersonList Bus PersonList Person Person 0..* AOP/Demeter

  32. Slide adapted from Karl Lieberherr talk Traversal Strategy from BusRoute through BusStop to Person busStops BusRoute BusStopList buses 0..* BusStop BusList waiting 0..* passengers Bus PersonList Person 0..* AOP/Demeter

  33. Slide adapted from Karl Lieberherr talk Writing Adaptive Programs with Strategies strategy: from BusRoute through BusStop to Person BusRoute { traversalwaitingPersons(PersonVisitor) { through BusStop to Person; } // from is implicit void printWaitingPersons() // traversal/visitor weaving instr. = waitingPersons(PrintPersonVisitor); PrintPersonVisitor { before Person () < do printing >} AOP/Demeter

  34. Slide adapted from Karl Lieberherr talk Robustness of Strategy from BusRoute bypassing Bus to Person villages BusRoute BusStopList buses VillageList busStops 0..* 0..* BusStop BusList Village waiting 0..* passengers Bus PersonList Person 0..* AOP/Demeter

  35. Slide adapted from Karl Lieberherr talk Filter out noise in class diagram • only three out of seven classes • are mentioned in traversal • strategy! from BusRoute through BusStop to Person replaces traversal methods for the classes BusRoute VillageList Village BusStopList BusStop PersonList Person AOP/Demeter

  36. Summary • Aspect-Oriented Programming and Adaptive Programming provide programmers with new expressive options • Active research area (Separation of Concerns Workshops at OOPSLA, ICSE, ECOOP, etc.) • Many directions to explore • Practical use still remains to be seen • Kiczales paper claims like OO in 1980 (by induction) • But some commercial success • Tendril Software (Adaptive programming tools for Java), bought by BEA Systems. http://www.webgain.com/Products/Structure_Builder/ University of Virginia CS 655

  37. Charge • Next time: John Thornley • Project Progress • If your implementation will not be complete by Monday morning, schedule a meeting with me now University of Virginia CS 655

More Related