Aspect-Oriented Programming w/AspectJ™ Cristina Lopes, Gregor Kiczales Xerox PARC © Copyright 1998, Xerox Corporation. All Rights Reserved. www.parc.xerox.com/aop.

Slides:



Advertisements
Similar presentations
Aspect Oriented Programming. AOP Contents 1 Overview 2 Terminology 3 The Problem 4 The Solution 4 Join point models 5 Implementation 6 Terminology Review.
Advertisements

1 JAC : Aspect Oriented Programming in Java An article review by Yuval Nir and Limor Lahiani.
©Ian Sommerville 2006Software Engineering, 8th edition. Chapter 32 Slide 1 Aspect-oriented Software Development.
Observer Method 1. References Gamma Erich, Helm Richard, “Design Patterns: Elements of Reusable Object- Oriented Software” 2.
Inheritance. Extending Classes It’s possible to create a class by using another as a starting point  i.e. Start with the original class then add methods,
Inheritance and Class Hierarchies Chapter 3. Chapter 3: Inheritance and Class Hierarchies2 Chapter Objectives To understand inheritance and how it facilitates.
Chapter 3 Data Abstraction: The Walls. © 2005 Pearson Addison-Wesley. All rights reserved3-2 Abstract Data Types Modularity –Keeps the complexity of a.
OOP in Java Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
University of British Columbia Software Practices Lab CAS Seminar 06 Fluid AJ - A Simple Fluid AOP Tool Terry Hon Gregor Kiczales.
© 2006 Pearson Addison-Wesley. All rights reserved4-1 Chapter 4 Data Abstraction: The Walls.
© 2006 Pearson Addison-Wesley. All rights reserved4-1 Chapter 4 Data Abstraction: The Walls.
About the Presentations The presentations cover the objectives found in the opening of each chapter. All chapter objectives are listed in the beginning.
Guide To UNIX Using Linux Third Edition
Chapter 10 Classes Continued
COMP 14: Intro. to Intro. to Programming May 23, 2000 Nick Vallidis.
1 An introduction to design patterns Based on material produced by John Vlissides and Douglas C. Schmidt.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Java Software Solutions Foundations of Program Design Sixth Edition by Lewis.
Introduction to Aspect- Oriented Programming CS 3360 Gregor Kiczales, et. al. Getting started with AspectJ, CACM, 44(10):59-65, October Fall 2012.
Object Oriented Software Development
A First Program Using C#
Abstract classes and Interfaces. Abstract classes.
Programming Languages and Paradigms Object-Oriented Programming.
Design Patterns.
MIT AITI 2002 Abstract Classes, Interfaces. Abstract Classes What is an abstract class? An abstract class is a class in which one or more methods is declared,
Lecture 2 COM 3362, April 5, Composition example Use three aspects simultaneously with three classes. Three aspects: –ShowReadWriteAccess –InstanceLogging.
220 FINAL TEST REVIEW SESSION Omar Abdelwahab. INHERITANCE AND POLYMORPHISM Suppose you have a class FunClass with public methods show, tell, and smile.
Chapter 3 Introduction to Collections – Stacks Modified
Java: Chapter 1 Computer Systems Computer Programming II.
Design patterns. What is a design pattern? Christopher Alexander: «The pattern describes a problem which again and again occurs in the work, as well as.
Recap (önemli noktaları yinelemek) from last week Paradigm Kay’s Description Intro to Objects Messages / Interconnections Information Hiding Classes Inheritance.
1 Java Inheritance. 2 Inheritance On the surface, inheritance is a code re-use issue. –we can extend code that is already written in a manageable manner.
Polymorphism, Inheritance Pt. 1 COMP 401, Fall 2014 Lecture 7 9/9/2014.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
1 CSC 221: Computer Programming I Spring 2010 interaction & design  modular design: roulette game  constants, static fields  % operator, string equals.
The Java Programming Language
Chapter 7 Objects and Classes 1 Fall 2012 CS2302: Programming Principles.
CSE 219 Computer Science III Program Design Principles.
Aspect Oriented Programming Gülşah KARADUMAN.
ECE450 - Software Engineering II1 ECE450 – Software Engineering II Today: Design Patterns IX Interpreter, Mediator, Template Method recap.
AOSD1 Aspect-Oriented Software Design Karl Lieberherr Theo Skotiniotis.
AOP-1 Aspect Oriented Programming. AOP-2 Aspects of AOP and Related Tools Limitation of OO Separation of Concerns Aspect Oriented programming AspectJ.
1 5/30/98LCR ‘98 BBN Technologies QoS Aspect Languages and their Runtime Integration Joseph P. Loyall, David E. Bakken, Richard E. Schantz, John A. Zinky,
Aspect-Oriented Programming and Modular Reasoning G. KiczalesM. Mezini Presented by Alex Berendeyev.
Topic 1 Object Oriented Programming. 1-2 Objectives To review the concepts and terminology of object-oriented programming To discuss some features of.
Object Oriented Software Development
Software Engineering Laboratory, Department of Computer Science, Graduate School of Information Science and Technology, Osaka University IWPSE 2003 Program.
Programming with Java © 2002 The McGraw-Hill Companies, Inc. All rights reserved. 1 McGraw-Hill/Irwin Chapter 5 Creating Classes.
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
Introduction to OOP CPS235: Introduction.
aspectj tools new and noteworthy Mik Kersten University of British Columbia Adrian Colyer IBM Hursley OOPSLA, October
Inheritance and Class Hierarchies Chapter 3. Chapter 3: Inheritance and Class Hierarchies2 Chapter Objectives To understand inheritance and how it facilitates.
Inheritance and Class Hierarchies Chapter 3. Chapter Objectives  To understand inheritance and how it facilitates code reuse  To understand how Java.
Classes, Interfaces and Packages
Quick Review of OOP Constructs Classes:  Data types for structured data and behavior  fields and methods Objects:  Variables whose data type is a class.
Introduction to Aspect- Oriented Programming CS 3360 Gregor Kiczales, et. al. Getting started with AspectJ, CACM, 44(10):59-65, October Spring 2012.
Session 7 Introduction to Inheritance. Accumulator Example a simple calculator app classes needed: –AdderApp - contains main –AddingFrame - GUI –CloseableFrame.
Copyright 1997, 1998 Xerox Corporation - Dijkstra, A discipline of programming, 1976 last chapter, In retrospect “To my taste the main characteristic of.
Exceptions Lecture 11 COMP 401, Fall /25/2014.
Author: DoanNX Time: 45’.  OOP concepts  OOP in Java.
 Description of Inheritance  Base Class Object  Subclass, Subtype, and Substitutability  Forms of Inheritance  Modifiers and Inheritance  The Benefits.
CSCE 240 – Intro to Software Engineering Lecture 3.
Visit for more Learning Resources
Software Engineering Fall 2005
Inheritance "Question: What is the object oriented way of getting rich? Answer: Inheritance.“ “Inheritance is new code that reuses old code. Polymorphism.
Lecture 21: Crosscutting Aspect-Oriented Programming
Week 6 Object-Oriented Programming (2): Polymorphism
Objects First with Java A Practical Introduction using BlueJ
Fundaments of Game Design
Presentation transcript:

Aspect-Oriented Programming w/AspectJ™ Cristina Lopes, Gregor Kiczales Xerox PARC © Copyright 1998, Xerox Corporation. All Rights Reserved.

2 using AOP and AspectJ to: –improve the design and source code modularity of systems that involve cross-cutting concerns aspects are: –a new kind of programming construct, that supports a new kind of module enables concerns that cross-cut the system to be captured in clean units AspectJ is: –is an aspect-oriented extension to Java™ that supports general-purpose aspect programming this tutorial is about...

3 an example system a distributed digital library

4 clean modular design title: string author: string isbn: int pdf: pdf tiff: tiff Library Book holds ** cooperates * * User accesses * * Printer uses **

5 public class PrinterImpl { String status = “Idle” Vector jobs; public PrinterImpl() {} pubilc get_status() { return status } public add_job(int j) { jobs.add(j); } Book Printer UserLibrary 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; } class User { private String name; Library theLibrary; Printer thePrinter; public User(String n) { name = n; } public boolean getBook (String title) { Book aBook = theLibrary.getBook(this, title); thePrinter.print(this,aBook); return true; } 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; } } clean modular code

6 benefits of good modularity aka “clean separation of concerns” each decision in a single place –easy to understand –easy to modify –easy to unplug

7 but... some issues don’t localize to objects –global coordination –interactions among many objects –resource sharing –error handling –performance optimizations –synchronization –...

8 Book Printer UserLibrary 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 Stringtitle; private Stringauthor; private Stringisbn; 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 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; } 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; } digital library with optimization

9 Book Printer UserLibrary 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 Stringtitle; private Stringauthor; private Stringisbn; 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 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; } 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; } “cross-cutting” this optimization cross-cuts the primary structure of the program

10 effects of cross-cutting “tangled code” code duplication, difficult to reason about –why is this here? –what does this connect to? –difficult to make changes essentially, it destroys modularity

11 the AOP idea many cross-cuts aren’t random! –they serve specific purposes: performance optimizations, interactions among objects, enforcing consistency, tracking global state… –they have well-defined structure: lines of dataflow, boundary crossings, points of resource utilization, points of access… so… let’s capture the cross-cutting structure in a modular way...

12 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 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; } 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; } 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 Stringtitle; private Stringauthor; private Stringisbn; public BookID(String t, String a, String i) { title = t; author = a; isbn = i; } public String get_title() {return title;} } public class PrinterImpl { String status = “Idle” Vector jobs; public PrinterImpl() {} pubilc get_status() { return status } public add_job(int j) { jobs.add(j); } 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; } class User { private String name; Library theLibrary; Printer thePrinter; public User(String n) { name = n; } public boolean getBook (String title) { Book aBook = theLibrary.getBook(this, title); thePrinter.print(this,aBook); return true; } 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; } } portal Printer { void print(Book book) { book: Book: {direct pages;} } portal Library { Book find (String title){ return: Book: {copy title, author, isbn;} } this aspect localizes the cross-cutting in one place aspects: a cross-cutting module

13 aspect-oriented programming “aspects” are program constructs that cross-cut classes 1 in well- defined, principled ways – the programmer uses classes to implement the primary module structure – the programmer uses aspects to implement the cross-cutting module structure 1 or other appropriate primary program construct, i.e. procedures if you added AOP to Scheme

14 aspect weaving weaver combines classes and aspects –compiler / pre-processor / interpreter –unambiguously coordinates cross-cutting aspect weaver public class PrinterImpl { String status = “Idle” Vector jobs; public PrinterImpl() {} pubilc get_status() { return status } public add_job(int j) { jobs.add(j); } 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; } 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 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; } } portal Printer { void print(Book book) { book: Book: {direct pages;} } portal Library { Book find (String title){ return: Book: {copy title, author, isbn;} } classes aspects executable code

15 benefits of using AOP good modularity, even in the presence of cross-cutting concerns –less tangled code, more natural code, smaller code –easier maintenance and evolution easier to reason about, debug, change –more reusable plug and play

16 AspectJ™ is… the first general-purpose AO language –“lexical” cross-cutting (current) –concern-specific libraries (current) –other kinds of cross-cutting (future) an extension to Java freely available implementation –user community will drive future design

17 looking ahead AOP works because cross-cutting modularities aren’t random aspects are used to capture the structure of the cross-cutting in clean ways AspectJ mechanisms Part II: the kinds of cross-cutting mechanisms AspectJ can capture problem structure Part IV: how to use AspectJ to capture the higher-level cross-cutting in your systems

18 outline I AOP overview –motivation, what is the AOP idea II AspectJ overview –basic concepts, kinds of cross-cutting III key technical details –running the aspect weaver, source files, emacs support IV using AspectJ –more realistic examples, kinds of aspects, elaboration of language semantics V style issues –when to use aspects, aspect coding style issues VI related work –survey of other activities in the AOP world

Part II Basic Concepts of AspectJ

20 goals of this chapter present the basic concepts of AspectJ –the different kinds of cross-cutting –when aspect code runs –what context aspect code runs in using a single simple example the next chapters elaborate on –environment, tools –details of the semantics –what can be written using AspectJ

21 overview class instances code (methods) and some state state whereas the underlying Java™ language supports classes and objects

22 overview class aspect AspectJ extends this with aspects that cross-cut the code in classes in various ways…

23 overview class aspect AspectJ extends this with aspects that cross-cut the code in classes in various ways…

24 overview class aspect AspectJ extends this with aspects that cross-cut the code in classes in various ways…

25 overview class aspect and aspect instances that cross-cut the state in objects in various ways

26 a first example class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } void setX (int x) { _x = x; } void setY (int y) { _y = y; } int getX() { return _x; } int getY() { return _y; } } aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); }

27 what it does Point p1 = new Point(); Point p2 = new Point(); p1 p2 The screen p1.set(3, 3); W W p2.setX(3);

28 aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); } Point ShowAccesses one aspect, one class this “advise weave” affects several methods in the class static: no aspect instances involved before: do this before method body

29 aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); } presentation note! the syntax shown here is slightly simplified, mostly to save room on the slides the full syntax for advise weaves on methods is presented in part iv (also look at the SpaceWar code)

30 class Point { int _x = 0; int _y = 0; void set (int x, int y) { System.out.println(“W”); _x = x; _y = y; } void setX (int x) { System.out.println(“W”); _x = x; } void setY (int y) { System.out.println(“W”); _y = y; }. here’s what we would have had to write in plain Java without AspectJ what was in one place is instead in 3 what was separated is now mixed in

31 Point p1 = new Point(); Point p2 = new Point(); p1 p2 The screen p1.set(3, 3); W W p2.setX(3); R int x = p1.getX(); extend to writes and reads...

32 one aspect with two weaves aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); } Point just as a class can have n methods an aspect can have n weaves ShowAccesses aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); } static before Point.getX, Point.getY,{ System.out.println(“R”); }

33 one aspect, two classes aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); } Point ShowAccesses aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); } static before Line.set, Line.setX1,... { System.out.println(“W”); } Line

34 one aspect, two classes aspect ShowAccesses { static before Point.set, Point.setX, Point.setY { System.out.println(“W”); } Point ShowAccesses Line aspect ShowAccesses { static before Point.set, Point.setX, Point.setY, Line.set, Line.setX1,... { System.out.println(“W”); } aspect ShowAccesses { static before Point.set, Point.setX, Point.setY, Line.set, Line.setX1,... { System.out.println(“W”); } static before Point.getX, Point.getY, Line.getX1,... { System.out.println(“R”); }

35 reads, writes and constructors aspect ShowAccesses { static before Point.set, Point.setX, Point.setY Line.set, Line.setX1,... { System.out.println(“W”); } static before Point.getX, Point.getY, Line.getX1,... { System.out.println(“R”); } static before Point(*), Line(*) { System.out.println(“C”); } methods constructors

36 summary so far ShowAccesses Point one aspect, one class ShowAccesses Point one aspect, two classes Line static advise weaves allow aspect to: extend existing class definitions independent of any aspect instances by modifying existing methods/constructors nxm cross-cutting is coming up

37 aspects are special classes class Point { … } class Line { … } class Circle { … } aspect LogNewInstances { static DataOutputStream log = null; static { // initializer try { log = new DataOutputStream( new FileOutputStream(“log”)); } catch (IOException e) {} } static after Point(*), Line(*), Circle(*) { long time = System.currentTimeMillis(); try { log.writeBytes(“New instance at ” + time + “ ” + thisObject.toString() + “\n”); } catch (IOException e) {} } LogNewInstances Point Line Circle the objectaspect var

38 what it does Point p1 = new Point(); p1 New instance at Point321 p2 New instance at Point322 Point p2 = new Point(); l1 New instance at Line611 Line l1 = new Line(); l2 New instance at Line612 Line l2 = new Line(); l3 New instance at Line613 Line l3 = new Line(); c1 New instance at Circle901 Circle c1 = new Circle();

39 per-object aspect-related state make Points go back to 0,0 after every 100 sets Point AutoReset aspect AutoReset { static new int Point.count = 0; static after Point.set, Point.setX, Point.setY { if ( ++count >= 100 ) { count = 0; _x = 0; _y = 0; } “new weaves” add definitions new fields, methods and constructors must be static object’s scope available

40 a peek ahead to style issues make Points go back to 0,0 after every 100 sets Point AutoReset aspect AutoReset { static new int Point.count = 0; static after Point.set, Point.setX, Point.setY { if ( ++count >= 100 ) { count = -1; set(0, 0); } “new weaves” add definitions new fields, methods and constructors must be static what is the class / aspect inferace?

41 how this runs count=0 Point p1 = new Point(); p1 count=0 Point p2 = new Point(); p2 p2.setY(7); count=1 p1.set(3, 3); count=1 p1.setX(3); count=2

42 summary so far ShowAccesses Point n aspects, m classes Line Point AutoReset adding state to each object advise weaves allow aspect to modify existing class definitions new weaves allow aspect to add to existing class definitions static means independent of any aspect instances n x m cross-cutting

43 aspect instances Point AutoReset aspect can be instantiated and aspect instances can then be associated with objects as a first step, move the counter from objects to aspect instances

44 simple use of aspect instances aspect AutoReset { int count = 0; after Point.set, Point.setX, Point.setY { if (++count >= 100) { count = -1; set(0, 0); } non-static not a weave

45 what it does Point p1 = new Point(); p1 Point p2 = new Point(); p2 AutoReset a1 = new AutoReset(); count=0 a1.addObject(p1); count=0 AutoReset a2 = new AutoReset(); a2.addObject(p2); p1.set(3, 3); count=1 p1.setX(3); count=2 p2.setY(7); count=1 after instantiation of every Point object, instantiate an AutoReset aspect and associate the two

46 one aspect instance, many objects Point p1 = new Point(1, 1); p1 Point p2 = new Point(1, 1); p2 Point p3 = new Point(1, 1); p3 a1.addObject(p1); a1.addObject(p3); a1.addObject(p2); the goal here is to get all of the Points to share a single AutoReset counter, so that they all reset, when as a group they have been set 100 times AutoReset a1 = new AutoReset();

47 one aspect instance, many objects aspect AutoReset { int count = 0; after Point.set, Point.setX, Point.setY { if (++count >= 100) { Vector objects = thisAspect.getObjects(); Enumeration e = objects.elements(); while (e.hasMoreElements()) { Point p = (Point)e.nextElement(); count = -1; p.set(0, 0); } aspect.getObjects() returns a vector of the objects object.getAspects() returns a vector of the aspects

48 aspects compose Line ShowAccesses Point Circle LogNewInstancesAutoReset all three aspects apply to the class Point –more on controlling this in next part code retains good separation of concerns

49 here’s the complete code written with AspectJ with AspectJ class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } void setX (int x) { _x = x; } void setY (int y) { _y = y; } int getX() { return _x; } int getY() { return _y; } } aspect ShowAccesses { static before Point.set, Point.setX, Point.setY Line.set, Line.setX1,... { System.out.println(“W”); } static before Point.getX, Point.getY, Line.getX1,... { System.out.println(“R”); } static before Point(*), Line(*) { System.out.println(“C”); } aspect LogNewInstances { static DataOutputStream log = null; static { // initializer try { log = new DataOutputStream( new FileOutputStream(“log”)); } catch (IOException e) {} } static after Point(*), Line(*), Circle(*) { long time = System.currentTimeMillis(); try { log.writeBytes(“New instance at ” + time + “ ” + this.toString() + “\n”); } catch (IOException e) {} } aspect AutoReset { int counter = 0; after Point.set, Point.setX, Point.setY { if (++counter >= 100) { count = -1; set(0, 0); }

50 class Point { int _x = 0; int _y = 0; Point () { System.out.println("C"); long time = System.currentTimeMillis(); try { log.writeBytes("New instance at " + time + " " + Point.this.toString() + "\n"); } catch (IOException e) { } } void set(int x, int y) { System.out.println("W"); _x = x; _y = y; doAutoResets(); } void setX(int x) { System.out.println("W"); _x = x; doAutoResets(); } void setY(int y) { System.out.println("W"); _y = y; doAutoResets(); } int getX() { System.out.println("R"); return _x; } int getY() { System.out.println("R"); return _y; } here’s a well-written version of what we would have had to write in plain Java without AspectJ Vector autoResets = new Vector(); void doAutoResets() { java.util.Enumeration enumeration = autoResets.elements(); AutoReset reset; while (enumeration.hasMoreElements()) { reset = (AutoReset)enumeration.nextElement(); if(++ reset.count >= 100){ System.out.println("Reseting " + this + "."); reset.count = - 1; set(0,0); } static DataOutputStream log = null; static { try { log = new DataOutputStream(new FileOutputStream("log")); } catch (IOException e) { } class AutoReset { int count = 0; public void addToScope(Point object) { object.autoResets.addElement(this); } public void removeFromScope(Point object) { object.autoResets.removeElement(this); }

51 benefits of using AOP good modularity, even in the presence of cross-cutting concerns –less tangled code, more natural code, smaller code –easier maintenance and evolution easier to reason about, debug, change –more reusable plug and play

52 summary advise weaves, new weaves different kinds of cross-cutting static and non-static weave code runs in mixed scope Line ShowAccesses PointCircle LogNewInstances AutoReset

53 looking ahead AOP works because cross-cutting modularities aren’t random aspects are used to capture the structure of the cross-cutting in clean ways AspectJ mechanisms Part II: the low-level kinds of cross- cutting AspectJ can capture problem structure Part III: how to use AspectJ to capture the higher-level kinds of cross-cutting in your systems

Part III Using AspectJ, the tool

55 source files Point ShowAccess “.ajava” files contain: regular Java source code aspect source code

56 processing aspects Point ShowAccess aspect weaver.ajava files byte code.class files

57 intermediate files Point ShowAccess aspect weaver.ajava files byte code.class files.java files Java code pre-processor: simplicity transition strategy

58 programming environment source files –extension –contents look&feel of ajava mode for emacs –what aspects apply where weaving woven code and tracking errors

59 demo of the AspectJ tools

Part IV - Using Aspects AspectJ mechanisms Part II: the kinds of cross-cutting mechanisms AspectJ can capture problem structure Part IV: how to use AspectJ to capture the higher-level cross-cutting in your systems

61 purpose and structure styles of aspects presented with examples: –common implementations –interaction (protocols) –shared state –specialized aspect libraries interleaved with more detail about AspectJ

62 notation Class object AspectInterface aspect instance slide containing semantic rules or conventions piece of implementation

63 terminology aspect ShowAccesses { static before Point.set, Point.setX, Point.setY Line.set, Line.setX1,... { System.out.println(“W”); } designators weave mode weave declaration (“weave”, for short) this syntax is slightly simplified, mostly to save room on the slides see next slide for the full syntax for designators

64 designators methods: ResultType Type.Id ( Formals ) constructors: Type ( Formals ) initializers: Type fields: Type.Id examples: void Point.set(int x, int y) * Point.set(*) shapes.util.Point(*) Point(int x, int y) shapes.Point.x methods field constructors ResultType: Type | * Formals: TrueFormals | *

65 outline using aspects to localize : –common implementations –interaction (protocols) –shared state specialized aspect libraries

66 example: plug & play tracing want to print out a trace message before and after every method of these classes; want to be able to turn it off class Customer { … } class Order { … } class Product { … }

67 with an aspect Customer Order Product aspect Trace { static before * Customer.*(*), * Order.*(*), * Product.*(*) { System.out.println(“ENTERING ” + thisMethodID); } static after * Customer.*(*), * Order.*(*), * Product.*(*) { System.out.println(“EXITING ” + thisMethodID); }

68 plug and play (plug and debug) plug in: plug out: –turn debugging on/off without editing classes –debugging disabled with no runtime cost –can save debugging code between uses ajweaver Customer.ajava Order.ajava Product.ajava Trace.ajava ajweaver Customer.ajava Order.ajava Product.ajava

69 special vars, scope rules specials: –thisAspect –thisObject –thisClassName –thisMethodName scope rules in body of weaves: 1. formals 2. aspect 3. object strings

70 an exception aspect XeroxServer Status getStatus() void registerClient(Client c) in all implementations of this interface, want to log exceptions

71 aspect XeroxServerCatcher { static catch XeroxServer.getStatus, XeroxServer.registerClient (Exception e) { System.err.println(“Exception ” + e + “ at ” + System.currentTimeMillis()); throw e; } an exception aspect type name aspect XeroxServerCatcher { static catch XeroxServer.getStatus, XeroxServer.registerClient (Exception e) { System.err.println(“Exception ” + e + “ at ” + System.currentTimeMillis()); throw e; }

72 types in Java: –Interface = Type (no implementation) –Class = Type + implementation designators refer to types –aspects apply to interfaces too! weaves apply to all implementations of the designated types

73 aspects for interfaces XeroxServerXeroxServerCatcher Class1Class2Class3... implements XeroxServerCatcher affects Class1, Class2, Class3,...

74 aspects that localize common code A B C A B C Aspect used in set-ups/clean-ups tracing logging method guards...

75 aspects that localize common code there is an abstraction occurring in several classes this abstraction can be implemented by a common piece of code inheritance is not best model or gets in the way of other code reuse aspect contains the common piece of code

76 outline using aspects to localize : –common implementations –interaction (protocols) aspects as repositories of related implementations design patterns –shared state specialized aspect libraries

77 example: tic-tac-toe Player public: run() getTurn() endGame(Player, Result) actionPerformed(ActionEvent) mouseClicked(MouseEvent) protected: addStatusDisplay() TicTacToe public: run() startGame() newPlayer(Player) putMark(Player, Position) getBoard() getNPlayers() getCurrentPlayer() isOver() getResult() attach(TTTObserver) detach(TTTObserver) protected: waitForPlayers() waitForMove() endGame() notify() on state changes TTTObserver public: actionPerformed(ActionEvent) aboutWindow() update() protected: addMenu() addBoardDisplay() addStatusDisplay() finish() 2 TicTacToe public: run() startGame() newPlayer(Player) putMark(Player, Position) getBoard() getNPlayers() getCurrentPlayer() isOver() getResult() attach(TTTObserver) detach(TTTObserver) protected: waitForPlayers() waitForMove() endGame() notify() on state changes TTTObserver public: actionPerformed(ActionEvent) aboutWindow() update() protected: addMenu() addBoardDisplay() addStatusDisplay() finish() plus other classes...

78 view of the update protocol Player TicTacToe public:... attach(TTTObserver) detach(TTTObserver) protected: notify() on state changes TTTObserver public: update() Canvas Label BoardDisplay update() StatusDisplay update() 6 tightly related methods and calls to notify() are spread all over

79 the protocol in an aspect TicTacToe StatusDisplay TTTObserver BoardDisplay aspect TTTDisplayProtocol { static new Vector TicTacToe.observers = new Vector(); static new Tictactoe TTTObserver.game; static new void TicTacToe.attach(TTTObserver obs) { observers.addElement(obs); } static new void TicTacToe.detach(TTTObserver obs) { observers.removeElement(obs); } static new void TTTObserver.update() { board.update(game); status.update(game); } static new void BoardDisplay.update(TicTacToe game), StatusDisplay.update(TicTacToe game) { theGame = game; repaint(); } // all methods that change state static after TicTacToe.startGame, TicTacToe.newPlayer, TicTacToe.putMark, TicTacToe.endGame { for (int i = 0; i < observers.size(); i++) ((Observer)observers.elementAt(i)).update(); } aspect TTTDisplayProtocol { static new Vector TicTacToe.observers = new Vector(); static new Tictactoe TTTObserver.game; static new void TicTacToe.attach(TTTObserver obs) { observers.addElement(obs); } static new void TicTacToe.detach(TTTObserver obs) { observers.removeElement(obs); } static new void TTTObserver.update() { board.update(game); status.update(game); } static new void BoardDisplay.update(TicTacToe game), StatusDisplay.update(TicTacToe game) { theGame = game; repaint(); } // all methods that change state static after TicTacToe.startGame, TicTacToe.newPlayer, TicTacToe.putMark, TicTacToe.endGame { for (int i = 0; i < observers.size(); i++) ((Observer)observers.elementAt(i)).update(); } aspect TTTDisplayProtocol { static new Vector TicTacToe.observers = new Vector(); static new Tictactoe TTTObserver.game; static new void TicTacToe.attach(TTTObserver obs) { observers.addElement(obs); } static new void TicTacToe.detach(TTTObserver obs) { observers.removeElement(obs); } static new void TTTObserver.update() { board.update(game); status.update(game); } static new void BoardDisplay.update(TicTacToe game), StatusDisplay.update(TicTacToe game) { theGame = game; repaint(); } // all methods that change state static after TicTacToe.startGame, TicTacToe.newPlayer, TicTacToe.putMark, TicTacToe.endGame { for (int i = 0; i < observers.size(); i++) ((Observer)observers.elementAt(i)).update(); } aspect TTTDisplayProtocol { static new Vector TicTacToe.observers = new Vector(); static new Tictactoe TTTObserver.game; static new void TicTacToe.attach(TTTObserver obs) { observers.addElement(obs); } static new void TicTacToe.detach(TTTObserver obs) { observers.removeElement(obs); } static new void TTTObserver.update() { board.update(game); status.update(game); } static new void BoardDisplay.update(TicTacToe game), StatusDisplay.update(TicTacToe game) { theGame = game; repaint(); } // all methods that change state static after TicTacToe.startGame, TicTacToe.newPlayer, TicTacToe.putMark, TicTacToe.endGame { for (int i = 0; i < observers.size(); i++) ((Observer)observers.elementAt(i)).update(); } aspect TTTDisplayProtocol { static new Vector TicTacToe.observers = new Vector(); static new Tictactoe TTTObserver.game; static new void TicTacToe.attach(TTTObserver obs) { observers.addElement(obs); } static new void TicTacToe.detach(TTTObserver obs) { observers.removeElement(obs); } static new void TTTObserver.update() { board.update(game); status.update(game); } static new void BoardDisplay.update(TicTacToe game), StatusDisplay.update(TicTacToe game) { theGame = game; repaint(); } // all methods that change state static after TicTacToe.startGame, TicTacToe.newPlayer, TicTacToe.putMark, TicTacToe.endGame { for (int i = 0; i < observers.size(); i++) ((Observer)observers.elementAt(i)).update(); } aspect contains fields, methods and procedures of protocol

80 observer pattern Subject attach(Observer) detach(Observer) notify() on state changes Observer update() ConcreteObserver update() ConcreteSubject protocol is spread in many classes not so good in Java - uses up only inheritance link With inheritance observers.addElement(obs);observers.removeElement(obs);

81 observer pattern Observer update() ConcreteObserver update() implements Subject attach(Observer) detach(Observer) implements ConcreteSubject attach(Observer) detach(Observer) notify() on state changes protocol is spread in many classes some replication of code in the concrete subjects with interfaces observers.addElement(obs);observers.removeElement(obs);

82 observer pattern with aspects ConcreteObserver implements ConcreteSubject protocol implementation is encapsulated in the aspects Subject attach(Observer) detach(Observer) Observer update() SubjectObserver static new Observer.subject static new Subject.observers static new Subject.attach(Observer) static new Subject.detach(Observer) observers.addElement(obs); observers.removeElement(obs); ConcreteObserverUpdates static new ConcreteObserver.update() static after ConcreteSubject.m1, ConcreteSubject.m2,... for (int i = 0; i < observers.size(); i++) { obs = observers.elementAt(i); obs.update(); }

83 aspects that localize interaction A B C A B C Aspect used in multi-class protocols – GUIs – notification –... many design patterns

84 aspects that localize interaction there is an interaction (protocol) involving several classes methods of the protocol are more coupled with each other than with the classes where they “sit” aspect captures the whole protocol

85 outline using aspects to localize : –common implementations –interaction (protocols) –shared state static vs non-static state when to use aspect instances specialized aspect libraries

86 static vs. non-static aspect Count1 { static int count = 0; static before Point.set, Point.setX, Point.setY { count++; } aspect Count2 { int count = 0; before Point.set, Point.setX, Point.setY { thisAspect.count++; } class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } void setX (int x) { _x = x; } void setY (int y) { _y = y; } int getX() { return _x; } int getY() { return _y; } }

87 static vs. non-static fields aspect Count1 { static int count = 0; static before Point.set, Point.setX, Point.setY { count++; } one incarnation of count ( same as static in class fields ) one incarnation of count per aspect instance ( same as non-static in class fields ) Point p0 = new Point(0,0); Point p1 = new Point(1,1); aspect Count2 { int count = 0; before Point.set, Point.setX, Point.setY { thisAspect.count++; } Point p0 = new Point(0,0); Point p1 = new Point(1,1);

88 static vs. non-static weaves two issues: 1. objects affected by weave 2. the existence of “thisAspect” related issue: the existence of “thisObject”

89 static vs. non-static weaves (1) aspect Count2 { int count = 0; before Point.set, Point.setX, Point.setY { thisAspect.count++; } Point p0 = new Point(0,0); Point p1 = new Point(1,1); p0.set(3,3); p1.set(4,4); aspect Count1 { static int count = 0; static before Point.set, Point.setX, Point.setY { count++; } Point p0 = new Point(0,0); Point p1 = new Point(1,1); p0.set(3,3); p1.set(4,4); static weave affects all Point objects, always Count2 count = new Count2(); count.addObject(p0); p0.set(3,3); non-static weave affects just the Point objects associated with an instance of Count2

90 static vs. non-static weaves (2) aspect Count1 { static int count = 0; static before Point.set, Point.setX, Point.setY { count++; } like a static method, this weave is executed without reference to a particular aspect instance may be omitted aspect Count2 { int count = 0; before Point.set, Point.setX, Point.setY { thisAspect.count++; } like a non-static method, this weave is executed with respect to particular aspect instance(s), thisAspect thisAspect available in non-static weaves

91 static vs. non-static (methods) aspect Count1 { static int count = 0; static before Point.set, Point.setX, Point.setY { count++; } class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } void setX (int x) { _x = x; } void setY (int y) { _y = y; } int getX() { return _x; } int getY() { return _y; } } non-static methods no particular aspect instance (no thisAspect ) but a particular Point object, thisObject thisObject available in static and non-static weaves of non-static methods

92 static vs. non-static (specials) static weave non-static weave static method non-static method available: thisObject thisAspect thisClassName thisMethdName available: thisObject thisClassName thisMethodName available: thisClassName thisMethodName

93 special methods for aspects –void addObject(Object o) –void removeObject(Object o) –Vector getObjects() for objects –Vector getAspects()

94 example: a shared log file want to log new instances of these classes in one log file Customer Order Product

95 static aspect state Customer Order Product aspect LogNewInstances { static DataOutputStream log = null; static { // initializer try { log = new DataOutputStream( new FileOutputStream(“log”)); } catch (IOException e) {} } static after Customer(*), Order(*), Product(*) { long time = System.currentTimeMillis(); try { log.writeBytes(“New instance at ” + time + “ ” + thisObject.toString() + “\n”); } catch (IOException e) {} } globally shared by Customer, Order, Product

96 example: monitoring DBServer PrinterServer WebServer DocumentServer ServiceMonitoring

97 example: monitoring public class DBServer { public Result query(Query q) { monitor.anEvent(new SEvent(this)); try { return processQuery(q); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally { monitor.anEvent(new OKEvent(this)); } } public Status getStatus() { monitor.anEvent(new IEvent(this)); return status; }... } public class PrinterServer { public void print(Path p) { monitor.anEvent(new SEvent(this)); try { printit(p); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} } public Status getStatus() { monitor.anEvent(new IEvent(this)); return status; }... } public class WebServer { public void post(Data d) { monitor.anEvent(new SEvent(this)); try { postit(d); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} } public Data get(Path p) { monitor.anEvent(new SEvent(this)); try { return getit(p); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} }... } public class DocumentServer { public Doc convert(Doc d,Format f) { monitor.anEvent(new SEvent(this)); try { return convertData(d, f); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} } public void newDocument(Doc d) { monitor.anEvent(new SEvent(this)); try { addDocument(d); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} }... }

98 example: monitoring public class DBServer { public Result query(Query q) { monitor.anEvent(new SEvent(this)); try { return processQuery(q); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally { monitor.anEvent(new OKEvent(this)); } } public Status getStatus() { monitor.anEvent(new IEvent(this)); return status; }... } public class PrinterServer { public void print(Path p) { monitor.anEvent(new SEvent(this)); try { printit(p); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} } public Status getStatus() { monitor.anEvent(new IEvent(this)); return status; }... } public class WebServer { public void post(Data d) { monitor.anEvent(new SEvent(this)); try { postit(d); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} } public Data get(Path p) { monitor.anEvent(new SEvent(this)); try { return getit(p); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} }... } public class DocumentServer { public Doc convert(Doc d,Format f) { monitor.anEvent(new SEvent(this)); try { return convertData(d, f); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} } public void newDocument(Doc d) { monitor.anEvent(new SEvent(this)); try { addDocument(d); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally {monitor.anEvent(new OKEvent(this));} }... } monitor.anEvent(new SEvent(this)); try { return processQuery(q); } catch (Exception e) { monitor.anEvent(new XEvent(this)); } finally { monitor.anEvent(new OKEvent(this)); }

99 aspect as monitor (static state) aspect ServiceMonitoring { static Vector serversInfo = new Vector(5); static int totalServiceRequests, totalExceptions, totalCompletions; static before DBServer.query, WebServer.post, WebServer.get, PrinterServer.print, DocumentServer.convert, DocumentServer.newDocument { anEvent(new SEvent(thisObject)); } more befores, afters, catches, finally static void anEvent(Event e) { update aspect state; sometimes sendCommand } static protected void sendCommand(Server srv, Command c) { srv.anOrder(c); }

100 one monitor for all servers (static state) DBServer PrinterServer WebServer DocumentServer ServiceMonitoring static state static weaves only one incarnation of the static variables weaves statically associated with classes (they affect all objects)

101 the need for aspect instances need different instances of aspect state –e.g. different monitors for different groups of servers need a handle for the aspect state –e.g. remote service monitor

102 service monitors aspect ServiceMonitoring { static Vector serversInfo = new Vector(5); static int totalServiceRequests, totalExceptions, totalCompletions; static before DBServer.query, WebServer.post, WebServer.get, PrinterServer.print, DocumentServer.convert, DocumentServer.newDocument { anEvent(new SEvent(thisObject)); } more befores, afters, catches, finally static void anEvent(Event e) { update aspect’s state; sometimes sendCommand } static protected void sendCommand(Server srv, Command c) { srv.anOrder(c); }

103 monitors for groups of servers ServiceMonitoring DBServer PrinterServer WebServer DocumentServer state non-static weaves aServiceMonitor.addObject(aServer)

104 inheritance of aspects class MyDocumentServer extends DocumentServer { protected boolean checkConsistency() {... } public Doc convert(Doc d, Format f) { Doc newDoc = super.convert(d, f); if (checkConsistency(newDoc)) return newDoc; else return null; } override extension

105 inheritance of aspects SuperClass SubClass Aspect extends overriding of methods in sub: aspect still applies and doesn’t repeat in calls to super SuperType applies to all implementations of designated types Aspect subclass implements SuperType

106 inheritance of aspects A foo() B foo() extends Aspect1 before A.foo {...} what code runs in (new A()).foo() ? Aspect1’s before, A.foo (new B()).foo() ? Aspect1’s before, Aspect2’s before, B.foo if B.foo calls super.foo() ? same as previous; Aspect1’s before does not repeat Aspect2 before B.foo {...}

107 the effective method { try { all befores all afters } all catches all finallys }

108 aspect as monitor (static state) aspect ServiceMonitoring { static Vector serversInfo = new Vector(5); static int totalServiceRequests, totalExceptions, totalCompletions; static before DBServer.query, WebServer.post, WebServer.get, PrinterServer.print, DocumentServer.convert, DocumentServer.newDocument { anEvent(new SEvent(thisObject)); } more befores, afters, catches, finally static void anEvent(Event e) { update aspect state; sometimes sendCommand } static protected void sendCommand(Server srv, Command c) { srv.anOrder(c); }

109 inheritance between aspects aspect VerboseMonitor extends ServiceMonitoring { ObjectOutputStream logStream; VerboseMonitor() { initialize logStream } protected void log(Event e) { logStream.writeObject(e); } public void anEvent(Event e) { System.out.println(e.toString()); log(e); super.anEvent(e); } override extension

110 inheritance between aspects SuperAspect SubAspect extends similar to inheritance between classes: –subaspect inherits methods, fields and weaves of superaspect –subaspect can extend superaspect with new methods, fields and weaves –subaspect can override methods and fields of superaspect (for now)

111 aspects that localize shared state A B C O A B C Aspect used in multi-class protocols with state – authentication – monitoring – object management –... encapsulation of state relating to groups of objects

112 aspects that localize shared state state needs to be encapsulated an object / a class would do, but interactions that affect the state of such object are well localized aspect contains that state and the weaves for interaction

113 outline using aspects to localize : –common implementations –interaction (protocols) –shared state specialized aspect libraries –cross-cutting abstractions –code-intensive, repetitive actions (goal of all libraries)

114 the cross-cutting nature of concurrency control Problem: a square and a circle are manipulated by several concurrent threads. They can both change color. However, they can’t both be red at the same time; a changeColor(red) request on one of them must wait if the other is currently red. Not OK OK

115 cross-cutting is unavoidable the cross-cutting nature of concurrency control class Square extends Shape { Pos pos; int size; Color color; fields for coordination public void changeColor(Color c){ some coordination code here color = c; some coordination code here } … } class Circle extends Shape { Pos pos; int r; Color color; fields for coordination public void changeColor(Color c){ some coordination code here color = c; some coordination code here } … } code may be more or less encapsulated, but

116 aspect NoSimultaneousRed { Shape redShape = null; // holds the reference to // the red shape or null before void Square.changeColor(Color color), void Circle.changeColor(Color color) { if (color == Color.red) { synchronized (thisAspect) { while (!(redShape == null || redShape == thisObject)) { try { wait(); } catch (InterruptedException e) {} } redShape = thisObject; } after void Square.changeColor(Color color), void Circle.changeColor(Color color) { if (color != Color.red) { synchronized (thisAspect) { if (thisObject == redShape) // coming out of red redShape = null; notifyAll(); } using an aspect aspect NoSimultaneousRed { Shape redShape = null; // holds the reference to // the red shape or null before void Square.changeColor(Color color), void Circle.changeColor(Color color) { if (color == Color.red) { synchronized (thisAspect) { while (!(redShape == null || redShape == thisObject)) { try { wait(); } catch (InterruptedException e) {} } redShape = thisObject; } after void Square.changeColor(Color color), void Circle.changeColor(Color color) { if (color != Color.red) { synchronized (thisAspect) { if (thisObject == redShape) // coming out of red redShape = null; notifyAll(); }

117 using an aspect aspect NoSimultaneousBlue { Shape blueShape = null; // holds the reference to // the blue shape or null before void Square.changeColor(Color color), void Circle.changeColor(Color color) { if (color == Color.blue) { synchronized (thisAspect) { while (!(blueShape == null || blueShape == thisObject)) { try { wait(); } catch (InterruptedException e) {} } blueShape = thisObject; } after void Square.changeColor(Color color), void Circle.changeColor(Color color) { if (color != Color.blue) { synchronized (thisAspect) { if (thisObject == blueShape) // coming out of blue blueShape = null; notifyAll(); } can pull out common code into a super

118 using coolib aspect NoSimultaneousRed extends Coordinator { Shape redShape = null; before void Square.changeColor(String color), void Circle.changeColor(String color) { if (color == Color.red) guardedEntry (thisMethodID, new Condition() { boolean checkit() { return (redShape == null || redShape == thisObject);}}, new CoordinationAction() { void doit() { redShape = thisObject; } }); } after void Square.changeColor(String color), void Circle.changeColor(String color) { if (color != Color.red) guardedExit (thisMethodID, new CoordinationAction() { void doit() {if (thisObject==redShape) redShape = null;}}); } aspect NoSimultaneousRed extends Coordinator { Shape redShape = null; before void Square.changeColor(String color), void Circle.changeColor(String color) { if (color == Color.red) guardedEntry (thisMethodID, new Condition() { boolean checkit() { return (redShape == null || redShape == thisObject);}}, new CoordinationAction() { void doit() { redShape = thisObject; } }); } after void Square.changeColor(String color), void Circle.changeColor(String color) { if (color != Color.red) guardedExit (thisMethodID, new CoordinationAction() { void doit() {if (thisObject==redShape) redShape = null;}}); }

119 coolib avoid writing ad-hoc coordination code in the classes: use coordination aspects provide high-level constructs for programming coordination

120 coolib mutual exclusion coordination state conditional suspension/notification coordination actions

121 coolib Coordinator guardedEntry(String methName, boolean condition, CoordinationAction act) guardedExit(String methName, CoordinationAction act) addSelfex(String methName) addMutex(String[] methNames) some other variants of guardedEntry and guardedExit CoordinationAction doit() Condition checkit() included in distribution of AspectJ

122 summary aspects capture design abstractions that involve several classes many different flavors of aspects –common implementations –protocols –state plus protocol aspects build on existing practices and techniques for OO –instantiation, inheritance –libraries for programming aspects (e.g. coolib)

Part V Style Issues

124 outline when to use aspects –what existing knowledge tells us coding style issues –aspect/class interface –recursion

125 good designs capture “the story” well may lead to good implementations, measured by –code size –tangling –coupling –etc. learned through experience, influenced by taste and style

126 3 examples pull out access tracing pull out error handling pull out X and Y

127 a good aspect (access tracing) class Point {... void set (int x, int y) {... } void setX (int x) {... } void setY (int y) {... } int getX() {... } int getY() {... } } aspect ShowAccesses { static before Point.set, Point.setX, Point.setY, Line.set, Line.setX1, Line.setY1, Line.setX2, Line.setY2 { System.out.println(“W”); } “access tracing” is a good abstraction on its own class Line {... void set(int x1,int y1, int x2,int y2) {... } void setX1 (Point p) {... } void setY1 (Point p) {... } void setX2 (Point p) {... } void setY2 (Point p) {... } }

128 a good aspect (access tracing) class Point { int _x = 0; int _y = 0; void set (int x, int y) { System.out.println(“W”); _x = x; _y = y; } void setX (int x) { System.out.println(“W”); _x = x; } void setY (int y) { System.out.println(“W”); _y = y; } int getX() { return _x; } int getY() { return _y; } alternative implementation: more tangled redundant information commonality is lost consistent change is harder harder to unplug  harder to maintain

129 a good aspect (errors) class DocumentServer { Doc convert(Doc d,Format f){ search locally and remotely } DocID lookupDoc (…) { search locally and remotely } void storeDoc (…) { store locally, notify remotely } void scanDoc (…) { get document from scanner } aspect DocumentServerErrors { static catch (RemoteException e) DocumentServer.lookupDoc, DocumentServer.storeDoc { pop up message offering to change the default server } static catch (DeviceError e) DocumentServer.convert, DocumentServer.scanDoc { pop up message offering to call the key operator } “how to deal with errors in the document server” is a good abstraction on its own

130 a good aspect (errors) class DocumentServer { Doc convert(Doc d,Format f){ try { search locally and remotely } catch (DeviceError e) { pop up message offering to call the key operator } DocID lookupDoc (…) { try { search locally and remotely } catch (RemoteException e) { pop up message offering to change the default server } void storeDoc (…) { try { store locally, notify remotely } catch (RemoteException e) { pop up message offering to change the default server }... alternative implementation: more tangled redundant information commonality is lost consistent change is harder harder to unplug  harder to maintain even single-class aspects can help, if they separate out some reasonable design concern

131 two questionable aspects class Point { } aspect XPart { static new Point._x = 0; static new int Point.getX() { return _x; } static new void Point.setX(int x) { _x = x; } aspect YPart { static new int Point._y = 0; static new int Point.getY() { return _y; } static new void Point.setY(int y) { _y = y; } points have these 2 parts, but does it really make sense to separate them? where does set go? other methods that need x and y? do these 2 aspects improve the code?

132 two questionable aspects class Point { int _x = 0; int _y = 0; void setX (int x) { _x = x; } void setY (int y) { _y = y; } int getX() { return x; } int getY() { return y; } void set (int x, int y) { _x = x; _y = y; } the Point class is a good implementation of the point abstraction: no redundant information no lost commonalties no tangling no difference in size plug in/out: what’s a point without the X part? not really do these 2 aspects improve the code?

133 when to use aspects is there a concern that: –cross-cuts the structure of several classes or methods –is beneficial to separate out

134 … cross-cutting a design concern that involves several classes or methods implemented without AOP would lead to distant places in the code that –do the same thing (i.e. println(“W”), logging) try grep to find these [Griswald] –do a coordinated single thing (i.e. observer pattern, synchronization) harder to find these

135 … beneficial to separate out does it improve the code in real ways? –separation of concerns think about service without logging –clarifies interactions, reduces tangling all the log.writeBytes are really the same checking that the “other object” isn’t red –easier to modify / extend change “W” to “a variable was set” aspect frameworks –plug and play can turn off aspect easily debugging aspects unplugged but not deleted

136 benefits of using AOP good modularity, even in the presence of cross-cutting concerns –less tangled code, more natural code, smaller code –easier maintenance and evolution easier to reason about, debug, change –more reusable plug and play

137 one-to-one association trick obj asp SomeAspect asp = new SomeAspect(); SomeClass obj = new SomeClass(); asp.addObject(obj); aspect SomeAspect { static after SomeClass(*) { SomeAspect asp = new SomeAspect(); asp.addObject(thisObject); }... } SomeClass obj = new SomeClass(); // aspect instance is associated with obj make aspect know about class more than the other way

Part VI References, Related Work

139 AOP and AspectJ on the web

140 workshops ECOOP’97 – ICSE’98 – ECOOP’98 –

141 AOP publications in proceedings of ECOOP’97 tech reports from PARC – workshop papers –see workshop pages

142 work we know best subject-oriented IBM –[Ossher, Harrison] adaptive Northeastern U –[Lieberherr] composition U Twente –[Aksit] assessment of SE UBC –[Murphy] information UCSD –[Griswald]