Programación Orientada por Aspectos Rubby Casallas Grupo de Construcción de Software Universidad de los Andes 1 Referencias http://eclipse.org/aspectj/ http://www.theserverside.com/events/video s/GregorKiczalesText/interview.jsp http://www.onjava.com/pub/a/onjava/2004/ 01/14/aop.html http://www.onjava.com/pub/a/onjava/2004/ 08/25/aoa.html 2 Agenda Motivación Conceptos Básicos El lenguaje AspectJ: Pointcuts Advices Aspects Introductions Ejemplos 3 Motivación Ejemplo: Se necesita saber cuanto tiempo se demora la ejecución de algunos métodos de una aplicación 4 Motivación public class BankAccount { public void withdraw (double amount) { long startTime = System.currentTimeMillis(); try { // Actual method body... } finally { long endTime = System.currentTimeMillis() – startTime; System.out.println("withdraw took: " + endTime); } } } 5 Motivación: Aspectos transversales Código similar en cada clase y cada método donde se quiera hacer la medición Si se necesitara un cambio en ese código tocaría cambiar en todas las clases donde está No se puede decir apagar o prender la ejecución de ese código 6 Motivación: Aspectos transversales Código similar en cada clase y cada método donde se quiera hacer la medición Si se necesitara un cambio en ese código tocaría cambiar en todas las clases donde está No se puede decir apagar o prender la ejecución de ese código El anterior es un ejemplo de un aspecto transversal a la aplicación. Es transversal porque la misma lógica se debe escribir en 7 varias partes de la aplicación. Motivación: variantes como aspectos En el contexto de una línea de producto: una variante opcional puede modelarse como un aspecto ver ejemplo en: Are Aspects useful for Managing Variability in Software Product Lines? A Case Study (2005). Alexander Nyßen , Shmuel Tyszberowicz , Thomas Weiler In Aspects and Software Product Lines: An Early Aspects Workshop at SPLC 2005 DOWNLOAD: http://trese.cs.utwente.nl/workshops/early-aspects 8 Conceptos Básicos Un aspecto es una preocupación común a varias clases de una aplicación El aspecto es “casi siempre” ortogonal a lo que la clase representa Por ejemplo: Logger, requerimientos no funcionales, testing y validación de contratos, etc. 9 Conceptos Básicos Un aspecto es una unidad funcional que permite expresar una estructura de código en diferentes partes de un programa Un aspecto está compuesto de dos partes: el punto de corte (point cut) que indica en qué partes del código se va a introducir un código definido el código del aspecto que típicamente se llama un advice 10 Conceptos Básicos Curso 0..* T ema 0..* Profesor 0.. * 0..* Material 0..* 0..* 0..* 0..* 0..* 11 Conceptos Básicos Problema: Incluir instrucciones en todos los métodos de todas las clases para hacer un logger! Al comienzo de la ejecución de cada método: logger.info("Entering: " + <nombremetodo>); 12 Conceptos Básicos Curso 0..* T ema 0..* Profesor 0.. * 0..* Material 0..* 0..* 0..* 0..* 0..* 13 Conceptos Básicos Curso 0..* Tema aspecto logger Operador “entretejer” (weaving) ) 0..* Profesor 0..* 0..* Material 0..* 0..* 0..* 0..* 0..* 14 Ejemplo: AspectJ aspect simpleLogger { pointcut tracedCall(): call(public * *(..)); before(): tracedCall() { logger.info("Entering: " + thisJoinPoint); } aspecto logger } 15 Ejemplo: AspectJ aspect simpleLogger { pointcut tracedCall(): call(public * *(..)); before(): tracedCall() { logger.info("Entering: " + thisJoinPoint); } } Puntos de la ejecución del programa 16 Ejemplo: AspectJ aspect simpleLogger { pointcut tracedCall(): call(public * *(..)); before(): tracedCall() { logger.info("Entering: " + thisJoinPoint); } } La instrucción del logger se va a ejecutar justo antes de alcanzar el punto tracedCall 17 Agenda Conceptos Básicos El lenguaje AspectJ: Join point Pointcuts Advices Aspects Introductions Ejemplos 18 Lo básico Un punto de unión (join point) es un punto bien definido en el flujo de ejecución de un programa. method & constructor call method & constructor execution field get & set exception handler execution static & dynamic initialization 19 Lo básico o1:C1 m() { ... // llamando a m2 o2.m2(x,y,z); .... } o2:C2 punto de unión (join point) m2() { ... //ejecutando m2 ... } 20 Lo básico o1:C1 m() { ... // llamando a m2 o2.m2(x,y,z); .... } punto de unión (join point) o2:C2 m2() { ... //ejecutando m2 ... } Al regresar del llamado también hay otro punto de unión 21 Lo básico Constructores del lenguaje: En un pointcut se define uno o más join points de un programa Un advice define el código que debe ser ejecutado cuando en el flujo de ejecución del programa se llegue a uno de los puntos definidos en un pointcut 22 AspectJ: Pointcut Puntos bien definidos en la ejecución del programa. Ejemplos: call(void Point.setX(int)) Cualquier llamado al método setX de los objetos de la clase Point call(void Point.setX(int)) || call(void Point.setY(int)) Cualquier llamado al método setX OR setY de los objetos de la clase Point 23 Pointcut Se le puede dar un nombre a un pointcut. Ejemplo: pointcut move(): call(void FigureElement.setXY(int,int)) || call(void call(void call(void call(void Point.setX(int)) || Point.setY(int)) || Line.setP1(Point)) || Line.setP2(Point)); El pointcut move crosscut varias clases. (namebased crosscutting) 24 Pointcut Más ejemplos: pointcut setter(): target(Point) && (call(void setX(int)) || call(void setY(int))); 25 Pointcut Property-based crosscutting Ejemplos: call(void Figure.make*(..)) call(public * Figure.* (..)) 26 Pointcut Property-based crosscutting Ejemplos: cflow(move()) Identifica todos los puntos que ocurren entre recibir llamados a métodos en move y retornar de estos llamados (ya sea que se salió con excepción o normalmente) 27 Pointcut Pointcut más ejemplos: pointcut ioHandler(): within(MyClass) && handler(IOException); Identifica cada punto donde una excepción de tipo IOException es manejada dentro del código definido en la clase MyClass 28 Agenda Conceptos Básicos El lenguaje AspectJ: Pointcuts Advices Aspects Introductions Ejemplos 29 Advice Un advice define código que debe ser ejecutado en jointpoints. Se puede indicar que el advice sea ejecutado ANTES, DESPUES o en vez de un joint point. Ejemplo: after(): move() { System.out.println("A figure element moved."); } 30 Advice aspect A { pointcut publicCall(): call(public Object *(..)); after() returning (Object o): publicCall() { System.out.println("Returned normally with " + o); } after() throwing (Exception e): publicCall() { System.out.println("Threw an exception: " + e); } after(): publicCall(){ System.out.println("Returned or threw an Exception"); } } 31 Pointcut y Advice Contexto de ejecución de los pointcuts Poincut básico: call(void FigureElement.setXY(int, int)) 32 Pointcut y Advice En un advice se quiere poder hacer referencia al objeto sobre el que se llamó el método setXY y a los argumentos con los que se invocó: setXY(FigureElement fe, int x, int y): call(void FigureElement.setXY(int, int)) && target(fe) && args(x, y); 33 Pointcut y Advice ... Y en el advice usamos el contexto: after(FigureElement fe, int x, int y): setXY(fe, x, y) { System.out.println(fe + " moved to (" + x + ", " + y + ")."); } 34 Advice: remplazar la ejecución aspect A { int around(): call(int C.foo()) { return 3; } } A retorna 3 en vez de lo que retornaba el método foo() de las instancias de la clase C 35 Agenda Conceptos Básicos El lenguaje AspectJ: Pointcuts Advices Aspects Introductions Ejemplos 36 Definición de Aspectos Un aspecto es una unidad modular de una implementación de un concern aspect SimpleTracing { pointcut tracedCall(): call(void FigureElement.draw(GraphicsContext)); before(): tracedCall() { System.out.println("Entering: " + thisJoinPoint); } } 37 Definición de Aspectos Un aspecto es una unidad modular de una implementación de un concern aspect SimpleTracing { pointcut tracedCall(): call(void FigureElement.draw(GraphicsContext)); before(): tracedCall() { System.out.println("Entering: " + thisJoinPoint); } } El efecto del código es imprimir, antes de que se invoque el método draw sobre cualquier objeto de la clase FigureElement, la línea: Entering: call(void FigureElement.draw(GraphicsContext)) 38 Definición de Aspectos Se define de manera similar como una clase y puede tener métodos, atributos, inicializadores. La implementación del concern se da en términos de pointcuts, advice e introductions. 39 Definición de Aspectos Por defecto, un aspecto es un singleton Sólo hay una instancia del aspecto. Los atributos son similares a los atributos estáticos de una clase. 40 Definición de Aspectos: Ejemplos aspect SetsInRotateCounting { int rotateCount = 0; int setCount = 0; before(): call(void Line.rotate(double)) { rotateCount++; } before(): call(void Point.set*(int)) && cflow(call(void Line.rotate(double))) { setCount++; } } 41 Definición de Aspectos: Ejemplos aspect SetsInRotateCounting { int rotateCount = 0; int setCount = 0; before(): call(void Line.rotate(double)) { rotateCount++; } before(): call(void Point.set*(int)) && cflow(call(void Line.rotate(double))) { setCount++; } Cuántas } veces fue invocado el método rotate de los objetos de la clase Line? Cuántas veces los métodos que comienzan con set de los objetos de la clase Point, Fueron llamados durante la ejecución de los métodos rotate de los objetos de la clase Line? 42 Definición de Aspectos: Ejemplos aspect PointBoundsChecking { pointcut setX(int x): (call(void FigureElement.setXY(int, int)) && args(x, *)) || (call(void Point.setX(int)) && args(x)); pointcut setY(int y): (call(void FigureElement.setXY(int, int)) && args(*, y)) || (call(void Point.setY(int)) && args(y)); before(int x): setX(x) { if ( x < MIN_X || x > MAX_X ) throw new IllegalArgumentException("x is out of bounds."); } before(int y): setY(y) { if ( y < MIN_Y || y > MAX_Y ) throw new IllegalArgumentException("y is out of bounds."); } } 43 Definición de Aspectos: Ejemplos static aspect RegistrationProtection { pointcut register(): call(void Registry.register(FigureElement)); pointcut canRegister(): withincode(static * FigureElement.make*(..)); before(): register() && !canRegister() { throw new IllegalAccessException("Illegal call " + thisJoinPoint); } } 44 Agenda Conceptos Básicos El lenguaje AspectJ: Pointcuts Advices Aspects Introductions Ejemplos 45 Introductions Las Introductions en AspectJ son la manera de modificar las clases y su jerarquía Permite adicionar nuevos métodos y nuevas clases alterando la relación de herencia entre las clases Los Advice operan dinámicamente Las Introductions operan estáticamente 46 Agenda Conceptos Básicos El lenguaje AspectJ: Pointcuts Advices Aspects Introductions Ejemplos 47 Ejemplos Tomados de: http://www.eclipse.org/aspectj/doc/released/pr ogguide/starting-development.html Tracing Profiling and Logging Pre- and Post-Conditions Contract Enforcement 48 Tracing Objetivo: imprimir un mensaje cada vez que se llama el método draw de un objeto de la clase FigureElement 49 aspect SimpleTracing { pointcut tracedCall(): call(void FigureElement.draw(..)); before(): tracedCall() { System.out.println("Entering: " + thisJoinPoint); } } 50 ... public static void main(String[] args) { Point p1 = new Point(); Point p2 = new Point(); Line line = new Line(p1, p2); line.draw(); } Entering: call(void FigureElement.draw(Point, Point)) 51 Profiling and Logging Objetivo: contestar las siguientes preguntas: Cuántas veces el método rotate es llamado sobre objetos de la clase Line? Cuántas veces los métodos de la clase Point que comienzan por set son llamados dentro de la ejecución de rotate? 52 aspect SetsInRotateCounting { int rotateCount = 0; int setCount = 0; before(): call(void Line.rotate(double)) { rotateCount++; } before(): call(void Point.set*(int)) && cflow(call(void Line.rotate(double))) { setCount++; } } 53 Pre- and Post-Conditions aspect PointBoundsChecking { pointcut setX(int x): call(void FigureElement.setXY(int, int)) && args(x, *)) || (call(void Point.setX(int)) && args(x)); pointcut setY(int y): (call(void FigureElement.setXY(int, int)) && args(*, y)) || (call(void Point.setY(int)) && args(y)); before(int x): setX(x) { if ( x < MIN_X || x > MAX_X ) throw new IllegalArgumentException("x is out of bounds."); } before(int y): setY(y) { if ( y < MIN_Y || y > MAX_Y ) throw new IllegalArgumentException("y is out of bounds."); } } 54 55 56 El compilador y el tejedor de AspectJ 1 2 3 Guide for the Developers of AspectJ's Compiler and Weaver, by Jim Hugunin http://aspectprogrammer.org/modules/sections/index.php?op=viewarticle&artid=11 [Ultima visita 6-oct-2005] 57