AspectOriented Programming wAspect J Cristina Lopes Gregor Kiczales

  • Slides: 142
Download presentation
Aspect-Oriented Programming w/Aspect. J™ Cristina Lopes, Gregor Kiczales Xerox PARC www. parc. xerox. com/aop

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

this tutorial is about. . . • using AOP and Aspect. J to: –

this tutorial is about. . . • using AOP and Aspect. J 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 • Aspect. J is: – is an aspect-oriented extension to Java™ that supports general-purpose aspect programming 2

an example system a distributed digital library 3

an example system a distributed digital library 3

clean modular design Book title: string author: string isbn: int pdf: pdf tiff: tiff

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

clean modular code Book class Book { private String private Post. Script private User

clean modular code Book class Book { private String private Post. Script private User title; author; isbn; ps; borrower; public Book(String t, String a, String i, Post. Script p) { title = t; author = a; isbn = i; ps = p; } public User get_borrower() {return borrower; } public void set_borrower(User u) {borrower = u; } public Post. Script get_ ps() { return ps; } } User Library class User { private String name; Library the. Library; Printer the. Printer; class Library { Hashtable books; Library(){ books = new Hashtable(100); } public Book get. Book(User u, String title) { System. out. println("REQUEST TO GET BOOK " + title); if(books. contains. Key(title)) { Book b = (Book)books. get(title); System. out. println("get. Book: Found it: " + b); if (b != null) { if (b. get_borrower() == null) b. set_borrower(u); return b; } } return null; } } public User(String n) { name = n; } public boolean get. Book (String title) { Book a. Book = the. Library. get. Book(this, title); the. Printer. print(this, a. Book); return true; } } Printer public class Printer. Impl { String status = “Idle” Vector jobs; public Printer. Impl() {} pubilc get_status() { return status } public add_job(int j) { jobs. add(j); } } 5

benefits of good modularity • aka “clean separation of concerns” • each decision in

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

but. . . • some issues don’t localize to objects – – – –

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

digital library with optimization Book class Book { private Book. ID private Post. Script

digital library with optimization Book class Book { private Book. ID private Post. Script private User. ID id; ps; borrower; User Library class User { private User. ID id; Library the. Library; Printer the. Printer; interface Library. Interface extends Remote { public Book. ID get. Book(User. ID u, String title) throws Remote. Exception; public Post. Script get. Book. PS(Book. ID bid) throws Remote. Exception; } public Book(String t, String a, String i, Post. Script p) { id = new Book. ID(t, a, i); ps = p; } public public User(String n) { id = new User. ID(n); } public boolean get. Book (String title) { Book. ID a. Book=null; try{ a. Book = the. Library. get. Book(id, title); } catch (Remote. Exception e) {} try { the. Printer. print(id, a. Book); } catch (Remote. Exception e) {} return true; } public User. ID get_uid() { return id; } User. ID get_borrower() {return borrower; } void set_borrower( User. ID u) {borrower = u; } Post. Script get_ ps() { return ps; } Book. ID get_bid() { return id; } } class Book. ID { private String title; author; isbn; public Book. ID(String t, String a, String i) { title = t; author = a; isbn = i; } public String get_title() {return title; } } class User. ID { private String name; public User. ID(String n) { name = n; } public String get_name() { return name; } } } Printerface Printer. Interface extends Remote { public boolean print (User. ID u, Book. ID b) throws Remote. Exception; } class Library extends Unicast. Remote. Object implements Library. Interface Hashtable books; Library() throws Remote. Exception { books = new Hashtable(100); } public Book. ID get. Book(User. ID u, String title) throws Remote. Exception { System. out. println("REQUEST TO GET BOOK " + title); if(books. contains. Key(title)) { Book b = (Book)books. get(title); System. out. println("get. Book: Found it: " + b); if (b != null) { if (b. get_borrower() == null) b. set_borrower(u); return b. get_bid(); } } return null; } public Post. Script get. Book. PS(Book. ID bid) throws Remote. Exception { if (books. contains. Key(bid. get_title())) { Book b = (Book)books. get(bid. get_title()); if (b != null) return b. get_ps(); } return null; } } public class Printer extends Unicast. Remote. Object implements Printer. Interface { private Vector jobs = new Vector(10, 10); private Library the. Library; public Printer() throws Remote. Exception{} public boolean print (User. ID u, Book. ID b) throws Remote. Exception{ Post. Script ps=null; try{ ps = the. Library. get. Book. PS(b); } catch (Remote. Exception e) {} Job new. Job = new Job (ps, u); return queue(new. Job); } boolean queue(Job j) { //. . . return true; } } 8 {

“cross-cutting” Book class Book { private Book. ID private Post. Script private User. ID

“cross-cutting” Book class Book { private Book. ID private Post. Script private User. ID id; ps; borrower; User Library class User { private User. ID id; Library the. Library; Printer the. Printer; interface Library. Interface extends Remote { public Book. ID get. Book(User. ID u, String title) throws Remote. Exception; public Post. Script get. Book. PS(Book. ID bid) throws Remote. Exception; } public Book(String t, String a, String i, Post. Script p) { id = new Book. ID(t, a, i); ps = p; } public public User(String n) { id = new User. ID(n); } public boolean get. Book (String title) { Book. ID a. Book=null; try{ a. Book = the. Library. get. Book(id, title); } catch (Remote. Exception e) {} try { the. Printer. print(id, a. Book); } catch (Remote. Exception e) {} return true; } public User. ID get_uid() { return id; } User. ID get_borrower() {return borrower; } void set_borrower( User. ID u) {borrower = u; } Post. Script get_ ps() { return ps; } Book. ID get_bid() { return id; } } class Book. ID { private String title; author; isbn; public Book. ID(String t, String a, String i) { title = t; author = a; isbn = i; } public String get_title() {return title; } } class User. ID { private String name; public User. ID(String n) { name = n; } public String get_name() { return name; } } } Printerface Printer. Interface extends Remote { public boolean print (User. ID u, Book. ID b) throws Remote. Exception; } public class Printer extends Unicast. Remote. Object implements Printer. Interface { private Vector jobs = new Vector(10, 10); private Library the. Library; public Printer() throws Remote. Exception{} public boolean print (User. ID u, Book. ID b) throws Remote. Exception{ Post. Script ps=null; try{ ps = the. Library. get. Book. PS(b); } catch (Remote. Exception e) {} Job new. Job = new Job (ps, u); return queue(new. Job); } boolean queue(Job j) { //. . . return true; } } class Library extends Unicast. Remote. Object implements Library. Interface Hashtable books; Library() throws Remote. Exception { books = new Hashtable(100); } public Book. ID get. Book(User. ID u, String title) throws Remote. Exception { System. out. println("REQUEST TO GET BOOK " + title); if(books. contains. Key(title)) { Book b = (Book)books. get(title); System. out. println("get. Book: Found it: " + b); if (b != null) { if (b. get_borrower() == null) b. set_borrower(u); return b. get_bid(); } } return null; } public Post. Script get. Book. PS(Book. ID bid) throws Remote. Exception { if (books. contains. Key(bid. get_title())) { Book b = (Book)books. get(bid. get_title()); if (b != null) return b. get_ps(); } return null; } } this optimization cross-cuts the primary structure of the program 9 {

effects of cross-cutting • “tangled code” • code duplication, • difficult to reason about

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 10

the AOP idea • many cross-cuts aren’t random! – they serve specific purposes: •

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. . . 11

aspects: a cross-cutting module class Book { private Book. ID id; class Book {

aspects: a cross-cutting module class Book { private Book. ID id; class Book { private Post. Script ps; private. User. ID String title; private borrower; private String author; private String public Book(String t, isbn; String a, String i, Post. Script p) { private ps; id = new. Post. Script Book. ID(t, a, i); private borrower; ps = p; User } public Book(String t, String a, String i, Post. Script p) { title = t; get_borrower() {return borrower; } public User. ID author a; public void= set_borrower( User. ID u) {borrower = u; } isbn. Post. Script = i; public get_ ps() { return ps; } ps =Book. ID p; public get_bid() { return id; } } } class User { private User. ID id; class User { Library the. Library; privatethe. Printer; String name; Printer Library the. Library; Printer the. Printer; public User(String n) { id = new User. ID(n); } interface Library. Interface extends Remote { public Book. ID get. Book(User. ID u, String title) throws Remote. Exception; class Library { Hashtable books; public Post. Script get. Book. PS(Book. ID bid) throws Remote. Exception; Library(){ } books = new Hashtable(100); } extends Unicast. Remote. Object implements Library. Interface { class Library publicboolean User(String n) (String { name =title) n; } { public get. Book Hashtable public books; Book get. Book(User u, String title) { System. out. println("REQUEST TO GET BOOK " + title); Book. ID a. Book=null; Library() throws Remote. Exception { public if(books. contains. Key(title)) { try{ boolean get. Book (String title) { books = new Hashtable(100); Book = the. Library. get. Book(this, Book b = (Book)books. get(title); a. Book = the. Library. get. Book(id, title); } Found it: " + b); } the. Printer. print(this, a. Book); catch (Remote. Exception e) {} public Book. ID System. out. println("get. Book: get. Book(User. ID u, String title) return true; if (b != null) { try { throws Remote. Exception { } the. Printer. print(id, a. Book); if (b. get_borrower() null) System. out. println("REQUEST TO GET == BOOK " + title); } } catch (Remote. Exception e) {} b. set_borrower(u); if(books. contains. Key(title)) { return b; return true; Book b = (Book)books. get(title); public User } class Book. ID { get_borrower() {return borrower; } } System. out. println("get. Book: Found it: " + b); public String void set_borrower(User u) {borrower = u; } private title; public User. ID get_uid() { return id; } if (b != }null) { public String Post. Scriptauthor; get_ ps() { return ps; } return null; private } if (b. get_borrower() == null) }private String } isbn; b. set_borrower(u); } class User. ID { return b. get_bid(); public Book. ID(String t, String a, String i) { private String name; } title = t; } author = a; public User. ID(String n) { name = n; } return null; isbn = i; public String get_name() { return name; } } public Post. Script get. Book. PS(Book. ID bid) public String get_title() {return title; } throws Remote. Exception { } if (books. contains. Key(bid. get_title())) { Book b = (Book)books. get(bid. get_title()); if (b != null) return b. get_ps(); } return null; interface Printer. Interface extends Remote { } public boolean print (User. ID u, Book. ID b) throws Remote. Exception; } } public extends publicclass. Printer. Impl { Unicast. Remote. Object implements Printer. Interface { String status = “Idle” private Vector jobs; jobs = new Vector(10, 10); private Library the. Library; public Printer. Impl() {} public throws Remote. Exception{} pubilc. Printer() get_status() { return status } public print j) (User. ID u, Book. ID b) throws Remote. Exception{ publicboolean add_job(int { Post. Script ps=null; jobs. add(j); try{} ps = the. Library. get. Book. PS(b); } } catch (Remote. Exception e) {} Job new. Job = new Job (ps, u); return queue(new. Job); } boolean queue(Job j) { //. . . return true; } } 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 12

aspect-oriented programming • “aspects” are program constructs that cross-cut classes 1 in welldefined, principled

aspect-oriented programming • “aspects” are program constructs that cross-cut classes 1 in welldefined, 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 13

aspect weaving • weaver combines classes and aspects – compiler / pre-processor / interpreter

aspect weaving • weaver combines classes and aspects – compiler / pre-processor / interpreter – unambiguously coordinates cross-cutting class Book { private String title; private String author; private String isbn ; private Post. Script ps ; private User borrower; public Book(String t, String a, String i, Post. Script p) { title = t; author = a; isbn = i; ps = p; } public class Printer. Impl { String status = “Idle” Vector jobs; public User get_borrower() {return borrower; } public void set_borrower(User u) {borrower = u; } public Post. Script get_ ps() { return ps; } } class User { private String name; Library the. Library ; Printer the; Printer classes public User(String n) { name = n; } public boolean get. Book (String title) { Book a. Book = the. Library. get. Book (this, title); the. Printer. print(this, a. Book ); return true; } } portal Printer { void print(Book book) { book: Book: {direct pages; } } public Printer. Impl () {} pubilc get_status() { return status } public add_job( int j) { jobs. add(j); } } class Library { Hashtable books; Library(){ books = new Hashtable (100); } public Book get. Book (User u, String title) { System. out. println ("REQUEST TO GET BOOK " + title); if(books. contains. Key (title)) { Book b = (Book)books. get(title); System. out. println ("get. Book : Found it: " + b); if (b != null) { if (b. get_borrower() == null) b. set_borrower(u); return b; } } return null; } } aspect weaver executable code portal Library { Book find (String title){ return: Book: {copy title, author, isbn; } } } aspects 14

benefits of using AOP • good modularity, even in the presence of cross-cutting concerns

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 15

Aspect. J™ is… • the first general-purpose AO language – “lexical” cross-cutting – concern-specific

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

looking ahead • AOP works because cross-cutting modularities aren’t random • aspects are used

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 problem structure Part IV: how to use Aspect. J to capture the higher-level cross-cutting in your systems Aspect. J mechanisms Part II: the kinds of cross-cutting mechanisms Aspect. J can capture 17

outline • I AOP overview – motivation, what is the AOP idea • II

outline • I AOP overview – motivation, what is the AOP idea • II Aspect. J overview – basic concepts, kinds of cross-cutting • III key technical details – running the aspect weaver, source files, emacs support • IV using Aspect. J – 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 18

Part II Basic Concepts of Aspect. J

Part II Basic Concepts of Aspect. J

goals of this chapter • present the basic concepts of Aspect. J – the

goals of this chapter • present the basic concepts of Aspect. J – 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 Aspect. J 20

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

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

overview Aspect. J extends this with aspects that cross-cut the code in classes in

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

overview Aspect. J extends this with aspects that cross-cut the code in classes in

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

overview Aspect. J extends this with aspects that cross-cut the code in classes in

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

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

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

a first example class Point { int _x = 0; int _y = 0;

a first example class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } aspect Show. Accesses { static before Point. set, Point. set. X, Point. set. Y { System. out. println(“W”); } } void set. X (int x) { _x = x; } void set. Y (int y) { _y = y; } int get. X() { return _x; } int get. Y() { return _y; } } 26

what it does p 1 Point p 1 = new Point(); Point p 2

what it does p 1 Point p 1 = new Point(); Point p 2 = new Point(); p 2 The screen p 1. set(3, 3); W p 2. set. X(3); W 27

one aspect, one class Show. Accesses aspect Show. Accesses { static before Point. set,

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

presentation note! aspect Show. Accesses { static before Point. set, Point. set. X, Point.

presentation note! aspect Show. Accesses { static before Point. set, Point. set. X, Point. set. Y { System. out. println(“W”); } } 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 Space. War code) 29

without Aspect. J here’s what we would have had to write in plain Java

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

extend to writes and reads. . . p 1 Point p 1 = new

extend to writes and reads. . . p 1 Point p 1 = new Point(); Point p 2 = new Point(); p 2 The screen p 1. set(3, 3); W p 2. set. X(3); W int x = p 1. get. X(); R 31

one aspect with two weaves Show. Accesses Point aspect Show. Accesses { static before

one aspect with two weaves Show. Accesses Point aspect Show. Accesses { static before Point. set, Point. set. X, Point. set. Y { System. out. println(“W”); } } static before Point. get. X, Point. get. Y, { System. out. println(“R”); } } just as a class can have n methods an aspect can have n weaves 32

one aspect, two classes Show. Accesses Point Line aspect Show. Accesses { static before

one aspect, two classes Show. Accesses Point Line aspect Show. Accesses { static before Point. set, Point. set. X, Point. set. Y { System. out. println(“W”); } } static before Line. set, Line. set. X 1, . . . { System. out. println(“W”); } } 33

one aspect, two classes Show. Accesses Point Line aspect Show. Accesses { static before

one aspect, two classes Show. Accesses Point Line aspect Show. Accesses { static before Point. set, Point. set. X, Point. set. Y { Point. set. Y, System. out. println(“W”); Line. set, } Line. set. X 1, }. . . { System. out. println(“W”); } } static before Point. get. X, Point. get. Y, Line. get. X 1, . . . { System. out. println(“R”); } } 34

reads, writes and constructors aspect Show. Accesses { static before Point. set, Point. set.

reads, writes and constructors aspect Show. Accesses { static before Point. set, Point. set. X, Point. set. Y Line. set, Line. set. X 1, . . . { System. out. println(“W”); } static before Point. get. X, Point. get. Y, Line. get. X 1, . . . { System. out. println(“R”); } static before Point(*), Line(*) { System. out. println(“C”); } } methods constructors 35

summary so far Show. Accesses Point one aspect, one class Show. Accesses Point Line

summary so far Show. Accesses Point one aspect, one class Show. Accesses Point 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 one aspect, two classes 36

aspects are special classes class Point { … } class Line { … }

aspects are special classes class Point { … } class Line { … } class Circle { … } Log. New. Instances Circle Point Line aspect Log. New. Instances { static Data. Output. Stream log = null; static { // initializer try { log = new Data. Output. Stream( new File. Output. Stream(“log”)); } catch (IOException e) {} } static after Point(*), Line(*), Circle(*) { long time = System. current. Time. Millis(); try { log. write. Bytes(“New instance at ” + time + “ ” + this. Object. to. String() + “n”); } catch (IOException e) {} } } aspect var the object 37

what it does p 1 Point p 1 = new Point(); Point p 2

what it does p 1 Point p 1 = new Point(); Point p 2 = new Point(); l 1 Line l 1 = new Line(); Line l 2 = new Line(); Line l 3 = new Line(); p 2 l 2 c 1 l 3 Circle c 1 = new Circle(); New New New instance instance at at at 3252384 3252451 3252653 3255678 3258765 4532805 Point 321 Point 322 Line 611 Line 612 Line 613 Circle 901 38

per-object aspect-related state make Points go back to 0, 0 after every 100 sets

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

a peek ahead to style issues make Points go back to 0, 0 after

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

how this runs count=2 count=1 count=0 Point p 1 = new Point(); p 1

how this runs count=2 count=1 count=0 Point p 1 = new Point(); p 1 count=0 Point p 2 = new Point(); p 2 p 1. set(3, 3); p 1. set. X(3); p 2. set. Y(7); 41

summary so far Show. Accesses Point Line n aspects, m classes Auto. Reset Point

summary so far Show. Accesses Point Line n aspects, m classes Auto. Reset Point • 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 • nxm cross-cutting adding state to each object 42

aspect instances Auto. Reset Point aspect can be instantiated and aspect instances can then

aspect instances Auto. Reset Point 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 43

simple use of aspect instances not a weave non-static aspect Auto. Reset { int

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

what it does count=1 count=2 count=0 count=1 Point p 1 = new Point(); p

what it does count=1 count=2 count=0 count=1 Point p 1 = new Point(); p 1 Auto. Reset a 1 = new Auto. Reset(); a 1. add. Object(p 1); Point p 2 = new Point(); Auto. Reset a 2 = new Auto. Reset(); a 2. add. Object(p 2); p 1. set(3, 3); p 1. set. X(3); p 2. set. Y(7); p 2 after instantiation of every Point object, instantiate an Auto. Reset aspect and associate the two 45

one aspect instance, many objects Point p 1 = new Point(1, 1); Point p

one aspect instance, many objects Point p 1 = new Point(1, 1); Point p 2 = new Point(1, 1); Point p 3 = new Point(1, 1); Auto. Reset a 1 = new Auto. Reset(); a 1. add. Object(p 1); a 1. add. Object(p 2); p 1 p 2 p 3 a 1. add. Object(p 3); the goal here is to get all of the Points to share a single Auto. Reset counter, so that they all reset, when as a group they have been set 100 times 46

one aspect instance, many objects aspect Auto. Reset { int count = 0; after

one aspect instance, many objects aspect Auto. Reset { int count = 0; after Point. set, Point. set. X, Point. set. Y { if (++count >= 100) { Vector objects = this. Aspect. get. Objects(); Enumeration e = objects. elements(); while (e. has. More. Elements()) { Point p = (Point)e. next. Element(); count = -1; p. set(0, 0); } } aspect. get. Objects() returns a vector of the objects object. get. Aspects() returns a vector of the aspects 47

aspects compose Log. New. Instances Show. Accesses Circle Line Auto. Reset Point • all

aspects compose Log. New. Instances Show. Accesses Circle Line Auto. Reset Point • all three aspects apply to the class Point – more on controlling this in next part • code retains good separation of concerns 48

with Aspect. J class Point { int _x = 0; int _y = 0;

with Aspect. J class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } aspect Auto. Reset { int counter = 0; after Point. set, Point. set. X, Point. set. Y { if (++counter >= 100) { count = -1; set(0, 0); } } void set. X (int x) { _x = x; } void set. Y (int y) { _y = y; } int get. X() { return _x; } int get. Y() { return _y; } } here’s the complete code written with Aspect. J } aspect Log. New. Instances { static Data. Output. Stream log = null; static { // initializer try { log = new Data. Output. Stream( new File. Output. Stream(“log”)); } catch (IOException e) {} } static after Point(*), Line(*), Circle(*) { long time = System. current. Time. Millis(); try { log. write. Bytes(“New instance at ” + time + “ ” + this. to. String() + “n”); } catch (IOException e) {} } aspect Show. Accesses static before Point. set, Point. set. X, Point. set. Y Line. set, Line. set. X 1, . . . { System. out. println(“W”); } static before Point. get. X, Point. get. Y, Line. get. X 1, . . . { System. out. println(“R”); } static before Point(*), Line(*) { System. out. println(“C”); } } } { 49

without Aspect. J class Point here’s a well-written version of what we would have

without Aspect. J class Point here’s a well-written version of what we would have had to write in plain Java { int _x = 0; int _y = 0; Point () { System. out. println("C"); long time = System. current. Time. Millis(); try { log. write. Bytes("New instance at " + time + " " + Point. this. to. String() + "n"); } catch (IOException e) { } Vector auto. Resets = new Vector(); void do. Auto. Resets() { java. util. Enumeration enumeration = auto. Resets. elements(); Auto. Reset reset; while (enumeration. has. More. Elements()) { reset = (Auto. Reset)enumeration. next. Element(); if(++ reset. count >= 100){ System. out. println("Reseting " + this + ". "); reset. count = - 1; set(0, 0); } } } void set(int x, int y) { System. out. println("W"); _x = x; _y = y; do. Auto. Resets(); } } void set. X(int x) static Data. Output. Stream log = null; { System. out. println("W"); _x = x; do. Auto. Resets(); static { try { log = new Data. Output. Stream(new File. Output. Stream("log")); } catch (IOException e) { } } } void set. Y(int y) { System. out. println("W"); _y = y; do. Auto. Resets(); } class Auto. Reset } { int count = 0; public void add. To. Scope(Point object) { object. auto. Resets. add. Element(this); } public void remove. From. Scope(Point object) { object. auto. Resets. remove. Element(this); } int get. X() { System. out. println("R"); return _x; } int get. Y() { System. out. println("R"); return _y; } } 50

benefits of using AOP • good modularity, even in the presence of cross-cutting concerns

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 51

summary • advise weaves, new weaves • different kinds of cross-cutting Log. New. Instances

summary • advise weaves, new weaves • different kinds of cross-cutting Log. New. Instances Show. Accesses Circle Line Auto. Reset Point static and non-static • weave code runs in mixed scope 52

looking ahead • AOP works because cross-cutting modularities aren’t random • aspects are used

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 problem structure Part III: how to use Aspect. J to capture the higher-level kinds of cross-cutting in your systems Aspect. J mechanisms Part II: the low-level kinds of crosscutting Aspect. J can capture 53

Part III Using Aspect. J, the tool

Part III Using Aspect. J, the tool

source files “. ajava” files contain: Point Show. Access • regular Java source code

source files “. ajava” files contain: Point Show. Access • regular Java source code • aspect source code 55

processing aspects Point aspect weaver byte code Show. Access . ajava files . class

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

intermediate files pre-processor: • simplicity • transition strategy Show. Access aspect weaver Java code

intermediate files pre-processor: • simplicity • transition strategy Show. Access aspect weaver Java code byte code Point . ajava files . class files 57

programming environment • source files – extension – contents • look&feel of ajava mode

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

demo of the Aspect. J tools 59

demo of the Aspect. J tools 59

Part IV - Using Aspects problem structure Part IV: how to use Aspect. J

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

purpose and structure • styles of aspects presented with examples: – common implementations –

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

notation Class Interface Aspect object slide containing semantic rules or conventions piece of implementation

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

terminology weave mode aspect Show. Accesses { static before Point. set, Point. set. X,

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

designators • • methods: constructors: initializers: fields: Result. Type. Id ( Formals ) Type.

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

outline • using aspects to localize : – common implementations – interaction (protocols) –

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

example: plug & play tracing class Customer { … } class Order { …

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

with an aspect Customer aspect Trace { static before * Customer. *(*), * Order.

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

plug and play (plug and debug) • plug in: ajweaver Customer. ajava Order. ajava

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

special vars, scope rules • specials: – – this. Aspect this. Object this. Class.

special vars, scope rules • specials: – – this. Aspect this. Object this. Class. Name this. Method. Name • scope rules in body of weaves: 1. formals 2. aspect 3. object strings 69

an exception aspect in all implementations of this interface, want to log exceptions Xerox.

an exception aspect in all implementations of this interface, want to log exceptions Xerox. Server Status get. Status() void register. Client(Client c) 70

an exception aspect Xerox. Server. Catcher { static catch Xerox. Server. get. Status, Xerox.

an exception aspect Xerox. Server. Catcher { static catch Xerox. Server. get. Status, Xerox. Server. register. Client (Exception e) { System. err. println(“Exception ” + e + “ at ” + System. current. Time. Millis()); throw e; } } type name 71

types • in Java: – Interface = Type (no implementation) – Class = Type

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 72

aspects for interfaces Xerox. Server implements Class 1 Xerox. Server. Catcher implements Class 2

aspects for interfaces Xerox. Server implements Class 1 Xerox. Server. Catcher implements Class 2 Class 3 . . . Xerox. Server. Catcher affects Class 1, Class 2, Class 3, . . . 73

aspects that localize common code A A B Aspect B C C used in

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

aspects that localize common code • there is an abstraction occurring in several classes

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 75

outline • using aspects to localize : – common implementations – interaction (protocols) •

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

example: tic-tac-toe TTTObserver public: action. Performed(Action. Event) about. Window() update() protected: add. Menu() add.

example: tic-tac-toe TTTObserver public: action. Performed(Action. Event) about. Window() update() protected: add. Menu() add. Board. Display() add. Status. Display() finish() Tic. Tac. Toe public: run() start. Game() new. Player(Player) put. Mark(Player, Position) get. Board() get. NPlayers() get. Current. Player() is. Over() get. Result() attach(TTTObserver) detach(TTTObserver) protected: wait. For. Players() wait. For. Move() end. Game() notify() on state changes plus other classes. . . 2 Player public: run() get. Turn() end. Game(Player, Result) action. Performed(Action. Event) mouse. Clicked(Mouse. Event) protected: add. Status. Display() 77

view of the update protocol Tic. Tac. Toe public: . . . attach(TTTObserver) detach(TTTObserver)

view of the update protocol Tic. Tac. Toe public: . . . attach(TTTObserver) detach(TTTObserver) protected: notify() on state changes TTTObserver public: update() Canvas Board. Display update() Status. Display 6 tightly related methods and calls to notify() are spread all over update() Player Label 78

the protocol in an aspect TTTDisplay. Protocol { static new Vector Tic. Tac. Toe.

the protocol in an aspect TTTDisplay. Protocol { static new Vector Tic. Tac. Toe. observers = new Vector(); static new Tictactoe TTTObserver. game; Tic. Tac. Toe static new void Tic. Tac. Toe. attach(TTTObserver obs) { observers. add. Element(obs); } static new void Tic. Tac. Toe. detach(TTTObserver obs) { observers. remove. Element(obs); } static new void TTTObserver. update() { board. update(game); status. update(game); } static new void Board. Display. update(Tic. Tac. Toe game), Status. Display. update(Tic. Tac. Toe game) { the. Game = game; repaint(); } TTTObserver Board. Display Status. Display aspect contains fields, methods and procedures of protocol // all methods that change static after Tic. Tac. Toe. start. Game, Tic. Tac. Toe. new. Player, Tic. Tac. Toe. put. Mark, Tic. Tac. Toe. end. Game { for (int i = 0; i < observers. size(); i++) ((Observer)observers. element. At(i)). update(); } } 79

observer pattern observers. add. Element(obs); observers. remove. Element(obs); Subject attach(Observer) detach(Observer) notify() on state

observer pattern observers. add. Element(obs); observers. remove. Element(obs); Subject attach(Observer) detach(Observer) notify() on state changes Concrete. Subject With inheritance Observer update() Concrete. Observer update() • protocol is spread in many classes • not so good in Java - uses up only inheritance link 80

observer pattern Subject attach(Observer) detach(Observer) implements observers. add. Element(obs); observers. remove. Element(obs); Concrete. Subject

observer pattern Subject attach(Observer) detach(Observer) implements observers. add. Element(obs); observers. remove. Element(obs); Concrete. Subject attach(Observer) detach(Observer) notify() on state changes with interfaces Observer update() implements Concrete. Observer update() • protocol is spread in many classes • some replication of code in the concrete subjects 81

observer pattern with aspects Subject. Observer static new new Observer. subject Subject. observers Subject.

observer pattern with aspects Subject. Observer static new new Observer. subject Subject. observers Subject. attach(Observer) Subject. detach(Observer) Subject attach(Observer) detach(Observer) Observer implements observers. add. Element(obs); observers. remove. Element(obs); Concrete. Subject Concrete. Observer update() for (int i = 0; i < observers. size(); i++) { obs = observers. element. At(i); obs. update(); } Concrete. Observer. Updates static new Concrete. Observer. update() static after Concrete. Subject. m 1, Concrete. Subject. m 2, . . . • protocol implementation is encapsulated in the aspects 82

aspects that localize interaction A 4 1 B A Aspect 2 B 3 C

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

aspects that localize interaction • there is an interaction (protocol) involving several classes •

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 84

outline • using aspects to localize : – common implementations – interaction (protocols) –

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

static vs. non-static class Point { int _x = 0; int _y = 0;

static vs. non-static class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } void set. X (int x) { _x = x; } void set. Y (int y) { _y = y; } int get. X() { return _x; } int get. Y() { return _y; } } aspect Count 1 { static int count = 0; static before Point. set, Point. set. X, Point. set. Y { count++; } } aspect Count 2 { int count = 0; before Point. set, Point. set. X, Point. set. Y { this. Aspect. count++; } } 86

static vs. non-static fields Point p 0 = new Point(0, 0); Point p 1

static vs. non-static fields Point p 0 = new Point(0, 0); Point p 1 = new Point(1, 1); one incarnation of count (same as static in class fields) Point p 0 = new Point(0, 0); Point p 1 = new Point(1, 1); one incarnation of count per aspect instance (same as non-static in class fields) aspect Count 1 { static int count = 0; static before Point. set, Point. set. X, Point. set. Y { count++; } } aspect Count 2 { int count = 0; before Point. set, Point. set. X, Point. set. Y { this. Aspect. count++; } } 87

static vs. non-static weaves two issues: 1. objects affected by weave 2. the existence

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

static vs. non-static weaves (1) Point p 0 = new Point(0, 0); Point p

static vs. non-static weaves (1) Point p 0 = new Point(0, 0); Point p 1 = new Point(1, 1); p 0. set(3, 3); p 1. set(4, 4); static weave affects all Point objects, always Point p 0 = new Point(0, 0); Point p 1 = new Point(1, 1); p 0. set(3, 3); p 1. set(4, 4); Count 2 count = new Count 2(); count. add. Object(p 0); p 0. set(3, 3); aspect Count 1 { static int count = 0; static before Point. set, Point. set. X, Point. set. Y { count++; } } aspect Count 2 { int count = 0; before Point. set, Point. set. X, Point. set. Y { this. Aspect. count++; } } non-static weave affects just the Point objects associated with an instance of Count 2 89

static vs. non-static weaves (2) like a static method, this weave is executed without

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

static vs. non-static (methods) class Point { int _x = 0; int _y =

static vs. non-static (methods) class Point { int _x = 0; int _y = 0; void set (int x, int y) { _x = x; _y = y; } void set. X (int x) { _x = x; } void set. Y (int y) { _y = y; } int get. X() { return _x; } int get. Y() { return _y; } } non-static methods aspect Count 1 { static int count = 0; static before Point. set, Point. set. X, Point. set. Y { count++; } } no particular aspect instance (no this. Aspect) but a particular Point object, this. Object available in static and non-static weaves of non-static methods 91

static vs. non-static (specials) non-static weave non-static method available: this. Object this. Aspect this.

static vs. non-static (specials) non-static weave non-static method available: this. Object this. Aspect this. Class. Name this. Methd. Name static weave available: this. Object this. Class. Name this. Method. Name available: this. Class. Name this. Method. Name 92

special methods • for aspects – void add. Object(Object o) – void remove. Object(Object

special methods • for aspects – void add. Object(Object o) – void remove. Object(Object o) – Vector get. Objects() • for objects – Vector get. Aspects() 93

example: a shared log file Customer want to log new instances of these classes

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

static aspect state Customer Order Product globally shared by Customer, Order, Product aspect Log.

static aspect state Customer Order Product globally shared by Customer, Order, Product aspect Log. New. Instances { static Data. Output. Stream log = null; static { // initializer try { log = new Data. Output. Stream( new File. Output. Stream(“log”)); } catch (IOException e) {} } static after Customer(*), Order(*), Product(*) { long time = System. current. Time. Millis(); try { log. write. Bytes(“New instance at ” + time + “ ” + this. Object. to. String() + “n”); } catch (IOException e) {} } } 95

example: monitoring Service. Monitoring DBServer Printer. Server Web. Server Document. Server 96

example: monitoring Service. Monitoring DBServer Printer. Server Web. Server Document. Server 96

example: monitoring public class DBServer { public Result query(Query q) { public class Printer.

example: monitoring public class DBServer { public Result query(Query q) { public class Printer. Server { public void print(Path p) { monitor. an. Event(new SEvent(this)); try { return process. Query(q); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally { monitor. an. Event(new OKEvent(this)); } monitor. an. Event(new SEvent(this)); try { printit(p); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } } public Status get. Status() { monitor. an. Event(new IEvent(this)); return status; }. . . } } public class Web. Server { public void post(Data d) { public class Document. Server { public Doc convert(Doc d, Format f) { monitor. an. Event(new SEvent(this)); try { postit(d); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } monitor. an. Event(new SEvent(this)); try { return convert. Data(d, f); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } } public Data get(Path p) { } public void new. Document(Doc d) { monitor. an. Event(new SEvent(this)); try { return getit(p); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } monitor. an. Event(new SEvent(this)); try { add. Document(d); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } }. . . } 97

example: monitoring public class DBServer { public Result query(Query q) { public class Printer.

example: monitoring public class DBServer { public Result query(Query q) { public class Printer. Server { public void print(Path p) { monitor. an. Event(new SEvent(this)); try { return process. Query(q); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally { monitor. an. Event(new OKEvent(this)); } monitor. an. Event(new SEvent(this)); try { printit(p); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } } } public Status get. Status() { public SEvent(this)); Status get. Status() { monitor. an. Event(new IEvent(this)); return status; try { return process. Query(q); } } catch (Exception. . . e) { } } monitor. an. Event(new XEvent(this)); } finally { public class Web. Server { monitor. an. Event(new public class Document. Server { OKEvent(this)); public void post(Data }d) { public Doc convert(Doc d, Format f) { }. . . monitor. an. Event(new SEvent(this)); try { postit(d); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } monitor. an. Event(new SEvent(this)); try { return convert. Data(d, f); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } } public Data get(Path p) { } public void new. Document(Doc d) { monitor. an. Event(new SEvent(this)); try { return getit(p); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } monitor. an. Event(new SEvent(this)); try { add. Document(d); } catch (Exception e) { monitor. an. Event(new XEvent(this)); } finally {monitor. an. Event(new OKEvent(this)); } }. . . } 98

aspect as monitor (static state) aspect Service. Monitoring { static Vector servers. Info =

aspect as monitor (static state) aspect Service. Monitoring { static Vector servers. Info = new Vector(5); static int total. Service. Requests, total. Exceptions, total. Completions; static before DBServer. query, Web. Server. post, Web. Server. get, Printer. Server. print, Document. Server. convert, Document. Server. new. Document { an. Event(new SEvent(this. Object)); } more befores, afters, catches, finally static void an. Event(Event e) { update aspect state; sometimes send. Command } static protected void send. Command(Server srv, Command c) { srv. an. Order(c); } } 99

one monitor for all servers Service. Monitoring static state static weaves (static state) •

one monitor for all servers Service. Monitoring static state static weaves (static state) • only one incarnation of the static variables • weaves statically associated with classes (they affect all objects) DBServer Web. Server Printer. Server Document. Server 100

the need for aspect instances • need different instances of aspect state – e.

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 101

service monitors aspect Service. Monitoring { static Vector servers. Info = new Vector(5); static

service monitors aspect Service. Monitoring { static Vector servers. Info = new Vector(5); static int total. Service. Requests, total. Exceptions, total. Completions; static before DBServer. query, Web. Server. post, Web. Server. get, Printer. Server. print, Document. Server. convert, Document. Server. new. Document { an. Event(new SEvent(this. Object)); } more befores, afters, catches, finally static void an. Event(Event e) { update aspect’s state; sometimes send. Command } static protected void send. Command(Server srv, Command c) { srv. an. Order(c); } } 102

monitors for groups of servers state Service. Monitoring non-static weaves state a. Service. Monitor.

monitors for groups of servers state Service. Monitoring non-static weaves state a. Service. Monitor. add. Object(a. Server) DBServer Web. Server Printer. Server Document. Server 103

inheritance of aspects class My. Document. Server extends Document. Server { protected boolean check.

inheritance of aspects class My. Document. Server extends Document. Server { protected boolean check. Consistency() {. . . } public Doc convert(Doc d, Format f) { Doc new. Doc = super. convert(d, f); if (check. Consistency(new. Doc)) return new. Doc; else return null; } extension override } 104

inheritance of aspects Super. Type Super. Class Aspect applies to all implementations of designated

inheritance of aspects Super. Type Super. Class Aspect applies to all implementations of designated types Aspect subclass implements Super. Type extends Sub. Class overriding of methods in sub: • aspect still applies and • doesn’t repeat in calls to super 105

inheritance of aspects A foo() Aspect 1 before A. foo {. . . }

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

the effective method { try { all befores < call to method containing original

the effective method { try { all befores < call to method containing original body > all afters } all catches all finallys } 107

aspect as monitor (static state) aspect Service. Monitoring { static Vector servers. Info =

aspect as monitor (static state) aspect Service. Monitoring { static Vector servers. Info = new Vector(5); static int total. Service. Requests, total. Exceptions, total. Completions; static before DBServer. query, Web. Server. post, Web. Server. get, Printer. Server. print, Document. Server. convert, Document. Server. new. Document { an. Event(new SEvent(this. Object)); } more befores, afters, catches, finally static void an. Event(Event e) { update aspect state; sometimes send. Command } static protected void send. Command(Server srv, Command c) { srv. an. Order(c); } } 108

inheritance between aspects aspect Verbose. Monitor extends Service. Monitoring { Object. Output. Stream log.

inheritance between aspects aspect Verbose. Monitor extends Service. Monitoring { Object. Output. Stream log. Stream; Verbose. Monitor() { initialize log. Stream } extension protected void log(Event e) { log. Stream. write. Object(e); } public void an. Event(Event e) { System. out. println(e. to. String()); log(e); super. an. Event(e); } override } 109

inheritance between aspects Super. Aspect • similar to inheritance between classes: extends Sub. Aspect

inheritance between aspects Super. Aspect • similar to inheritance between classes: extends Sub. Aspect – 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) 110

aspects that localize shared state A O A B Aspect B C C used

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

aspects that localize shared state • state needs to be encapsulated • an object

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 112

outline • using aspects to localize : – common implementations – interaction (protocols) –

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) 113

the cross-cutting nature of concurrency control Problem: a square and a circle are manipulated

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 change. Color(red) request on one of them must wait if the other is currently red. OK Not OK 114

the cross-cutting nature of concurrency control class Square extends Shape { Pos pos; int

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

using an aspect No. Simultaneous. Red { Shape red. Shape = null; // holds

using an aspect No. Simultaneous. Red { Shape red. Shape = null; // holds the reference to // the red shape or null before void Square. change. Color(Color color), void Circle. change. Color(Color color) { if (color == Color. red) { synchronized (this. Aspect) { while (!(red. Shape == null || red. Shape == this. Object)) { try { wait(); } catch (Interrupted. Exception e) {} } red. Shape = this. Object; } } } after void Square. change. Color(Color color), void Circle. change. Color(Color color) { if (color != Color. red) { synchronized (this. Aspect) { if (this. Object == red. Shape) // coming out of red. Shape = null; notify. All(); } } 116

using an aspect No. Simultaneous. Blue { Shape blue. Shape = null; // holds

using an aspect No. Simultaneous. Blue { Shape blue. Shape = null; // holds the reference to // the blue shape or null before void Square. change. Color(Color color), void Circle. change. Color(Color color) { can pull out common code into a super if (color == Color. blue) { synchronized (this. Aspect) { while (!(blue. Shape == null || blue. Shape == this. Object)) { try { wait(); } catch (Interrupted. Exception e) {} } blue. Shape = this. Object; } } } after void Square. change. Color(Color color), void Circle. change. Color(Color color) { if (color != Color. blue) { synchronized (this. Aspect) { if (this. Object == blue. Shape) // coming out of blue. Shape = null; notify. All(); } } 117

using coolib aspect No. Simultaneous. Red extends Coordinator { Shape red. Shape = null;

using coolib aspect No. Simultaneous. Red extends Coordinator { Shape red. Shape = null; before void Square. change. Color(String color), void Circle. change. Color(String color) { if (color == Color. red) guarded. Entry(this. Method. ID, new Condition() { boolean checkit() { return (red. Shape == null || red. Shape == this. Object); }}, new Coordination. Action() { void doit() { red. Shape = this. Object; } }); } after void Square. change. Color(String color), void Circle. change. Color(String color) { if (color != Color. red) guarded. Exit(this. Method. ID, new Coordination. Action() { void doit() {if (this. Object==red. Shape) red. Shape = null; }}); } } 118

coolib • avoid writing ad-hoc coordination code in the classes: use coordination aspects •

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

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

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

coolib Coordinator Coordination. Action guarded. Entry(String meth. Name, boolean condition, Coordination. Action act) guarded.

coolib Coordinator Coordination. Action guarded. Entry(String meth. Name, boolean condition, Coordination. Action act) guarded. Exit(String meth. Name, Coordination. Action act) add. Selfex(String meth. Name) add. Mutex(String[] meth. Names) doit() Condition checkit() some other variants of guarded. Entry and guarded. Exit included in distribution of Aspect. J 121

summary • aspects capture design abstractions that involve several classes • many different flavors

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) 122

Part V Style Issues

Part V Style Issues

outline • when to use aspects – what existing knowledge tells us • coding

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

good designs • capture “the story” well • may lead to good implementations, measured

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 125

3 examples • pull out access tracing • pull out error handling • pull

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

a good aspect (access tracing) class Point {. . . void set (int x,

a good aspect (access tracing) class Point {. . . void set (int x, int y) {. . . } void set. X (int x) {. . . } void set. Y (int y) {. . . } int get. X() {. . . } int get. Y() {. . . } } class Line {. . . void set(int x 1, int y 1, int x 2, int y 2) {. . . } void set. X 1 (Point p) {. . . } void set. Y 1 (Point p) {. . . } void set. X 2 (Point p) {. . . } void set. Y 2 (Point p) {. . . } } aspect Show. Accesses { static before Point. set, Point. set. X, Point. set. Y, Line. set. X 1, Line. set. Y 1, Line. set. X 2, Line. set. Y 2 { System. out. println(“W”); } } “access tracing” is a good abstraction on its own 127

a good aspect (access tracing) class Point { int _x = 0; int _y

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 set. X (int x) { System. out. println(“W”); _x = x; } void set. Y (int y) { System. out. println(“W”); _y = y; } int get. X() { alternative implementation: • more tangled • redundant information • commonality is lost • consistent change is harder • harder to unplug return _x; } int get. Y() { return _y; } harder to maintain } 128

a good aspect (errors) class Document. Server { Doc convert(Doc d, Format f){ search

a good aspect (errors) class Document. Server { Doc convert(Doc d, Format f){ search locally and remotely } Doc. ID lookup. Doc (…) { aspect Document. Server. Errors { static catch (Remote. Exception e) Document. Server. lookup. Doc, Document. Server. store. Doc { pop up message offering to change the default server search locally and remotely } void store. Doc (…) { } static catch (Device. Error e) Document. Server. convert, Document. Server. scan. Doc { store locally, notify remotely } void scan. Doc (…) { pop up message offering to call the key operator get document from scanner } } “how to deal with errors in the document server” is a good abstraction on its own 129

a good aspect (errors) class Document. Server { Doc convert(Doc d, Format f){ try

a good aspect (errors) class Document. Server { Doc convert(Doc d, Format f){ try { search locally and remotely } catch (Device. Error e) { pop up message offering to call the key operator } } Doc. ID lookup. Doc (…) { try { search locally and remotely } catch (Remote. Exception e) { pop up message offering to change the default server } } void store. Doc (…) { try { store locally, notify remotely } catch (Remote. Exception 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 130

two questionable aspects do these 2 aspects improve the code? class Point { }

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

two questionable aspects do these 2 aspects improve the code? not really class Point

two questionable aspects do these 2 aspects improve the code? not really class Point { int _x = 0; int _y = 0; void set. X (int x) { _x = x; } void set. Y (int y) { _y = y; } int get. X() { return x; } int get. Y() { 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? 132

when to use aspects • is there a concern that: – cross-cuts the structure

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

… cross-cutting • a design concern that involves several classes or methods • implemented

… 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 134

… beneficial to separate out does it improve the code in real ways? –

… 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. write. Bytes 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 135

benefits of using AOP • good modularity, even in the presence of cross-cutting concerns

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 136

one-to-one association trick asp Some. Aspect asp = new Some. Aspect(); Some. Class obj

one-to-one association trick asp Some. Aspect asp = new Some. Aspect(); Some. Class obj = new Some. Class(); asp. add. Object(obj); obj make aspect know about class more than the other way aspect Some. Aspect { static after Some. Class(*) { Some. Aspect asp = new Some. Aspect(); asp. add. Object(this. Object); }. . . } Some. Class obj = new Some. Class(); // aspect instance is associated with obj 137

Part VI References, Related Work

Part VI References, Related Work

AOP and Aspect. J on the web • http: //www. parc. xerox. com/aop/aspectj 139

AOP and Aspect. J on the web • http: //www. parc. xerox. com/aop/aspectj 139

workshops • ECOOP’ 97 – http: //wwwtrese. cs. utwente. nl/aop-ecoop 97 • ICSE’ 98

workshops • ECOOP’ 97 – http: //wwwtrese. cs. utwente. nl/aop-ecoop 97 • ICSE’ 98 – http: //www. parc. xerox. com/aop/icse 98 • ECOOP’ 98 – http: //wwwtrese. cs. utwente. nl/aop-ecoop 98 140

AOP publications • in proceedings of ECOOP’ 97 • tech reports from PARC –

AOP publications • in proceedings of ECOOP’ 97 • tech reports from PARC – http: //www. parc. xerox. com/aop • workshop papers – see workshop pages 141

work we know best • subject-oriented programming @ IBM – [Ossher, Harrison] • adaptive

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