Aplicación de programación orientada a aspectos a patrones de ...

141
UN FRAMEWORK PARA LA VISUALIZACIÓN DE PATRONES DE DISEÑO DISTRIBUIDOS Y CONCURRENTES IMPLEMENTADOS CON PROGRAMACIÓN ORIENTADA A ASPECTOS: ACVF(ASPECTUAL COMPONENT VISUALIZATION FRAMEWORK) TESIS DE GRADO EN INGENIERIA INFORMATICA FACULTAD DE INGENIERIA UNIVERSIDAD DE BUENOS AIRES TESISTA: Sr. Diego M.S. ERDÖDY DIRECTORA: Prof. María FELDGEN Laboratorio de Sistemas Distribuidos Heterogéneos DICIEMBRE 2006

Transcript of Aplicación de programación orientada a aspectos a patrones de ...

Page 1: Aplicación de programación orientada a aspectos a patrones de ...

UN FRAMEWORK PARA LA VISUALIZACIÓN DE PATRONES DE

DISEÑO DISTRIBUIDOS Y CONCURRENTES IMPLEMENTADOS CON

PROGRAMACIÓN ORIENTADA A ASPECTOS:

ACVF(ASPECTUAL COMPONENT VISUALIZATION FRAMEWORK)

TESIS DE GRADO EN INGENIERIA INFORMATICA

FACULTAD DE INGENIERIA

UNIVERSIDAD DE BUENOS AIRES

TESISTA: Sr. Diego M.S. ERDÖDY

DIRECTORA: Prof. María FELDGEN

Laboratorio de Sistemas Distribuidos Heterogéneos

DICIEMBRE 2006

Page 2: Aplicación de programación orientada a aspectos a patrones de ...
Page 3: Aplicación de programación orientada a aspectos a patrones de ...

UN FRAMEWORK PARA LA VISUALIZACIÓN DE PATRONES DE

DISEÑO DISTRIBUIDOS Y CONCURRENTES IMPLEMENTADOS CON

PROGRAMACIÓN ORIENTADA A ASPECTOS:

ACVF(ASPECTUAL COMPONENT VISUALIZATION FRAMEWORK)

TESIS DE GRADO EN INGENIERIA INFORMATICA

Laboratorio de Sistemas Distribuidos Heterogéneos

FACULTAD DE INGENIERIA

UNIVERSIDAD DE BUENOS AIRES

Sr. Diego M.S. Erdody

Tesista

Prof. María Feldgen

Directora

DICIEMBRE 2006

Page 4: Aplicación de programación orientada a aspectos a patrones de ...
Page 5: Aplicación de programación orientada a aspectos a patrones de ...

Resumen

En este trabajo se hace un análisis exhaustivo de los beneficios y desventajas que

tiene una implementación de patrones de diseños distribuidos y concurrentes utilizando el

paradigma de programación orientada a aspectos. Junto con la implementación de las

aplicaciones de cada patrón de diseño, se modela y desarrolla el framework ACVF (bau-

tizado con el nombre de “Aspectual Component Visualization Framework”) para poder

integrar gráficamente los componentes de cada patrón y observar la interacción resultan-

te. Cada patrón se visualiza como una mini-aplicación. Los patrones a analizar se han

dividido en 3 categorías: Concurrentes, Manejo de Eventos y Fiabilidad. Como eje del

análisis, se analizarán las características de las implementaciones orientadas a aspectos

para determinar las mejoras en modularidad.

Palabras clave: programación orientada a aspectos, patrones de diseño distribuidos.

Abstract

This work consists of an exhaustive analysis about the benefits of applying aspect

oriented programming to distributed and concurrent design patterns. Along with the im-

plementation of the study cases for the different design pattern, a framework called

ACVF (Aspectual Component Visualization Framework) was designed and developed.

The framework is used to visually integrate the pattern components and study its interac-

tions. In this way, each pattern can be considered a mini-application. The design patterns

under study have been divided in three groups: Concurrent, Event Handling and Security.

The main objective of this work is to analyze the aspect oriented implementations and

establish its improvements in modularity.

Keywords: aspect oriented programming, distributed design patterns.

Page 6: Aplicación de programación orientada a aspectos a patrones de ...
Page 7: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy 1

Índice de Contenidos

Índice de Figuras ............................................................................................................... 1

1. Introducción ............................................................................................................... 3

1.1. Estructura del trabajo ...................................................................................... 4 1.1.1. Programación Orientada a Aspectos ........................................................... 5

1.1.2. Patrones de diseño distribuidos ................................................................... 5

1.1.3. Análisis de patrones .................................................................................... 5

1.1.4. Framework de Visualización ....................................................................... 5

1.1.5. Patrones de concurrencia ............................................................................. 5

1.1.6. Patrones de manejo de eventos.................................................................... 5

1.1.7. Patrones de comunicación distribuida ......................................................... 5

1.1.8. Patrones de seguridad y fiabilidad .............................................................. 5

1.1.9. Resultados y conclusiones ........................................................................... 5

1.1.10. Futuros trabajos ........................................................................................... 6

2. Programación Orientada a Objetos ........................................................................... 7

2.1. Fundamentos ..................................................................................................... 7

2.2. Problemas ........................................................................................................... 8

3. Programación Orientada a Aspectos ......................................................................... 8

3.1. Separación en intereses ..................................................................................... 8 3.1.1. Programación de patrones ......................................................................... 10

3.1.2. Filtros de composición .............................................................................. 11

3.1.3. Programación de meta-objetos .................................................................. 12

3.1.4. Conclusiones ............................................................................................. 13

3.2. Estructura de un aspecto ................................................................................ 13

3.3. Combinación de intereses ............................................................................... 14

3.4. Ventajas y Problemas de la AOP ................................................................... 16

3.5. AspectJ ............................................................................................................. 18 3.5.1. Sintaxis de un aspecto ............................................................................... 19

3.5.2. Definición de un pointcut .......................................................................... 20

3.5.3. Declaración de un advice .......................................................................... 25

3.5.4. Ejemplos .................................................................................................... 26

3.5.5. Declaraciones de miembros inter-tipo....................................................... 30

3.5.6. Declaraciones de derivación ...................................................................... 31

3.5.7. Otras declaraciones ................................................................................... 33

3.5.8. Intercalado ................................................................................................. 34

3.6. Comparación con otras implementaciones de AOP ..................................... 35 3.6.1. AspectWerkz ............................................................................................. 35

3.6.2. JBoss AOP ................................................................................................ 36

3.6.3. Spring AOP ............................................................................................... 37

Page 8: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

2 Diego M.S. Erdödy

3.6.4. CaesarJ ....................................................................................................... 38

3.6.5. Conclusiones .............................................................................................. 40

4. Patrones de diseño distribuidos ................................................................................ 45

4.1. Patrones de diseño ........................................................................................... 45 4.1.1. Beneficios y problemas de los patrones de diseño .................................... 45

4.1.2. Descripción de patrones de diseño ............................................................ 46

4.2. Uso en sistemas distribuidos y concurrentes ................................................. 47

5. Metodología de Análisis de patrones ....................................................................... 49

5.1. Objetivos ........................................................................................................... 49

5.2. Descripción de las características a analizar ................................................. 49 5.2.1. Reusabilidad .............................................................................................. 49

5.2.2. Transparencia de composición .................................................................. 49

5.2.3. Independencia ............................................................................................ 49

5.2.4. Localidad del código ................................................................................. 49

5.3. Notación UML .................................................................................................. 50 5.3.1. Aspect ........................................................................................................ 50

5.3.2. Pointcut ...................................................................................................... 51

5.3.3. Advice ........................................................................................................ 51

5.3.4. Introduction ............................................................................................... 52

5.3.5. Declare ....................................................................................................... 53

6. Framework de Visualización .................................................................................... 55

6.1. Introducción ..................................................................................................... 55

6.2. Frameworks ..................................................................................................... 55

6.3. Características de ACVF ................................................................................ 57 6.3.1. Orientación a Componentes ....................................................................... 57

6.3.2. Relaciones .................................................................................................. 60

6.3.3. Simulación ................................................................................................. 60

6.3.4. Vista de resumen........................................................................................ 61

6.4. Arquitectura y Diseño ..................................................................................... 62 6.4.1. GEF Framework ........................................................................................ 63

6.4.2. ACVF Framework ..................................................................................... 64

6.5. Otros Frameworks de Visualización .............................................................. 76

6.6. Conclusión ........................................................................................................ 77

7. Patrones de concurrencia y sincronización ............................................................. 79

7.1. Rendezvous ....................................................................................................... 79 7.1.1. Resumen .................................................................................................... 79

7.1.2. Otras denominaciones ................................................................................ 79

7.1.3. Problema .................................................................................................... 79

7.1.4. Solución ..................................................................................................... 79

7.1.5. Caso de estudio .......................................................................................... 79

Page 9: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy 3

7.1.6. Estructura .................................................................................................. 80

7.1.7. Estrategia de implementación Orientada a Aspectos ................................ 80

7.1.8. Análisis ...................................................................................................... 86

7.1.9. Componente gráfico .................................................................................. 87

7.2. Balking ............................................................................................................. 88 7.2.1. Resumen .................................................................................................... 88

7.2.2. Otras denominaciones ............................................................................... 88

7.2.3. Problema.................................................................................................... 88

7.2.4. Solución ..................................................................................................... 88

7.2.5. Caso de Estudio ......................................................................................... 89

7.2.6. Estructura .................................................................................................. 89

7.2.7. Estrategia de implementación Orientada a Aspectos ................................ 89

7.2.8. Análisis ...................................................................................................... 91

7.2.9. Componente gráfico .................................................................................. 92

7.3. Observador ...................................................................................................... 93 7.3.1. Resumen .................................................................................................... 93

7.3.2. Otras denominaciones ............................................................................... 93

7.3.3. Problema.................................................................................................... 93

7.3.4. Solución ..................................................................................................... 94

7.3.5. Caso de estudio ......................................................................................... 94

7.3.6. Estructura .................................................................................................. 94

7.3.7. Estrategia de implementación Orientada a Aspectos ................................ 95

7.3.8. Análisis ...................................................................................................... 98

7.3.9. Componente gráfico .................................................................................. 98

7.4. Optimistic Locking .......................................................................................... 99 7.4.1. Resumen .................................................................................................... 99

7.4.2. Otras denominaciones ............................................................................... 99

7.4.3. Problema.................................................................................................... 99

7.4.4. Solución ..................................................................................................... 99

7.4.5. Caso de estudio ....................................................................................... 100

7.4.6. Estructura ................................................................................................ 100

7.4.7. Estrategia de implementación Orientada a Aspectos .............................. 102

7.4.8. Análisis .................................................................................................... 105

7.4.9. Componente gráfico ................................................................................ 105

8. Patrones de manejo de eventos .............................................................................. 107

8.1. Reactor ........................................................................................................... 107 8.1.1. Resumen .................................................................................................. 107

8.1.2. Otras denominaciones ............................................................................. 107

8.1.3. Problema.................................................................................................. 107

8.1.4. Solución ................................................................................................... 108

8.1.5. Caso de estudio ....................................................................................... 108

8.1.6. Estructura ................................................................................................ 108

8.1.7. Estrategia de implementación Orientada a Aspectos .............................. 109

8.1.8. Análisis .................................................................................................... 112

Page 10: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

4 Diego M.S. Erdödy

8.1.9. Componente gráfico................................................................................. 113

9. Patrones de seguridad y fiabilidad ......................................................................... 115

9.1. Watchdog ........................................................................................................ 115 9.1.1. Resumen .................................................................................................. 115

9.1.2. Otras denominaciones .............................................................................. 115

9.1.3. Problema .................................................................................................. 115

9.1.4. Solución ................................................................................................... 115

9.1.5. Caso de estudio ........................................................................................ 115

9.1.6. Estructura ................................................................................................. 116

9.1.7. Estrategia de implementación Orientada a Aspectos............................... 117

9.1.8. Análisis .................................................................................................... 119

9.1.9. Componente gráfico................................................................................. 119

10. Resultados y Conclusiones ..................................................................................... 123

11. Futuros trabajos ...................................................................................................... 125

Referencias ...................................................................................................................... 127

Glosario ........................................................................................................................... 131

Page 11: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Índice de Figuras 1

Índice de Figuras

Figura 3-1: Mapeo entre espacio de intereses y espacio de implementación ...................... 9

Figura 3-2: Modelo Conceptual de Filtros de Composición ............................................. 12

Figura 3-3: Mecanismo de combinación de intereses ....................................................... 15

Figura 3-4: Impacto de cambios sobre sistemas convencionales y orientados a aspectos 16

Figura 3-5: Diagrama de estructura para los ejemplos de AspectJ ................................... 27

Figura 3-6: Captura de Eclipse mostrando el resultado de “declare error” ....................... 34

Figura 3-7: Mecanismo general de funcionamiento de AspectJ ....................................... 35

Figura 5-1: Ejemplo de notación UML para un Aspecto .................................................. 51

Figura 5-2: Ejemplo de notación UML para un Pointcut .................................................. 51

Figura 5-3: Ejemplo de notación UML para un Advice simple ........................................ 52

Figura 5-4: Ejemplo de notación UML para un Advice con argumentos ......................... 52

Figura 5-5: Ejemplo de notación UML para una Introducción ......................................... 53

Figura 5-6: Ejemplo de notación UML para una declaración de implementación ........... 54

Figura 6-1: Paleta de componentes ................................................................................... 57

Figura 6-2: Propiedades comunes a todos los componentes ............................................. 58

Figura 6-3: Propiedades particulares para el componente RoboArm ............................... 58

Figura 6-4: Ejemplo de un Componente ........................................................................... 59

Figura 6-5: Relaciones entre Componentes ...................................................................... 59

Figura 6-6: Ejemplo de un diagrama con varios componentes y relaciones ..................... 60

Figura 6-7: Vista de resumen ............................................................................................ 61

Figura 6-8: Capas de la arquitectura del Framework y sus características principales ..... 62

Figura 6-9: Interacción entre las distintas capas MVC del framework ............................. 63

Figura 6-10: Capa de Modelo de ACVF ........................................................................... 65

Figura 6-11: Compartimientos del componente ................................................................ 67

Figura 6-12: Capa de Vista de ACVF ............................................................................... 68

Figura 6-13: Capa de Controlador de ACVF .................................................................... 69

Figura 6-14: Capa de Componentes de ACVF .................................................................. 71

Figura 6-15: Diagrama de secuencia para el movimiento de un componente .................. 73

Figura 6-16: Diagrama de secuencia para el inicio de la simulación ................................ 75

Figura 6-17: Diagrama de estructura básico del framework de visualización JHotDraw . 76

Figura 7-1: Diagrama de Estructura del Patrón “Rendezvous” ......................................... 80

Figura 7-2: Núcleo de la estructura Orientada a Aspectos del Patrón “Rendezvous” ...... 81

Figura 7-3: Estructura de la aplicación del patrón “Rendezvous” .................................... 83

Figura 7-4: Estructura de la distintas implementaciones del Rendezvous ........................ 84

Figura 7-5: Estructura de la implementación remota del Rendezvous .............................. 85

Figura 7-6: Estructura completa para el Rendezvous........................................................ 86

Figura 7-7: Diagrama ACVF del caso de estudio para el patrón “Rendezvous” .............. 88

Figura 7-8: Diagrama de estructura del patrón “Balking” ................................................ 89

Figura 7-9: Estructura del Núcleo del patrón “Balking” ................................................... 90

Figura 7-10: Estructura de la aplicación del patrón “Balking” ......................................... 91

Figura 7-11: Diagrama ACVF del caso de estudio para el patrón “Balking” ................... 93

Figura 7-12: Diagrama de estructura del patrón “Observador” ........................................ 94

Figura 7-13: Estructura del Núcleo del patrón “Observador” ........................................... 95

Page 12: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

2 Diego M.S. Erdödy

Figura 7-14: Estructura de la aplicación del patrón “Observador” .................................... 97

Figura 7-15: Diagrama ACVF del caso de estudio del patrón “Watchdog”...................... 99

Figura 7-16: Interacción del patrón de concurrencia optimista ....................................... 101

Figura 7-17: Estructura del Núcleo del patrón “Optimistic Locking” ............................. 102

Figura 7-18: Estructura de la aplicación del patrón “Optimistic Locking” ..................... 104

Figura 7-19: Diagrama del patrón “Optimistic Locking” ................................................ 106

Figura 8-1: Estructura del patrón “Reactor” .................................................................... 108

Figura 8-2: Estructura del Núcleo (sector Event Handling) del patrón “Reactor” .......... 110

Figura 8-3: Estructura del Núcleo (sector Event Dispatching) del patrón “Reactor” ...... 111

Figura 8-4: Estructura de la aplicación concreta del patrón “Reactor” ........................... 112

Figura 8-5: Diagrama ACVF del caso de estudio para el patrón “Reactor” .................... 114

Figura 9-1: Diagrama de estructura del patrón “Watchdog” ........................................... 116

Figura 9-2: Estructura del Núcleo del patrón “Watchdog” ............................................. 117

Figura 9-3: Estructura de la aplicación del patrón “Watchdog” al caso de estudio ........ 118

Figura 9-4: Simulación de patrón Watchdog ................................................................... 120

Figura 9-5: Propiedades de los componentes gráficos Pacemaker y Watchdog ............. 120

Page 13: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Introducción 3

1. Introducción

En los últimos años, la programación orientada a objetos (POO) ha sido el modelo

de lenguaje de programación predominante dada su gran capacidad para abstraer la com-

plejidad de un problema determinado. La programación orientada a objetos clásica se

basa en el paradigma de que todo programa está compuesto de una colección de unidades

individuales llamadas objetos. Cada objeto es capaz de recibir mensajes, procesar infor-

mación o enviar mensajes a otros objetos. Si bien este modelo ha sido un gran paso en la

evolución de los lenguajes de programación, no es de ninguna forma perfecto.

Uno de los grandes problemas que posee, por ejemplo, es la incapacidad de abstraer

problemas que afectan a varios sectores del sistema en forma transversal. La programa-

ción orientada a aspectos (POA) provee una solución para abstraer código “transversal”,

que se encuentra distribuido en varias clases sin relación funcional con ellas (por ej. ins-

trucciones de seguridad o de bitácora). En vez de dispersar este código dentro de las cla-

ses, la POA permite abstraer estos fragmentos en módulos independientes, llamados as-

pectos, para luego poder aplicar este código dinámicamente cuando sea necesario. Esto se

logra definiendo lugares específicos (llamados puntos de corte o “pointcuts”) en el mode-

lo de objetos donde el código transversal debe ser aplicado. Este código es insertado de-

ntro de las clases tanto en tiempo de ejecución como en tiempo de compilación, depen-

diendo del framework POA utilizado y de la configuración. Esencialmente, la POA per-

mite agregar nueva funcionalidad dentro de los objetos sin la necesidad de que ellos ten-

gan conocimiento de dicha introducción.

Las implementaciones de POA más desarrolladas y activas que existen hasta este

momento son:

AspectJ [Ram 03] El proyecto fue iniciado por uno de los creadores de la POA, el

cual se basa en una extensión al lenguaje Java y se ha transformado en una de las

implementaciones más completas y genéricas de este paradigma1.

AspectWerks [AWerks 05] Es una herramienta concebida por el grupo de código

libre Codehaus.

JBossAOP [Bur 03] Es una extensión para el servidor de aplicaciones JBoss cuya

implementación se basa en interceptores configurables via XML.

SpringAOP [Rus 04] Es uno de los módulos del framework multipropósito

llamado Spring, el cual también está basado en interceptores configurables via

XML.

CaesarJ [Mez 03] Es la más reciente y prometedora implementación de AOP

basada en extensión al lenguaje Java, nacida en la Universidad de Darmstadt,

Alemania.

Dentro de la POO, los patrones de diseño son estructuras conocidas y definidas

como soluciones estándar para problemas comunes en el diseño de software. El objetivo

de estos patrones es disminuir los tiempos de diseño e implementación de los sistemas,

1 Patrón de pensamiento y conjunto de reglas que enmarcan y sirven de guía en una especialidad determi-

nada.

Page 14: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

4 Introducción Diego M.S. Erdödy

proveyendo soluciones prefabricadas que resultaron eficientes para determinado tipo de

problema. Es por este motivo, que mientras más independientes y fáciles de “ensamblar”

sean estas soluciones, mayor será el tiempo ahorrado, tanto en diseño e implementación

como en mantenimiento.

Dado que los beneficios de la introducción de la POA en los patrones de diseño tra-

dicionales, también llamados GoF (Gang of Four, debido a los autores libro [Gam 95])

han sido ampliamente verificados [Han 02], se demuestra, en este trabajo, que lo mismo

ocurre con patrones de diseño distribuidos y concurrentes, es decir, los que tratan con

problemas en donde intervienen más de una máquina o hilo de ejecución2.

El objetivo del trabajo es hacer un análisis exhaustivo de los beneficios y desven-

tajas que tiene una implementación de patrones de diseños distribuidos y concurrentes

utilizando el paradigma de programación orientada a aspectos. Junto con la implementa-

ción de las aplicaciones de cada patrón de diseño, se modela y desarrolla un framework

(bautizado con el nombre de “Component Visualization Framework”) para poder integrar

gráficamente los componentes de cada patrón y observar la interacción resultante.

Cada patrón se implementa simulando una aplicación clásica. Por ejemplo, el

“Rendezvous” se visualiza como una mini-aplicación donde un conjunto de brazos robó-

ticos esperan un evento para comenzar su tarea. Estas mini-aplicaciones pueden conectar-

se entre sí y con el ambiente. En la cadena así armada se puede evaluar el impacto de los

cambios según POO y POA. Los patrones a analizar se han dividido en 4 categorías:

Concurrentes, Distribuidos, Manejo de Eventos y Control o Tiempo Real [Dou 02]

[Sch 00]. Para cada uno se hace el desarrollo de una mini-aplicación del patrón usando

las mejores técnicas conocidas en POO y POA.

El framework está basado en una conjunción de caja blanca [Ras 03] para los com-

ponentes y caja negra para las utilidades asociadas al entorno. Se utiliza meta-

información como mecanismo de extensión de ciertos puntos definidos, denominados

“hotspots”. Las simulaciones pueden ser ejecutadas tanto en modo automático como en

modo manual o interactivo, permitiendo una visualización con mayor detalle. En el modo

manual, el usuario es el encargado de hacer que los componentes actúen sobre otros, pu-

diendo ejecutar acciones sobre cada componente y ver las reacciones en el resto. En el

modo automático, cada componente ejecuta un comportamiento predeterminado, que en

la mayoría de los casos se puede configurar a través de las propiedades del componente,

que se inicializa al comenzar la simulación.

1.1. Estructura del trabajo

Este trabajo consta de los siguientes capítulos:

2 Unidad de división de paralelización de procesamiento de un programa determinado.

Page 15: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Introducción 5

1.1.1. Programación Orientada a Aspectos

Breve introducción a la programación orientada a objetos (POO) y su evolución

hacia la programación orientada a aspectos (POA). Las definiciones de elementos de la

POA y una comparación de herramientas que implementan la POA. Por último se justifi-

ca la elección de la herramienta elegida, AspectJ.

1.1.2. Patrones de diseño distribuidos

Definición de un patrón de diseño. Características de los patrones de diseño distri-

buidos y sus distintos tipos.

1.1.3. Análisis de patrones

Especificación de características a analizar, metodología de trabajo y lenguaje de

modelado que se utiliza para la especificación de los diseños orientados a aspectos.

1.1.4. Framework de Visualización

Descripción de las características del framework desarrollado para la visualización

de los casos de estudio. Explicación de la arquitectura y diseño.

1.1.5. Patrones de concurrencia

Descripción y análisis de patrones de diseño de concurrencia.

1.1.6. Patrones de manejo de eventos

Descripción y análisis de patrones de diseño de manejo de eventos.

1.1.7. Patrones de comunicación distribuida

Descripción y análisis de patrones de diseño de comunicación distribuida.

1.1.8. Patrones de seguridad y fiabilidad

Descripción y análisis de patrones de diseño seguridad y fiabilidad.

1.1.9. Resultados y conclusiones

Análisis comparativo de los resultados de los distintos casos de estudio. Conclusio-

nes obtenidas aplicando distintas métricas.

Page 16: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

6 Introducción Diego M.S. Erdödy

1.1.10. Futuros trabajos

Lineamientos para profundización del presente trabajo y trabajos relacionados.

Page 17: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Objetos 7

2. Programación Orientada a Objetos

2.1. Fundamentos

La programación orientada a objetos consiste básicamente en descomponer un pro-

blema en un grupo de objetos que interactúan entre sí por medio de mensajes. Cada obje-

to puede contener atributos para almacenar su estado interno, el cual puede ser alterado a

través de los mensajes. Los mensajes, también llamados métodos, son subrutinas que se

ejecutan en el ámbito de un objeto en particular. Cada objeto debe estar asociado a un

tipo de objeto, llamado clase. La clase es la que contiene la definición de los métodos que

los objetos de su tipo poseerán así como también los atributos que contendrán.

Una vez definido los elementos fundamentales, se enumeran los conceptos princi-

pales presentes dentro de este paradigma:

Abstracción: Al igual que en matemáticas, es el mecanismo por el cual se identi-

fican características comunes en un cierto conjunto de elementos. Por este meca-

nismo, se pueden establecer formas homogéneas de ver a un objeto desde el exte-

rior, llamadas interfaces. La abstracción permite independizar dichas interfaces,

de la forma de implementar el comportamiento semántico definido por ellas.

Encapsulación: Asegura que los atributos internos de un objeto, también llama-

dos privados, no puedan ser accedidos desde afuera, dando así la seguridad de que

futuros cambios sobre ellos no impactarán en el resto de los objetos. Para acceder

a dichos atributos se deberán proveer maneras específicas y controladas como, por

ejemplo, métodos públicos.

Herencia: Los elementos de una clase (métodos y atributos) pueden ser heredados

por otra clase. Esto significa que la clase hija (la que hereda) contendrá implíci-

tamente todos los elementos de la clase padre. Se dice que la clase hija “extiende”

o “especializa” a la clase padre, ya que es un mecanismo por el cual se incorporan

nuevos elementos a partir de los ya existentes.

Polimorfismo: En su definición clásica, consiste en poder utilizar la misma defi-

nición con distintos tipos de datos indistintamente. Una de las técnicas de poli-

morfismo que provee la POO es la posibilidad de contar con distintas implemen-

taciones del mismo método dentro de una jerarquía de clases. Dicha técnica perte-

nece al grupo del polimorfismo dinámico dado que la decisión, de que tipo de

comportamiento aplicar, se realiza en tiempo de ejecución. Otra de las formas de

polimorfismo presentes en la POO es el mecanismo denominado “sobrecarga”

que es la redefinición de un mismo método con distintos tipos de argumentos. De

esta forma se logra un comportamiento acorde a cada tipo de objeto. Esta última

técnica pertenece al grupo del polimorfismo “ad-hoc”, ya que la cantidad de va-

riantes de tipos argumentos debe ser explícitamente declarada en tiempo de com-

pilación (un método distinto por cada tipo).

Page 18: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

8 Programación Orientada a Aspectos Diego M.S. Erdödy

2.2. Problemas

Uno de los principales problemas de la POO, es la incapacidad de abstraer eficien-

temente la funcionalidad que se repite en distintos módulos que no estén relacionados en

la jerarquía de clases. Uno de los ejemplos más claros de este inconveniente son las ins-

trucciones de bitácora y de traza de ejecución. Si en un sistema se quisiera mostrar un

mensaje cada vez que comienza la ejecución de un método, se tendría que agregar dicha

instrucción en todos los métodos del sistema. Supongamos, que se incorpora una instruc-

ción en cada uno de los métodos del sistema que muestre el nombre del método al cual se

está invocando. Si en el futuro, se decide que es necesario ver además, los valores de los

argumentos con los cuales fue llamado cada método, se necesitaría hacer una modifica-

ción en cada uno de los lugares donde fue aplicada la instrucción originalmente. Dicha

modificación implica un esfuerzo lineal en comparación con el tamaño del sistema. To-

dos estos problemas surgen de la falta de mecanismos del paradigma para la abstracción

de comportamiento transversal.

3. Programación Orientada a Aspectos

3.1. Separación en intereses

Es posible ver un sistema como la combinación de múltiples intereses. Se define in-

terés como cualquier aspecto3 que le concierne a un programa, ya sea relacionado a la

infraestructura, al negocio, a los requerimientos o a las estructuras de diseño. Nótese que

la definición es genérica por naturaleza. Ejemplos típicos de intereses son lógica de nego-

cio, performance, bitácora, persistencia, autenticación, restricciones de tiempo real y tole-

rancia a fallos.

Los intereses se pueden dividir en locales y transversales. Los intereses locales son

los que sólo le conciernen a un componente (o grupo reducido) en particular. El ejemplo

clásico de este tipo de intereses es la lógica de negocio. Los intereses transversales en

cambio, son aquellos que involucran a más de un componente a la vez. Un ejemplo es el

logging (o bitácora de ejecución) de una aplicación. La mayoría de los componentes, si

no todos, deben preocuparse por tener un registro persistente de su ejecución.

Los intereses se pueden ver en dos planos o espacios distintos, el conceptual y el de

la implementación. El primero es el espacio lógico en el cual se identifica el interés. El

segundo es el espacio físico en el cual se traduce el interés conceptual a una implementa-

ción específica, en un leguaje de programación determinado. El problema principal con el

mapeo entre ambos espacios utilizando lenguajes orientados a objetos, es que el espacio

conceptual posee múltiples dimensiones, una dimensión por cada interés existente. En

cambio, el espacio de implementación presenta una naturaleza “unidimensional” inheren-

te. En el caso de la POO, el espacio de implementación se limita a un flujo lineal de tras-

paso de mensajes entre objetos. Por esta razón, el mapeo produce una pérdida de infor-

mación valiosa. En la siguiente figura se puede apreciar gráficamente este efecto:

3 En su acepción tradicional, no confundir con el aspecto definido más adelante

Page 19: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 9

Figura 3-1: Mapeo entre espacio de intereses y espacio de implementación

En el espacio de intereses, se observan tres intereses ortogonales que generan dicho

espacio. Al llevar estos intereses a un espacio de implementación, que como se indicó,

tiene una naturaleza unidimensional, éstos se deben mapear a un único eje de acción. Este

proceso conlleva una pérdida de identidad de cada interés.

El proceso de conversión de un espacio multidimensional a un espacio unidimen-

sional produce problemas y efectos colaterales. Los principales síntomas de este fenóme-

no, aplicados al caso de logging, son los siguientes:

Mezcla de código: La implementación del interés principal de un módulo contiene

en muchos casos, la implementación de otros intereses transversales intercalada.

Esto dificulta la lectura y el mantenimiento del mismo. Cada elemento que quiera

ser registrado en la bitácora, debe agregar instrucciones especiales, las cuales es-

tarán mezcladas con las que implementan el interés especial.

Dispersión de código: Es el caso contrario al anterior. La implementación del

comportamiento de un interés transversal se encuentra distribuido en distintos

módulos. Por este motivo resulta muy difícil identificar el interés. Para saber qué

componentes están siendo registrados en la bitácora, es necesario revisar todo el

sistema para rastrear en dónde se están utilizando tales instrucciones.

Repetición de código: Una consecuencia del problema anterior es que el código

disperso, frecuentemente se encuentra repetido. Las mismas instrucciones de log-

ging aparecerán una y otra vez en cada módulo que precise ser registrado.

Y las principales desventajas son:

Problemas al analizar la implementación: Al implementar múltiples intereses se

hace cada vez más difícil distinguir cada uno de los intereses en su implementa-

ción. Este es un problema exponencial, dado que cada interés transversal incorpo-

rado al sistema, potencialmente dificulta cada uno de los intereses existentes.

Baja productividad: Al momento de implementar un módulo, es necesario pre-

ocuparse por la correcta implementación del interés principal así como también de

los intereses transversales que afectan al módulo. Evidentemente preocuparse por

Espacio de ImplementaciónEspacio de intereses

Mapeo

Aut

entic

ación

Logging

gic

a d

e

Ne

go

cio

Lógica de

NegocioAutenticación

Logging

Page 20: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

10 Programación Orientada a Aspectos Diego M.S. Erdödy

un solo interés a la vez resultaría más sencillo y reduciría el riesgo de errores, lo

cual aumentaría considerablemente la productividad.

Imposibilidad de reutilización: Dado que cada módulo contiene la implementa-

ción de los intereses transversales, otros sistemas que tengan distintos requeri-

mientos de sistema, no podrán reutilizar la implementación del módulo.

Mantenimiento difícil: En caso de necesidad de cambios en los requerimientos

del sistema, los cambios a nivel de implementación tienen un costo, en el mejor

de los casos, de orden lineal al tamaño del sistema. Esto se debe a que la modifi-

cación se debe hacer en todos los lugares en donde se encuentre intercalada la im-

plementación del interés. Por ejemplo, para el caso del logging, si durante la evo-

lución de un sistema se determina que aparte de registrar un mensaje, es necesario

identificar al usuario involucrado, cada una de las llamadas que el sistema realiza

al componente de log, tendrán que ser modificadas. Mientras más grande sea el

sistema, más llamadas habrá al componente de log y de la misma forma aumen-

tará la cantidad de cambios necesarios.

Evolución compleja: Incorporar nuevos intereses es también costoso y aumenta

con la cantidad de intereses transversales que existan. Siguiendo con el ejemplo

de logging, si una aplicación inicialmente no contempló la necesidad de registrar

su ejecución, el costo de la incorporación de dicho interés será proporcional al

tamaño del sistema.

Es por todas estas razones que se debe encontrar un método que permita implemen-

tar cada interés en forma independiente. De tal forma que cualquier modificación en un

interés no afecte al resto de los intereses, pero los intereses requieren interactuar entre

ellos. Esto requiere que existan mecanismos que permitan la interacción entre ellos sin

perder la independencia.

Existen varios métodos para lograr el objetivo planteado [Hur 95]. Estos métodos se

describen y analizan en las siguientes secciones.

3.1.1. Programación de patrones

Lieberherr [Lie 96] describe la programación adaptativa basada en patrones de

código. Los patrones de código, que no son patrones de diseño, se pueden dividir en dife-

rentes categorías:

Patrones de propagación: Consiste en identificar subgrafos dentro de la estruc-

tura general de objetos, que están ligados a una operación en común. De esta for-

ma, el acceso a la información de esa operación se hará de forma tal que no sea

necesario conocer el camino. Sólo es necesario saber a qué operación pertenece.

Por ejemplo, sea la estructura simple de tres clases: Alumno, Clase (que posee re-

ferencias a un conjunto de alumnos) y Escuela (que se asocia a un conjunto de

clases). En la POO, para acceder a un alumno a partir de una Escuela se debe co-

nocer el camino, es decir a través de la clase “Clase”. Si se modifica la estructura

de objetos, y se agrega un nivel “Departamento” entre Escuela y Clase, debe mo-

dificarse la estrategia de acceso. Los patrones de propagación tratan este tipo de

Page 21: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 11

problemas y permiten hacer llamadas tales como “a partir de una Escuela, obtener

el Alumno tal”, es decir, abstraen el camino dentro de la estructura.

Patrones de transporte: El objetivo de estos patrones es la abstracción del con-

cepto de parametrización. Se utilizan dentro de los patrones de propagación para

enviar los parámetros entre los subgrafos.

Patrones de sincronización: Define esquemas de sincronización entre los objetos

en aplicaciones concurrentes.

Este conjunto de patrones debe ser complementado con una estructura de clases so-

bre la cual aplicarlo. Un compilador de patrones tomará tanto la estructura de clases como

los patrones y generará un programa orientado a objetos.

Cada categoría trata con un conjunto de problemas distintos y puede considerarse

un interés de alto nivel dentro de una aplicación.

3.1.2. Filtros de composición

El modelo de filtros de composición desarrollado por Bergmans y Aksit [Aks 92]

[Ber 94] en la Universidad de Twente, es una extensión del modelo convencional orien-

tado a objetos. Este modelo fue aplicado a un sistema de pagos de subsidios médicos por

invalidez implementada en el lenguaje Sina [Ber 01].

El siguiente diagrama representa el modelo de un filtro de composición.

Mensajes

Recibidos

Mensajes

Enviados

Filtros de entrada

Filtros de salida

Métodos y

Condiciones

Variables de

Instancia

Interface

Implementación

(objeto núcleo)

Objetos

internos

Objetos

externos

Page 22: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

12 Programación Orientada a Aspectos Diego M.S. Erdödy

Figura 3-2: Modelo Conceptual de Filtros de Composición

El núcleo o implementación del objeto representa el comportamiento y sólo puede

ser modificado a través del procesamiento de los mensajes de entrada y salida. Esto se

logra a través de la capa externa del núcleo del objeto, llamada interface. La interface

contiene los elementos más importantes que son los filtros, tanto de entrada como de sali-

da. Los filtros son los encargados de combinar el comportamiento del objeto con otros

objetos. Los otros objetos pueden ser tanto internos como externos.

El objeto núcleo contiene variables de instancia que representarán el estado del

componente y en el límite con la interface se encuentran los métodos y las condiciones.

Los métodos pueden ser invocados por mensajes, siempre y cuando no sean rechazados

por alguno de los filtros de entrada. Las condiciones son simplemente expresiones boo-

leanas que se refieren al estado del objeto y son usadas por los filtros en el momento de

procesar los mensajes.

Los filtros, que son los encargados de combinar los intereses, aceptando, rechazan-

do y modificando los mensajes, tienen un orden determinístico de aplicación formando

filtros en cascada. La composición de filtros en cascada posee un comportamiento boo-

leano del tipo AND mientras que los distintos elementos dentro de un mismo filtro pro-

veen el comportamiento OR. Esta propiedad hace que el modelo sea apropiado para re-

presentar intereses que se deben aplicar en un orden especificado.

3.1.3. Programación de meta-objetos

Un “meta-objeto” es una entidad que puede crear o modificar a otros objetos. Los

protocolos de meta-objetos (MOP) son interfaces definidas en el lenguaje de programa-

ción que posibilita al usuario, cierto grado de libertad, para modificar el comportamiento

y la implementación del lenguaje. De esta forma los objetos que se encuentran en el nivel

primario, por lo general encargados de los algoritmos fundamentales de un programa,

pueden ser modificados por meta-objetos con el objetivo de adaptarlos a requerimientos

específicos de un entorno determinado.

Los protocolos de meta-objetos [Kic 92] se pueden clasificar en meta-objetos en

tiempo de ejecución y meta-objetos en tiempo de compilación. Uno de los lenguajes más

representativos del primer grupo es el Common Lisp Object System [Kic 91], el cual

permite alterar mecanismos del lenguaje LISP tales como la herencia, instanciación de

objetos o procesamiento de mensajes, en tiempo de ejecución.

Sullivan [Sul 01] enumera los siguientes beneficios de un MOP en tiempo de ejecu-

ción:

Se permite la modificación de objetos en el momento de cargar las clases, agre-

gando un nivel de extensibilidad mayor.

Los meta-objetos pueden utilizar valores de tiempo de ejecución para tomar las

decisiones de cómo modificar los objetos.

Page 23: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 13

Los meta-objetos pueden ser modificados en tiempo de ejecución. Esto tiene co-

mo corolario que el meta-comportamiento puede ser removido también en tiempo

de ejecución.

Además muestra cómo un lenguaje reflexivo como Java no cumple con los reque-

rimientos de un MOP ya que si bien permite obtener información de otros objetos, el ac-

ceso que brinda es de “sólo lectura”, es decir, no admite que los objetos sean modifica-

dos. Kojarski [Koj 03], demuestra que todas las funciones que brinda la biblioteca de

reflexión de Java (CJR) se pueden realizar con un lenguaje basado en MOP como As-

pectJ, incluso con mejoras en la performance. Desde luego que hay una decisión de com-

promiso en dicho beneficio. Se requiere un aumento en la memoria necesaria ya que la

meta-información es almacenada completamente en un caché. Para minimizar este pro-

blema, se puede reducir el conjunto de clases que van a ser almacenadas. Esto se puede

lograr indicando explícitamente el conjunto de clases que podrá ser accedida reflexiva-

mente. Esto no es posible con la CJR dado que la reflexión es implícita para todas las

clases.

3.1.4. Conclusiones

El primer modelo, programación de patrones, tiene una gran limitación en la canti-

dad de intereses que puede representar dado que fue diseñado para tratar problemas es-

pecíficos como la abstracción de caminos de acceso a ciertos elementos, pasaje de pará-

metros y sincronización general. Para la implementación de los patrones que se analiza-

ron en este trabajo, no es conveniente dada la heterogeneidad de los mismos.

En el segundo modelo, filtros de composición, la única forma de combinar los in-

tereses es por medio del procesamiento de los mensajes de entrada y salida. Otra de las

desventajas para la implementación de los patrones de este trabajo es que no permite la

modificación en la estructura de los objetos, limitando considerablemente las formas de

inserción del comportamiento de los nuevos intereses.

Se ha elegido un modelo similar a la programación de meta-objetos para la imple-

mentación de los patrones de diseño de este trabajo, dada la gran generalidad y flexibili-

dad del modelo.

3.2. Estructura de un aspecto

Los términos “aspecto” y “AOP” fueron definidos por Gregor Kiczales en 1997

[Kic 97]. Estructuralmente, un aspecto es una clase con ciertos elementos adicionales que

lo caracterizan. Estos elementos le dan la expresividad que necesita para poder abstraer

intereses transversales. Los elementos son:

Join point: es un punto específico dentro de la estructura o ejecución de un pro-

grama. Puede ser, por ejemplo, la ejecución de un método, la creación de un obje-

to o la modificación en el valor de un atributo. Mientras más tipos de join points

Page 24: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

14 Programación Orientada a Aspectos Diego M.S. Erdödy

se puedan especificar con una herramienta AOP, más casos se podrán representar

en un aspecto y por ende más potente será dicha herramienta.

Pointcut: es una agrupación lógica de un grupo de join points dentro de un aspec-

to.

Advice: es un fragmento de código equivalente al contenido de un método, en

donde se especifica el comportamiento transversal que contendrá el aspecto. Este

comportamiento va acompañado de la indicación del pointcut donde debe ser in-

sertado y la forma de insertarlo (antes, después o en reemplazo del pointcut).

Declaraciones de miembros inter-clase: son declaraciones que permiten agregar

métodos o atributos a interfaces o clases ya existentes. También conocido como

introducción.

Otras declaraciones: son declaraciones de distintos tipos cuya disponibilidad de-

penden del lenguaje orientado a aspectos que se utilice. Por ejemplo para el caso

de AspectJ se cuenta con los siguientes tipos:

o parents: que especifica que una clase determinada herede de otra en parti-

cular.

o implements: que agrega la implementación de una interface a una clase

dada

o soft: que elimina la obligación de capturar las excepciones.

o warning: que genera un aviso en tiempo de compilación cuando se cumple

la condición requerida.

o error: que genera un error en tiempo de compilación cuando se cumple la

condición requerida.

o precedence: que especifica el orden de aplicación de los distintos aspectos

para eliminar conflictos de precedencia de aspectos.

Matemáticamente, los aspectos constituyen una extensión de segundo orden en el

paradigma de programación, es decir que mientras los paradigmas conocidos utilizan

simples funciones, mensajes o equivalentes, la AOP permite razonar en términos de con-

juntos de dichas entidades a través del uso de los puntos de corte. De esta forma se puede

ver a la AOP como una poderosa extensión lógica más que como un nuevo paradigma.

3.3. Combinación de intereses

La combinación de intereses es el mecanismo por el cual distintos elementos de los

aspectos se insertan dentro de las clases. Existen dos grandes grupos de elementos a in-

sertar, los estructurales y los advices. Los estructurales implican cambios en la estructura

de la clase, ya sea agregando la implementación de nuevas interfaces, nuevos atributos o

nuevos métodos. En el segundo caso, la inserción es más compleja ya que depende de la

incorporación de los advices en los distintos pointcuts que puede requerir el cumplimien-

to de distintas condiciones.

Las formas clásicas de llevar a cabo la combinación de intereses son:

Preprocesador de código fuente.

Postprocesador que modifique el código binario ya compilado.

Page 25: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 15

Compilador preparado para AOP que genere el código binario intercalado.

Intercalado en tiempo de carga de las clases (por ej., en el caso de Java, se interca-

la cada advice a medida que se cargan las clases en la máquina virtual (JVM))

Intercalado en tiempo de ejecución (capturar cada join point en tiempo de ejecu-

ción y ejecutar todos los advices correspondientes).

Las primeras dos opciones complican la tarea del programador mientras que las dos

últimas pueden afectar la performance del sistema. La última opción necesita de un en-

torno de ejecución especial para que sea factible (en el caso de Java esto implica una

JVM a medida).

Se resume el mecanismo de la combinación de intereses en el siguiente gráfico:

Figura 3-3: Mecanismo de combinación de intereses

Todas estas soluciones implican modificaciones del código compilado en algún

punto. Esto quiere decir que el código binario resultante es distinto al generado por un

compilador tradicional. Esto es un grave problema al momento de depurar código con las

herramientas tradicionales.

Cohen y Gil [Coh 04] proponen una estrategia de combinación denominada “de-

ploy-time weaving”. La diferencia principal con los métodos anteriores es que en vez de

modificar el código compilado inyectándole los aspectos, estos son introducidos a través

de clases que extienden las clases ya existentes y sobrescriben sus métodos. La ventaja de

este mecanismo es que el código original queda intacto y por ende se pueden utilizar

herramientas de depuración tradicionales sin mayor inconveniente. También se observa

como ventaja la compatibilidad con el código tradicional ya que los aspectos pasan a ser

objetos que extienden otros objetos. Como desventaja se puede mencionar el hecho de

que la creación de nuevas capas en la jerarquía de herencia reduce la eficiencia final.

Implementación de

intereses principales

(objetos)

Implementación de intereses

transversales (aspectos)

+ reglas de intercalado

Sistema

Compilador e Intercalador

AOP

Page 26: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

16 Programación Orientada a Aspectos Diego M.S. Erdödy

3.4. Ventajas y Problemas de la AOP

La implementación de cada interés en forma independiente, facilita el mantenimien-

to del sistema y la introducción de modificaciones o nuevas funcionalidades. Esto se pue-

de ver en el siguiente diagrama:

Figura 3-4: Impacto de cambios sobre sistemas convencionales y orientados a aspectos

Por un lado se muestra que con en el caso de la POO, una modificación sobre el

código concerniente a un interés transversal, impacta en diversos lugares del sistema. Es

decir que los mismos cambios se tienen que repetir más de una vez. En cambio, en el caso

de la POA, al poder modularizar el código asociado al interés transversal, las modifica-

ciones que se le deban aplicar siempre estarán centralizadas en un único lugar físico.

La depuración de código es uno de los grandes problemas de la AOP. El código

fuente transversal en la AOP es independiente mientras que una vez compilado y en

tiempo de ejecución esto no es cierto debido al intercalado. Una solución a este problema

Caso con la POACaso con la POO

Sistema original

Sistema original

+ interes modificado

Sistema original

+ interés transversal

Sistema original

Sistema original

Sistema original

Implementación del

interés transversal

(aspecto)

Aspecto modificado

Page 27: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 17

es utilizar herramientas especializadas de depuración para AOP, que puedan relacionar el

código fuente con el código binario correspondiente.

Existe otro problema asociado a la captura de pointcuts con comodines. Los point-

cuts con comodines representan diversos puntos (llamada a métodos, asignación de atri-

butos, etc.) dentro del sistema, agrupados por una convención de nombres que contiene

caracteres especiales denominados comodines. El comodín “*”, por ejemplo, representa

un grupo de caracteres. Si se usa por ejemplo, un esquema de pointcuts basado en el

nombre de los métodos (como en AspectJ 1.2) se corre el riesgo que en futuras modifica-

ciones, se cambie el nombre de uno de los métodos referenciados por el pointcut. Esto

produciría el funcionamiento incorrecto del aspecto. Esto se puede controlar usando

estándares de nombres rígidos pero aún así no se elimina el problema completamente.

Otra alternativa es contar con herramientas de desarrollo que permitan visualizar fácil-

mente la integración entre clases y aspectos de forma tal de poder contar con controles

visuales al momento de hacer cambios. Sin embargo, la solución más prometedora a di-

cho inconveniente es la introducción de información adicional (o meta-información) a la

especificación de las clases, ya sea métodos o atributos. De esta forma se tiene un control

certero y flexible al mismo tiempo.

La forma de especificar esta meta-información se analizará más adelante, pero para

ejemplificar el problema, se tomará el ejemplo de una clase a la que se le debe aplicar

políticas de seguridad. Para ello se define que para llamar a cualquier método cuyo nom-

bre empiece con “get”, se deben poseer privilegios especiales. Si con la evolución de la

clase, alguien que no tenga conocimiento de la política de seguridad, intenta agregar otro

método bajo la misma convención (una práctica habitual en Java), se verá forzado a hacer

entrar dicho método a la política de seguridad, aunque no sea el comportamiento espera-

do. Para solucionar el problema, se puede agregar meta-información a los métodos que

los categorice según su funcionalidad, por ejemplo, “Privilegiado”. De esta forma, los

nuevos métodos no se verán afectados.

La meta-información puede estructurarse en distintas formas. Una de las más com-

plejas, actualmente en desarrollo, es la estructura semántica. En el framework SetPoint

[Alt 04], se hace uso de un lenguaje de ontologías llamado OWL [OWL 06] (Ontology

Web Language), aumentando considerablemente el grado de expresividad de la meta-

información. Por ejemplo, se pueden vincular pointcuts con expresiones del tipo “todos

los objetos que representen una manufactura y cuyo costo sea mayor a 100”.

Como indica Roger Alexander [Ale 02], existe un peligro inherente a la abstracción

transversal que implica la orientación a aspectos. Este peligro se asocia a la carga cogni-

tiva que se adiciona con la aplicación de nuevos intereses transversales. A esto se lo de-

nomina “distancia cognitiva” [Kru 92] entre la abstracción base (la implementación antes

de aplicar funcionalidad transversal) y la que resulta luego del intercalado con intereses

transversales. Esta distancia cognitiva lleva a que invariantes asumidas por el autor de la

implementación original, ya no se cumplan al intercalar el o los intereses transversales.

Page 28: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

18 Programación Orientada a Aspectos Diego M.S. Erdödy

Otro problema que ha sido identificado dentro de la AOP, se denomina “pointcuts

frágiles”. El problema se presenta al efectuar una reestructuración de código en un siste-

ma que ha sido implementado en AOP. Los cambios introducidos por la reestructuración

pueden afectar la cantidad de joinpoints representados por cada pointcut y en última ins-

tancia hacer que el comportamiento no sea el esperado. Este problema ha sido analizado

por Koppen y Stoerzer [Kop 04] y han propuesto una herramienta para minimizar sus

efectos. La herramienta básicamente calcula la diferencia en número de joinpoints repre-

sentados por cada pointcut antes y después de una reestructuración, permitiendo visuali-

zar los resultados para poder tomar medidas correctivas.

3.5. AspectJ

AspectJ [Asj 05] es una implementación en Java de AOP creada en los laboratorios

de XEROX Parc y que gradualmente se convirtió en el lenguaje orientado a aspectos más

popular. El proyecto ha sido integrado a la fundación Eclipse en diciembre de 2002 y

conjuntamente se le ha dado soporte dentro del entorno de desarrollo Eclipse (proyecto

llamado AspectJ Development Tools [AJDT 06]). Este proyecto provee un aporte impor-

tante hacia el mejor entendimiento de la interacción entre los aspectos y la base de código

existente, a través de ayudas gráficas y atajos.

AspectJ está diseñado como una extensión a la especificación del lenguaje Java. De

la misma forma que Java, se trata de un lenguaje multipropósito, es decir, no está ligado a

un tipo de dominio en particular. Es una implementación diseñada para ser compatible en

varios niveles [Kic 01]:

Compatibilidad con versiones anteriores: todos los programas escritos en

Java, son también programas válidos en AspectJ.

Compatibilidad de plataforma: todos los programas AspectJ corren en

máquinas virtuales de Java (JVM) tradicionales, sin ninguna modificación

adicional.

Compatibilidad de herramientas: las herramientas de desarrollo de Java

son extensibles de una forma natural para poder trabajar con programas As-

pectJ.

Compatibilidad para el programador: para el programador, AspectJ es

una extensión natural del lenguaje Java.

Las dos formas de implementación transversal que brinda AspectJ son:

Implementación transversal dinámica: permite definir comportamiento

adicional que se ejecutará en puntos específicos dentro del programa.

Implementación transversal estática: permite modificar la estructura está-

tica del programa, agregando superclases o implementaciones de interfaces.

La implementación transversal dinámica se logra a partir de los join points, mien-

tras que la implementación transversal estática se logra con las declaraciones de miem-

bros inter-clase y las declaraciones de extensión e implementación. En todos estos

Page 29: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 19

casos la modificación de la estructura de clases se realiza desde un elemento localizado y

modular como lo es un aspecto.

3.5.1. Sintaxis de un aspecto

En AspectJ, un aspecto se define de manera similar a una clase y tiene la siguiente

sintaxis:

La palabra reservada “class” que define una clase en Java es reemplazada por “as-

pect” para el caso de un aspecto en AspectJ. De la misma forma que una clase, un aspecto

debe tener un identificador único dentro de su paquete, que le dará el nombre al aspecto.

Los modificadores permitidos para un aspecto son similares a los que puede prece-

der a una clase:

public: el aspecto es expuesto públicamente y por ende puede ser accedido

desde cualquier punto en la jerarquía de paquetes.

default o package: el modificador por defecto indica que sólo es posible

acceder al aspecto dentro del paquete donde fue definido.

final: al igual que el modificador de clases, indica que el aspecto no puede

ser extendido.

abstract: de la misma forma que en una clase, los aspectos abstractos tienen

la característica de contener elementos abstractos, es decir, sólo definidos

pero no implementados. En el caso de los aspectos, estos elementos pueden

ser atributos, métodos o pointcuts.

La palabra reservada privileged es un modificador introducido por AspectJ exclu-

sivamente para los aspectos e indica que el aspecto tiene el privilegio de acceder a miem-

bros de clases que comúnmente no podría, ya sean privados, protegidos o “default” de

otros paquetes.

Los aspectos, al igual que una clase, pueden implementar interfaces y/o extender

otra clase. Además, pueden extender de otros aspectos, manteniendo la misma semántica

que en el caso de las clases, es decir, se heredan los elementos públicos y protegidos del

aspecto o clase base. Como restricciones, los aspectos no pueden implementar ni la inter-

face “Serializable” ni la interface “Clonable”. La semántica de estas interfaces no tiene

sentido para el caso de un aspecto. Si bien un aspecto puede extender tanto de una clase

como de un aspecto, lo contrario no es cierto en AspectJ, una clase sólo puede extender

otra clase, ya que los aspectos tienen un grupo de elementos que incluyen a los de un cla-

se. Es decir, un aspecto es una clase con elementos adicionales.

<Aspecto> :=

[ privileged ] [ <Modificadores> ] aspect <Identificador>

[ extends <Tipo> ] [ implements <ListaDeInterfaces> ]

[ <ClausulaDeInstanciación> ]

{ <Cuerpo> }

Page 30: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

20 Programación Orientada a Aspectos Diego M.S. Erdödy

A diferencia de una clase, un aspecto no puede poseer constructores debido a que

no puede ser instanciado explícitamente. En cambio, el aspecto es automáticamente ins-

tanciado. El momento y forma de su instanciación depende de la política que se defina en

la <ClausulaDeInstanciación>. Las distintas políticas disponibles son:

issingleton(): política por defecto que indica que existirá sólo una instancia

del aspecto.

perthis( <Pointcut> ): una instancia es creada y asociada a cada objeto que

actúa de iniciador al llegar al punto de ejecución definido por cualquiera de

los join points que forman el pointcut que se recibe como parámetro.

pertarget( <Pointcut> ): similar al caso anterior, pero con la diferencia que

la instancia se asocia al objeto destino del join point perteneciente al point-

cut pasado como parámetro.

percflow( <Pointcut> ): es la abreviación de “per control flow” (por cada

control de flujo). El aspecto es instanciado al entrar en el flujo de ejecución

definido por el pointcut. A diferencia de los dos casos anteriores, puede

haber más de una instancia de un aspecto definido para el mismo objeto, si

el flujo del programa pasa más de una vez por los join points definidos en el

pointcut. En los últimos dos casos sólo puede haber una instancia del mismo

aspecto asociada a un objeto.

percflowbelow( <Pointcut> ): Variación del caso anterior en donde la ins-

tanciación se hace inmediatamente después de llegar a uno de los join points

del pointcut.

pertypewithin( <PatronTipo> ): A diferencia de los demás tipos de instan-

ciación, pertypewithin recibe como parámetro una expresión del tipo <Pa-

tronTipo>. Dicha expresión representa un conjunto de Clases o Interfaces

con ciertas características en común y será explicada en detalle más adelan-

te. Al utilizar este tipo de instanciación, una instancia del aspecto es creada

por cada Clase o Interface que concuerda con la expresión.

Por último, un aspecto debe poseer un cuerpo en donde se definen los elementos in-

tegrantes del aspecto. Estos elementos pueden ser, al igual que en una clase: atributos,

métodos, clases internas o interfaces internas, teniendo en cuenta que un aspecto no pue-

de definir constructores. En el cuerpo de un aspecto también se pueden definir los si-

guientes elementos: pointcut, advice, declaraciones inter-tipo y otras declaraciones. En

las siguientes secciones se analiza la gramática y semántica de cada uno de estos elemen-

tos.

3.5.2. Definición de un pointcut

Un pointcut, es la estructura que no se asemeja a ninguno de los miembros tradicio-

nales de una clase. Básicamente, se trata de un identificador seguido de parámetros y la

definición de una expresión que indicará cuales son los join points a capturar. La estruc-

tura formal es:

Page 31: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 21

El primer caso corresponde a un pointcut abstracto el cual, de la misma forma que

un método abstracto, sólo declara la “firma” del pointcut, comprendida por el identifica-

dor y sus parámetros. Al igual que en un método abstracto, su objetivo es declarar la exis-

tencia del elemento para que pueda ser referenciado dentro del aspecto, dejando abierta la

posibilidad de definirlo en aspectos derivados.

El segundo caso se aplica para los pointcuts concretos. El pointcut se define de la

misma forma que en el primer caso, sin la palabra reservada “abstract”. Los modificado-

res posibles son los mismos que para el caso de un aspecto: public, private, default y fi-

nal. Estos tienen la misma semántica. Los parámetros tienen la misma sintaxis que en el

caso de los métodos de Java, es decir, una lista separada por coma de parámetros los cua-

les se componen del tipo (clase o interface) y el identificador del parámetro.

Si bien los pointcuts se pueden sobrescribir en aspectos derivados, al igual que un

método, no existe la noción de sobrecarga. Eso quiere decir que no se puede declarar más

de un pointcut con el mismo identificador en un mismo aspecto o aspectos derivados, que

posean una lista de parámetros distinta, ya sea en cantidad o en tipos.

La expresión <PointcutExpression> está formada principalmente por elementos

llamados pointcuts primitivos. Hay varios tipos de pointcuts primitivos y cada uno defi-

ne un conjunto específico de join points prefijado dentro del universo de join points posi-

ble en un programa. Dicho conjunto puede ser limitado a través de los parámetros que se

le proveen. Estos pointcuts primitivos pueden ser combinados entre sí con operaciones de

conjuntos para formar la expresión final que especificará exactamente los join points que

integrarán el pointcut en cuestión. Las operaciones disponibles son: unión (||), intersec-

ción (&&) y complemento (!). Por último, en el caso de utilizar parámetros dentro de la

declaración del pointcut, se deben utilizar operadores especiales que se encargan de enla-

zar los parámetros con elementos del join point, como se verá al final de la sección.

AspectJ permite utilizar los siguientes tipos de pointcuts primitivos:

call( <PatronFirma> ): incluye los join points en donde se realice una lla-

mada a métodos que coincidan con la firma pasada como parámetro. Esta

firma puede incluir comodines en distintos puntos, para poder agrupar va-

rios métodos relacionados con una sola expresión. La expresión <Patron-

Firma> puede ser una patrón de método o de constructor y la sintaxis for-

mal es:

<Pointcut> := <PointcutAbstracto> | <PointcutConcreto>

<PointcutAbstracto> :=

abstract [ <Modificadores> ] pointcut <Id> ( <Parametros>

);

<PointcutConcreto> :=

[ <Modificadores> ] pointcut <Id> ( <Parametros> ) :

<PointcutExpression> ;

Page 32: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

22 Programación Orientada a Aspectos Diego M.S. Erdödy

Como se puede ver en la sintaxis formal, la diferencia entre ambos es que

para el caso de un constructor, no hace falta el tipo de retorno y en vez de un

identificador, se utiliza la palabra “new”.

Las expresiones <PatronModificadoresMetodo> y <PatronModificadores-

Constructor> son simplemente una enumeración de los modificadores de

Java que se pretenden incluir o el modificador precedido por el signo „!‟ si

se lo quiere excluir. Los modificadores posibles para un constructor son

“public”, “protected” y “private”. Para el caso de un método se agregan los

modificadores “static”, “final” y “synchronized”.

La expresión <PatronIdentificador> es una secuencia de caracteres válidos

para un identificador en Java con la posibilidad de utilizar el carácter co-

modín „*‟ para reemplazar un grupo de caracteres.

La expresión <PatronThrow> es una lista separadas por coma de <Patron-

Tipo> en donde cada elemento puede ir precedido del signo „!‟ en caso de

querer excluirlo.

Por último, la expresión <PatronTipo> conceptualmente representa un

patrón que agrupa clases o interfaces. Este patrón es utilizado en la expre-

siones <PatronMétodo> y <PatronConstructor> para reemplazar el tipo de

retorno del método, el calificador (a qué tipo pertenece el método) y a los ti-

pos de cada uno de los parámetros. A partir de la versión 1.5 de AspectJ se

introdujo compatibilidad con Java 1.5 y es por eso que se aceptan anotacio-

nes dentro de este patrón. La sintaxis es:

<PatronFirma> := PatronMetodo | PatronConstructor

<PatronMetodo> :=

[ <PatronModificadoresMetodo> ] <PatronTipo>

[ <PatronTipo> . ] <PatronIdentificador> ( <PatronTipo> |

.. , ... )

[ throws <PatronThrow> ]

<PatronConstructor> :=

[ <PatronModificadoresConstructor> ] [ <PatronTipo> . ]

new ( <PatronTipo> | .. , ... )

[ throws <PatronThrow> ]

Page 33: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 23

Esta definición recursiva, muestra que el <PatronTipo> consiste de expre-

siones simples de tipos que pueden ser combinadas con operadores boolea-

nos y a los cuales se les puede indicar un patrón de anotación. El <Patron-

TipoSimple> consta de una expresión <PatronNombreTipo> que consta de

una cadena de caracteres para especificar un identificador de tipo, opcio-

nalmente con su paquete y puede contener dos tipos de comodines, „*‟ y „..‟.

El comodín „*‟ reemplaza una cadena de caracteres que no incluyan el

carácter „.‟ mientras que el comodín „..‟ reemplaza un grupo de términos se-

parados por el carácter „.‟. Si bien se pueden agrupar distintos tipos de esta

manera (basados en patrones de nombre o de paquete), el signo „+‟ permite

hacer coincidir además, a todos los tipos derivados de las coincidencias ori-

ginales, es decir clases o interfaces hijas según sea el caso. En caso de tra-

tarse de vectores se deben agregar la cantidad correspondientes de pares de

corchetes según la dimensión.

La expresión <PatronAnotacion> permite reducir el grupo de coincidencias

basándose en las anotaciones que posee el elemento. La sintaxis es:

Es una lista de términos encabezados por el signo „@‟. La semántica en el

caso de los términos de la lista es la conjunción, es decir una coincidencia se

dará cuando se cumplan las condiciones de todos los términos. Opcional-

mente se puede preceder a cada término por el signo „!‟ para negarlo. Cada

término puede ser simple o complejo. En el primer caso consta de un identi-

ficador de tipo. En el segundo caso, la expresión debe ir encerrada entre

paréntesis y consta de una expresión booleana de identificadores del primer

tipo con la posibilidad de combinarlos con los operadores „||‟, „&&‟ o „!‟.

execution( <PatronFirma> ): similar al pointcut primitivo del tipo call, con

la diferencia de que el join point se encuentra inmediatamente después de

haber realizado la llamada e inmediatamente antes de iniciar la ejecución del

<PatronAnotación> := [ ! ] @ <PatronNombreTipo> | (

<ExpresionTipo> ) ...

<PatronTipo> := <PatronTipoSimple> |

! <PatronTipo> |

( [ <PatronAnotacion> ] <PatronTipo> )

<PatronTipo> '&&' <PatronTipo> |

<PatronTipo> '||' <PatronTipo>

<PatronTipoSimple> := <PatronNombreTipo> [ + ] [ '[]' ... ]

Page 34: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

24 Programación Orientada a Aspectos Diego M.S. Erdödy

método. La expresión <PatronFirma> es la misma que se describió en el

caso anterior.

get( <PatronAtributo> ): representa los join points en donde se efectúa una

lectura de los atributos que coinciden con la expresión <PatronAtributo>.

Dicha expresión tiene la siguiente sintaxis:

La expresión consta de un patrón de anotación opcional seguido de un <Pa-

tronModificadoresAtributo> que tiene la misma sintaxis que en los casos

anteriores y las posibilidades son equivalentes a los modificadores permiti-

dos para un atributo en Java, es decir, “public”, “private”, “protected”, “sta-

tic”, “transient” y “final”.

La expresión se completa con un término <PatronTipo>, explicado ante-

riormente, que indica el tipo de los atributos a capturar y otra expresión op-

cional del mismo tipo que especifica a qué clase pertenecen los atributos a

capturar. Por último se especifica el patrón que aplicará al identificador del

atributo.

set( <PatronAtributo> ): similar al pointcut primitivo del tipo “get”, con la

diferencia que se seleccionan los join points de escritura en vez de lectura,

de los atributos que coincidan con el patrón especificado.

handler( <PatronTipo> ): representa los join points en donde se captura

una excepción del tipo indicado por la expresión <PatronTipo>. Esta captu-

ra está siempre especificada por una cláusula “catch” en Java.

adviceexecution(): representa los join points donde se inicia la ejecución de

un advice. No requiere argumentos.

within( <PatronTipo> ): representa el conjunto de todos los join points que

tienen como elemento en la cadena de llamadas al tipo especificado en la

expresión pasada como argumento.

withincode( <PatronFirma> ): similar al pointcut primitivo anterior, con la

diferencia que en vez de aplicarse a un tipo, se aplica a una firma, es decir

un método o constructor. Formalmente, el conjunto de todos los join points

que tienen como elemento en la cadena de llamadas a un método o construc-

tor que coincida con la expresión pasada como argumento.

cflow( <PointcutExpression> ): representa los join points que están dentro

del flujo de ejecución de los join points capturados por la expresión pasada

como parámetro, incluyendo a estos últimos. Dentro del flujo de ejecución

significa que los join points figuran dentro de la cadena de llamada.

<PatronAtributo> :=

[ <PatronAnotacion> ] [ <PatronModificadoresAtributo> ]

<PatronTipo> [ <PatronTipo> ] . <PatronIdentificador>

Page 35: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 25

cflowbelow( <PointcutExpression> ): similar al caso anterior, con la dife-

rencia que los join points representados por la expresión pasada como pará-

metro, son excluidos del conjunto.

staticinitialization( <PatronTipo> ): captura los join points del inicio de la

ejecución de un inicializador estático para los tipos que coinciden con el

patrón pasado como parámetro.

initialization( <PatronFirma> ): captura los join points del inicio de la eje-

cución de un constructor desde que retorna la ejecución del constructor pa-

dre (super) hasta el retorno del primer constructor, para los constructores

que coinciden con el patrón pasado como parámetro.

preinitialization( <PatronFirma> ): a diferencia del anterior, los join

points capturados son los de la ejecución desde el inicio del constructor has-

ta la llamada del constructor padre (super).

Para poder enlazar los parámetros que se le proveen al pointcut con la expresión

que lo definirá, se cuenta con un proceso denominado “Exposición de Contexto”. En

dicho proceso, ciertos operadores llevan a cabo la tarea de relacionar los parámetros del

pointcut con objetos definidos según el tipo de operador. Estos operadores son:

this( <Tipo> | < PointcutVar> ): representa el conjunto de join points en

donde el objeto que se está ejecutando es del tipo indicado por el parámetro.

En el caso de pasar como parámetro un identificador de variable del point-

cut, se asigna a dicha variable el objeto en ejecución al momento de alcan-

zar el join point.

target( <Tipo> | < PointcutVar> ): similar al caso anterior con la diferencia

de que en vez de referirse al objeto que se está ejecutando, se refiere al obje-

to destino del join point. Por ejemplo, en un join point del tipo “call” co-

rresponderá al objeto sobre el cual se efectúa la llamada.

args( <Tipo> | <PointcutVar> , … ): en este caso, se trata de referenciar los

argumentos del pointcut. A diferencia de los otros dos casos, recibe una lista

de argumentos que pueden ser tipos o identificadores. Semánticamente re-

presenta los join points cuyos tipos parámetros coinciden con los tipos (o los

tipos de los identificadores) pasados como parámetro. En el caso de prove-

erse identificadores como parámetro, a dicha variable se le asigna el valor

que posee el argumento correspondiente en el join point al momento de ser

capturado, por ejemplo al ejecutar un advice.

3.5.3. Declaración de un advice

Un advice define el comportamiento que deberá ejecutarse en los join points captu-

rados por un pointcut. La declaración es muy similar a un método, con la diferencia que

se debe especificar a qué tipo pertenece y sobre qué pointcuts actuará. La sintaxis formal

de la declaración de un advice es:

Page 36: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

26 Programación Orientada a Aspectos Diego M.S. Erdödy

El modificador opcional strictfp, al igual que en Java, indica que las operaciones de

punto flotante realizadas dentro del código del advice deben tener estrictamente la preci-

sión indicada por el estándar, independientemente del hardware utilizado.

La expresión <AdviceSpec> contiene el tipo del advice a declarar junto con los

parámetros necesarios. Los tipos disponibles de advice en AspectJ son los siguientes:

before: el código se ejecuta antes de los join points capturados.

after: el código se ejecuta después de los join points capturados. Por defec-

to, el advice se ejecuta sin importar si el código que sigue al join point, fina-

lizó normalmente o por una excepción. Para indicar específicamente cada

uno de estos dos casos, se utilizan las palabras reservadas “returning” y

“throwing” respectivamente al final de la expresión, seguidos opcionalmen-

te de un argumento entre paréntesis que representa el valor de retorno o la

excepción capturada.

around: el método se ejecutará en vez del join point capturado. Por ejem-

plo, si el join point es del tipo “call”, la llamada original no se realizaría (a

no ser que se especifique explícitamente en el método del advice) y en cam-

bio se ejecutaría el código indicado en el advice.

Al igual que un método, se puede indicar opcionalmente la lista de excepciones que

pueden ocurrir dentro del cuerpo del advice, precedida de la palabra throws. Por último,

se completa la declaración del advice con un signo „:‟ seguido de una <PointcutExpres-

sion> que ya fue definida anteriormente y el cuerpo de advice encerrado entre llaves.

3.5.4. Ejemplos

Una vez definidos los tres elementos fundamentales (aspecto, pointcut y advice) se

muestran distintos ejemplos para clarificar las definiciones hasta aquí presentadas. Los

ejemplos están basados en una implementación de un modelo sencillo de cuentas banca-

rias. La estructura del ejemplo es la siguiente:

<Advice> := [ strictfp ] <AdviceSpec> [ throws <ListaDeTipos> ] :

<PointcutExpression> { <CuerpoAdvice> }

<AdviceSpec> :=

before ( <Argumentos> ) |

after ( <Argumentos> ) |

after ( <Argumentos> ) returning [ ( <Argumento> ) ] |

after ( <Argumentos> ) throwing [ ( <Argumento> ) ] |

<Tipo> around ( <Argumentos> )

Page 37: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 27

Figura 3-5: Diagrama de estructura para los ejemplos de AspectJ

Los clientes están representados por la clase Customer que tiene atributos como

identificación, nombre, dirección y una lista de cuentas. La clase abstracta Account en-

capsula el comportamiento de una cuenta y posee dos clases derivadas SavingAccount y

CurrentAccount, para una caja de ahorro y una cuenta corriente respectivamente. La

cuenta posee una identificación y un monto. Además de consultar el saldo, se puede de-

positar o extraer dinero mediante los métodos deposit() y withdraw().

Por otro lado, los usuarios internos del sistema están representados por la interface

User. Existen dos tipos: Sentinel y Teller, que representan un empleado de seguridad y

un cajero, en ese orden. Por último, la clase SecurityManager, permite averiguar si un

usuario está registrado en el sistema a través del método estático userLogged().

El siguiente ejemplo muestra la implementación más simple de un interés transver-

sal de auditoría sobre todas las llamadas críticas, es decir los movimientos de fondos.

Account

-amount : double

-id : String

<<JavaElement>>+withdraw( dAmount : double ) : void{JavaAnnotations = @Transaction}

<<JavaElement>>+deposit( dAmount : double ) : void{JavaAnnotations = @Transaction}

+transferTo( destination : Account, dAmount : double ) : void

<<setter>>+setId( id : String ) : void

<<getter>>+getAmount() : double

<<getter>>+getId() : String

-id : String

Teller

<<getter>>+getAccounts( cust : Customer ) : List<E->Account>

<<constructor>>+Teller( nid : String )

<<getter>>+getId() : String

Sentinel

-id : String

<<getter>>+getAccounts( cust : Customer ) : void

<<constructor>>+Sentinel( nid : String )

<<getter>>+getId() : String

Customer

-accounts : List<E->Account>

-address : String

-name : String

-id : String

<<setter>>+setAddress( address : String ) : void

<<getter>>+getAccounts() : List<E->Account>

<<setter>>+setName( name : String ) : void

<<setter>>+setId( id : String ) : void

<<getter>>+getAddress() : String

<<getter>>+getName() : String

<<getter>>+getId() : String

SecurityManager

+userLogged( user : User ) : boolean

User

<<getter>>+getId() : String

CurrentAccountSavingAccount

-has

0..*

Page 38: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

28 Programación Orientada a Aspectos Diego M.S. Erdödy

El interés es implementado por el aspecto Audit, el cual consta del poincut audita-

bleCall() que representa las llamadas a auditar. En este caso, por simplicidad, las llamadas

a los métodos de depósito y extracción son enumeradas (vinculadas con el operador „||‟).

Nótese que se utilizan comodines para el tipo de devolución de los métodos, así como

también para los argumentos. Esto garantiza que en caso de sobrecargar los métodos en

futuras implementaciones, los métodos sobrecargados seguirán formando parte del poin-

cut. También cabe destacar que al utilizar el operador „+‟, el pointcut abarca las llamadas

a los métodos de la clase Account y a todas las clases derivadas, en este caso SavingAc-

count y CurrentAccount. Por último, el aspecto define un advice del tipo “before” sobre

el poincut, para realizar la operación de auditoría, representada por el método audit().

Para hacer la implementación más flexible, se puede usar metainformación para

describir la funcionalidad de los participantes del sistema. De esta manera, se pueden usar

construcciones que consuman esta metainformación y así evitar la enumeración. Si los

métodos deposit() y withdraw() de la clase Account, estuvieran modificados con la anota-

ción de negocio @Transaction, describiendo a las operaciones monetarias atómicas, el

poincut se podía reescribir de la siguiente manera:

De esta forma se están capturando todas las llamadas a métodos públicos de la clase

Account o derivadas, que estén modificados con dicha anotación.

Por último se analiza el caso de la implementación de un interés de seguridad. Se

pretende que el acceso a cuentas de un cliente, sea permitido sólo a los cajeros que están

registrados en el sistema. El aspecto que lo implementa es el siguiente:

public pointcut auditableCall():

call(@Transaction public * Account+.*(..));

public aspect Audit {

public pointcut auditableCall():

call(public * Account+.deposit(..)) ||

call(public * Account+.withdraw(..));

before(): auditableCall() {

audit("Audit transaction: " + thisJoinPoint);

}

}

Page 39: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 29

En el aspecto AccessRestriction, se comienza declarando el pointcut securityCalls()

que encapsula las llamadas que se pretenden controlar. En este caso son las llamadas a

métodos de acceso a las cuentas getAccounts() de la clase Customer o derivadas. A conti-

nuación, se define el pointcut checkedCalls() que representa las llamadas que se deben

permitir solamente cuando el usuario esté registrado en el sistema. Está compuesto por

todos los puntos contenidas en securityCalls() que sean llamados desde un objeto del tipo

Teller o derivado. Además, se vincula un parámetro del tipo usuario, con el objeto origen

de la invocación, es decir el cajero. Para el pointcut checkedCalls(), se define un advice del

tipo “before” que consulta con el SecurityManager si el usuario está registrado. De no

ser así, se lanza una excepción indicando la situación. El segundo advice lanza una ex-

cepción cuando se llega a un punto contenido en forbiddenCalls(), indicando que no se tie-

ne acceso.

Para la definición de las llamadas a controlar, en el pointcut securityCalls(), existe

el peligro de que en el futuro se agreguen métodos que accedan a la lista interna del obje-

to, pero bajo otra convención de nombres (un iterador, por ejemplo). Esto se puede solu-

cionar con el mecanismo de las anotaciones, aunque en este caso la anotación no tiene

una semántica definida, es decir sería una solución forzada. Otra posible solución al pro-

blema, es definir el pointcut a partir del acceso a la lista interna, utilizando el join point

del tipo “get”. El pointcut sería:

public pointcut securityCalls():

cflow(call( * Customer+.*(..))) &&

get(private List<Account> Customer+.accounts);

public aspect AccessRestriction {

public pointcut securityCalls():

call( * Customer+.getAccounts(..));

public pointcut checkedCalls(User usr):

within(Teller+) && securityCalls() && this(usr);

public pointcut forbiddenCalls():

!within(Teller+) && securityCalls();

before(User usr): checkedCalls(usr) {

if (!SecurityManager.userLogged(usr)) {

throw new BankingException("User should be logged");

}

}

before(): forbiddenCalls() {

throw new BankingException("Access denied");

}

}

Page 40: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

30 Programación Orientada a Aspectos Diego M.S. Erdödy

En esta nueva versión se está incluyendo a todos los puntos que precedan a una

llamada a un método de la clase Customer o derivada (indicado con el join point “cflow”)

y en cuya ejecución se acceda al atributo privado “accounts” de la misma clase. Esta im-

plementación tiene el problema de depender de la estructura interna del objeto, aunque en

este caso no es muy probable que se vaya a modificar.

3.5.5. Declaraciones de miembros inter-tipo

Para la implementación transversal estática, AspectJ cuenta con las declaraciones

de miembros inter-tipo. Estas declaraciones consisten en agregar miembros, ya sea atribu-

tos o métodos, a clases externas al aspecto. De esta forma se logra introducir en la clase,

la lógica específica al interés que implementa el aspecto, sin que dicha clase tenga cono-

cimiento.

Existen varias estructuras sintácticas para este tipo de declaraciones, según sea el

tipo de miembro que se quiera agregar. Estas son:

El primer y el segundo caso corresponden a declaraciones de introducción de méto-

dos abstracto y concreto, respectivamente. En estos casos la sintaxis es casi idéntica a la

declaración de un método en Java. La única diferencia es que el nombre o identificador

del método debe ir precedido del nombre de la clase en donde se desea introducir.

El tercer caso corresponde a la introducción de un constructor. La declaración cuen-

ta con la particularidad de que en vez de requerir un identificador, como en el caso de un

método, se debe utilizar la palabra reservada new, para indicar que se trata de un cons-

tructor. Al igual que el identificador de un método, la palabra debe ir precedida de la cla-

se en donde se quiere introducir el constructor.

El cuarto caso representa la introducción de un atributo. Sigue la forma de una de-

claración de atributos en Java, con la diferencia de anteponer el tipo al que se quiere in-

troducir, antes del identificador del atributo.

1) abstract [ <Modificadores> ] <Tipo> <Tipo> . <Id> ( <Parametros> )

[ throws <ListaDeTipos> ] ;

2) [ <Modificadores> ] <Tipo> <Tipo> . <Id> ( <Parametros> )

[ throws <ListaDeTipos> ] { <Cuerpo> }

3) [ <Modificadores> ] <Tipo> . new ( <Parametros> )

[ throws <ListaDeTipos> ] { <Cuerpo> }

4) [ <Modificadores> ] <Tipo> <Tipo> . <Id> [ = <Expresion> ] ;

Page 41: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 31

3.5.6. Declaraciones de derivación

Llamamos declaraciones de derivación a las sentencias de un aspecto que permiten

introducir extensión de padres o implementación de interfaces en una clase dada. La sin-

taxis de estas declaraciones es:

En ambos casos, la declaración comienza con las palabras reservadas “declare

parents : ” y es seguida de una expresión del tipo <PatronTipo>. Dicha expresión repre-

senta un conjunto de clases a las cuales se les efectuará la introducción.

El primer caso corresponde a la introducción de la extensión de la clase especifica-

da. Como el código compilado que genera AspectJ debe ser compatible con cualquier

JVM tradicional, no se pueden introducir extensiones a clases que ya poseen un padre. En

otras palabras, si una clase extiende de otra, no se puede forzar a que extienda de una

tercera ya que Java no permite le herencia múltiple. Existe, sin embargo, una excepción a

dicha regla que consiste en introducir una extensión de una subclase del padre original.

Por ejemplo, si A extiende de B, un aspecto puede hacer que A extienda de C, siempre y

cuando C sea subclase de B.

El segundo caso corresponde a la introducción de implementación de nuevas inter-

faces. Al igual que en Java, se puede especificar una lista de interfaces a implementar. La

única restricción que existe, es que los métodos definidos por las nuevas interfaces, deben

ser implementados, o bien con métodos preexistentes, o con métodos introducidos por el

aspecto.

Siguiendo con el ejemplo propuesto, se analiza la implementación del interés “co-

bro de servicios”, para brindar un ejemplo de declaraciones de miembros inter-tipo como

de declaraciones de derivación. El objetivo es registrar los accesos a los servicios de las

cuentas corrientes de cada cliente y acumularlo para poder realizar los resúmenes a fin de

mes. Si bien esta implementación se podría realizar sin la ayuda de aspectos, el código

asociado al interés se mezclaría con el interés principal de una cuenta que es administrar

fondos. El aspecto que lo implementa es el siguiente:

1) declare parents : <PatronTipo> extends <Tipo> ;

2) declare parents : <PatronTipo> implements <ListaDeInterfaces> ;

Page 42: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

32 Programación Orientada a Aspectos Diego M.S. Erdödy

En el aspecto Billing, se declara la interface Billable que representa un objeto con-

table. Esta interface posee el método getBill() para obtener el acumulado de consumo y

addToBill() para agregar un nuevo consumo. En las siguientes tres declaraciones de inter-

tipo, se realiza la implementación de la interface, agregando un atributo que representa el

acumulado de consumo y la implementación de los métodos. Este mecanismo es similar a

implementar una clase abstracta, pero brinda la facilidad de poder utilizar varias imple-

mentaciones al mismo tiempo, como se haría en un esquema de herencia múltiple. La

siguiente línea indica que la clase CurrentAccount debe implementar la interface Billa-

ble. Luego se declara el poincut billableCall(), similar al utilizado en el ejemplo de auditor-

ía, el cual captura los métodos modificados con la anotación @Transaction. Por último,

se define un advice de tipo “before” sobre el pointcut, para adicionar un costo arbitrario

al consumo de la cuenta.

Vale aclarar que los ejemplos utilizados son ilustrativos para comprender el uso de

la sintáxis de AspectJ. La mayoría de los ejemplos se pueden resolver con aspectos abs-

tractos que hacen que la implementación sea reutilizable, y aumentan las propiedades de

modularidad, pero esto aumenta considerablemente la complejidad de los mismos.

public aspect Billing {

interface Billable {

double getBill();

void addToBill(double amount);

}

public double Billable.bill;

public double CurrentAccount.getBill() {

return bill;

}

public void CurrentAccount.addToBill(double amount) {

bill += amount;

}

declare parents: CurrentAccount implements Billable;

public pointcut billableCall(Billable billable):

call(@Transaction public * CurrentAccount.*(..)) &&

target(billable);

before(Billable billable): billableCall(billable) {

billable.addToBill(1);

}

}

Page 43: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 33

3.5.7. Otras declaraciones

Por último, se describen las declaraciones generales que provee AspectJ. La sintaxis

de las declaraciones restantes es:

La primera y la segunda declaración, tienen semánticas y sintaxis muy similares.

Ambas definen que cierto conjunto de join points, especificados por la expresión <Poin-

cutExpression>, deben ser tratados por el compilador, al momento de compilación como

advertencias o como errores, según se trate del primer o del segundo caso respectivamen-

te. El mensaje a mostrar es el último término de la declaración. Este tipo de declaraciones

sirven, por ejemplo, para reforzar la modularidad de cierto componente y asegurarse que

sus métodos sean utilizados sólo desde algunas clases seleccionadas, es decir, casos com-

plejos donde la visibilidad no alcanza para cumplir dicho propósito.

La declaración del tipo “soft”, convierte al tipo org.aspectj.lang.SoftException la

excepción especificada en la declaración que se lanza en los join points que representa el

pointcut. Dicha excepción es del tipo RuntimeException, por lo que no es necesario cap-

turarla.

Por último, la declaración “precedence” indica en qué orden se deben aplicar los

aspectos, en caso que haya alguna ambigüedad al respecto. Simplemente se enumera la

lista de aspectos en el orden de su aplicación, pudiendo utilizar opcionalmente comodines

para hacer más simples las instrucciones del tipo “primero aplicar el aspecto A y después

cualquier otro que deba aplicarse”.

Continuando con el ejemplo del interés de seguridad, para las llamadas prohibidas,

(es decir, los pedidos de cuentas a usuarios por parte de objetos que no sean cajeros ni

derivados) la acción que se tomó fue lanzar una excepción. El inconveniente que trae esta

decisión es que las llamadas ilegales serán identificadas en tiempo de ejecución, cuando

tal vez sea demasiado tarde. Para poder identificar dichas llamadas en tiempo de compi-

lación, se puede usar una llamada del tipo “declare error” de la siguiente forma:

declare error: forbiddenCalls() : "Access denied";

1) declare warning : <PointcutExpression> : <String> ;

2) declare error : <PointcutExpression> : <String> ;

3) declare soft : <Excepcion> : <Pointcut> ;

4) declare precedence : <ListaDeAspectos>;

Page 44: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

34 Programación Orientada a Aspectos Diego M.S. Erdödy

De esta manera utilizando extensiones que soportan el análisis sintáctico en tiempo

de edición, como por ejemplo AJDT en la IDE de Eclipse, las llamadas prohibidas serán

identificadas como errores de compilación tradicionales. La siguiente captura muestra

este caso:

Figura 3-6: Captura de Eclipse mostrando el resultado de “declare error”

3.5.8. Intercalado

Con respecto a la técnica de intercalado, AspectJ utiliza un compilador dedicado, el

cual genera código Java binario a partir del conjunto de clases y aspectos, ya sea en códi-

go fuente o archivos compilados, que están disponibles en tiempo de compilación.

Page 45: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 35

Figura 3-7: Mecanismo general de funcionamiento de AspectJ

La gran desventaja de este mecanismo es la necesidad de contar con todas las clases

que intervienen en el sistema al momento de compilación, en vez de poder hacer el inter-

calado a medida que se van cargando las clases en tiempo de ejecución. Sin embargo, de

este modo se logra una mayor performance del sistema ya que todo el código ha sido pro-

cesado e intercalado en tiempo de compilación y no existe ninguna penalidad en cuanto a

performance en tiempo de ejecución.

3.6. Comparación con otras implementaciones de AOP

Para poder seleccionar la herramienta que se utiliza en este trabajo, se realizó un

análisis de otras implementaciones AOP, similar al trabajo de Mik Kersten [Ker 05], so-

bre versiones actualizadas y nuevas implementaciones. Sin entrar en los detalles sintácti-

cos de cada una de las implementaciones, se realiza un análisis y comparan las caracterís-

ticas de cada implementación, las cuales se resumen al final en una tabla comparativa.

3.6.1. AspectWerkz

AspectWerkz [AWerks 05] (AW) es un framework AOP para Java, diseñado para

ser dinámico, liviano y de alta performance.

La primera diferencia importante que presenta frente a AspectJ, es que la imple-

mentación no está basada en una extensión a la sintaxis del lenguaje Java. Existen dos

opciones para realizar declaraciones de aspectos.

La primera opción consiste en un archivo de configuración en formato XML que

contiene todas las instrucciones que indican las clases que implementarán los aspectos,

pointcuts, advices y demás declaraciones de AOP. Es decir que los aspectos son en reali-

dad clases tradicionales de Java, las cuales deben cumplir con alguna convención, como

por ejemplo poseer cierto tipo específico de constructor.

La otra opción, incorporada recientemente para la definición de declaraciones AOP

de AW, es usar anotaciones de Java 5. Básicamente, se traslada la información del archi-

Archivos compilados

(.jar + .class)

Código fuente Java (.java)

Código fuente AspectJ (.aj)

AspectJ Compiler (ajc)

Sistema intercalado (archivos .class + .jar )

JVM tradicional(java)

Page 46: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

36 Programación Orientada a Aspectos Diego M.S. Erdödy

vo XML a anotaciones dentro de clases tradicionales de Java. De esta forma, la informa-

ción AOP se encuentra mucho más localizada que en el caso del archivo de configura-

ción, permitiendo un mejor entendimiento y facilitando el mantenimiento.

Ambas opciones tienen la desventaja de no proveer un chequeo sintáctico de las ex-

presiones de pointcuts en tiempo de compilación. Dado que dichas expresiones son atri-

butos de XML o argumentos de anotaciones, según la opción que se prefiera, los cheque-

os que se realizan en tiempo de compilación no analizan las expresiones. En AW en cam-

bio, las expresiones son verificadas en tiempo de ejecución. En el caso de AJDT, el plug-

in de AspectJ para Eclipse, los errores son marcados en tiempo de edición. Esto no se

puede lograr con anotaciones ni con archivos XML.

En cuanto a la estrategia de intercalado, AW utiliza varios modelos según la versión

de Java y el tipo de JVM que se utilice. La opción más moderna, es el intercalado en

tiempo de carga que se puede realizar con la nueva API de instrumentación de Java 5,

especificado en el Java Specification Request número 163 del Java Community Process

[JSR 163]. Dicha API, permite especificar al iniciar la JVM, una o más clases con ciertas

características que actuarán de “agentes java”. Estas clases deben contener un método

llamado “premain” el cual será llamado al iniciar la JVM. Uno de los argumentos de este

método, es un objeto que implementa la interface “Instrumentation” que brinda los servi-

cios específicos de instrumentación. Entre estos servicios, se encuentra la posibilidad de

incorporar implementaciones propias de la interface “ClassFileTransformer” con la habi-

lidad de modificar el código intermedio de las clases cargadas.

AW soporta la mayoría de los pointcuts primitivos soportados por AspectJ con las

excepciones de adviceexecution, cflowbelow, initialization y preinitialization. Los únicos

dos pointcuts de AW que no posee AspectJ son hasmethod y hasfield. Ambos ayudan a

limitar la cantidad de join points seleccionados en relación a propiedades estructurales

como es la existencia de otros métodos o atributos. AW no soporta las políticas de instan-

ciación del tipo pertarget ni percflow que posee AspectJ.

3.6.2. JBoss AOP

JBoss AOP [JBA 06][Bur 03], es un módulo de soporte de AOP ideado para utili-

zar con el Servidor de Aplicaciones JBoss [JBS 06]. Si bien los conceptos básicos de

AOP están presentes en JBoss AOP (JBA), la forma de presentarlos tiene ciertas diferen-

cias con AspectJ.

En primer lugar, JBA al igual que AW, ofrece dos opciones para declarar los ele-

mentos AOP que acompañan a las clases que los implementan: anotaciones de Java5 (o

un equivalente de XDoclet [XDoc 06] en Java 1.4) o un archivo de configuración XML.

La funcionalidad que se logra con cualquiera de las dos opciones es la misma, ya que

existe un mapeo entre ambas notaciones.

En segundo lugar, en JBA las declaraciones de AOP se pueden realizar en dos ti-

pos distintos de clases, a diferencia de AJ o AW en donde sólo existe el aspecto. En JBA

se utiliza la noción de “interceptores” para poder declarar advices, aunque sigue existien-

do la noción de aspecto. Estos interceptores son simplemente clases que deben implemen-

tar una interface específica (Interceptor) y ser afectadas por la anotación que la identifi-

Page 47: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 37

cará como tal. La mayoría de los elementos AOP restantes pueden declararse tanto dentro

de un aspecto como dentro de un interceptor.

A diferencia de las implementaciones analizadas anteriormente, JBA sólo soporta

los advices del tipo “around”, es decir, los interceptores reemplazan a los join points in-

terceptados. La interface Interceptor contiene un método que se ejecutará al momento de

llegar al join point y tiene como argumento un objeto del tipo Invocation. Este objeto

brinda por un lado meta-información sobre el join point actual (p. ej. tipo de miembro,

nombre del método/constructor, argumentos, etc.) y por otro lado acciones tales como

“seguir con el joinpoint”. De esta forma se logran simular los advices del tipo “after” o

“before”por medio de programación. En otras implementaciones se puede hacer también

en forma “declarativa”, que resulta más sencillo y visual.

Los pointcuts tienen una sintaxis similar a la de AJ y son representados por un

atributo estático de tipo “Pointcut” modificado por la anotación que lo identifica. Los

advices deben relacionarse con los pointcuts a través de declaraciones especiales denomi-

nadas “Bind” en JBA. Los pointcuts primitivos de AJ que no son soportados por JBA

son: handler, adviceexecution, staticinitialization y preinitialization. Al igual que AW,

adiciona los siguientes pointcuts primitivos “has” y “hasfield” que sirven para relacionar

con la estructura del tipo, es decir si poseen cierto atributo, método o constructor. Por

último, JBA posee un pointcut primitivo llamado “field” que es equivalente a la expre-

sión “get(x) || set(x)” en AJ.

En cuanto a la introducción de elementos, JBA permite introducir solamente nue-

vas implementaciones de interfaces, no soporta la extensión de una nueva clase. Para po-

der implementar los métodos de las interfaces introducidas, JBA utiliza el concepto de

“mixin”. Un mixin en JBA, consta de una clase que implementa las interfaces a introducir

y que cuenta con un constructor que recibe el objeto en donde las interfaces serán intro-

ducidas. Esta clase debe ir acompañada de la declaración del mixin en donde se indica

qué interfaces se quiere introducir en qué clase y cual mixin lo implementará. No es posi-

ble introducir métodos o atributos a una clase, si no es por medio de la introducción de un

nueva interface y de un mixin que la implemente.

Las políticas de instanciación son muy similares a las de AJ, salvo que no permite

“percflow”. En cambio, permite instanciación por clase a diferencia de AJ. Las declara-

ciones adicionales de AJ también son soportadas en su mayoría, excepto las del tipo

“soft”.

El tipo de intercalado que utiliza JBA, es en tiempo de carga, llevado a cabo por

un classloader especial que debe indicarse en el momento de inicializar la VM.

3.6.3. Spring AOP

Spring nació como un framework genérico y modular de soluciones elegantes a

problemas comunes en aplicaciones de empresa, como por ejemplo la configuración de

componentes. Este problema es resuelto por uno de los módulos más populares de Spring

llamado IoC (inversión de control) [Fow 04]. El módulo de AOP [Rus 04], según la pro-

pia documentación, no fue diseñado para ser la solución más completa en AOP, sino para

proveer una buena integración con el módulo de IoC. Es por esto, que la declaración de

Page 48: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

38 Programación Orientada a Aspectos Diego M.S. Erdödy

elementos AOP en Spring, se realiza en el mismo archivo de configuración xml en donde

se definen y configuran los componentes.

En Spring, los pointcuts se declaran a través de clases que deben implementar la

interface “Poincut”. Esta interface tiene dos métodos destinados a seleccionar las clases y

métodos que incluirá el pointcut. La implementación más usada, se basa en expresiones

regulares. Los advice se deben implementar también en una clase que implemente a la

interface del tipo de advice que se desee aplicar, por ejemplo “AfterReturningAdvice”.

Dentro de dicha clase se debe implementar el método declarado que contendrá la lógica

del advice. Este método cambia de nombre dependiendo del tipo de advice. Para el caso

de AfterReturningAdvice, el método que se declara se denomina “afterReturning”. Los

otros tipos de advice soportados son “before” y “throws”. Este último cumple la misma

función que la declaración “after throwing” de AspectJ.

Al igual que JBoss AOP, Spring incorpora el concepto de interceptores. La idea es

muy similar, existe una interface por cada tipo de interceptor (de método, atributo o cons-

tructor) las cuales definen métodos que serán llamados al momento de llegar al punto

interceptado. Estos métodos proveen, a través de los argumentos, la meta información

sobre el punto de intersección que se está utilizando (nombre del método, argumentos,

etc.).

Para introducir nuevas interfaces en Spring, se utiliza un mecanismo similar al ca-

so del advice. Se debe también implementar una interface específica que define varios

métodos. Uno de los métodos está destinado a seleccionar las clases destino de la intro-

ducción. Otro de los métodos indica la lista de clases que serán las interfaces introduci-

das. Por último, un tercer método, similar a los utilizados para interceptores de métodos,

implementa los métodos de las interfaces introducidas, utilizando un mecanismo de iden-

tificación por nombre de los métodos, lo cual resulta engorroso.

Si bien en Spring no existe la noción de aspecto, la conjunción de implementación

de advices y pointcuts en una misma clase se la conoce como “Advisor”. En Spring, los

Advisors son las unidades de modularización y reutilización, similares a los aspectos de

AspectJ.

El intercalado de los elementos AOP en Spring, está inherentemente relacionado

al módulo de inversión de control que provee. Como la instanciación de los componentes

está controlada por el framework, para poder intercalar elementos foráneos a la clase de-

finida, se utiliza una clase provista por el módulo AOP que actúa de Proxy y realiza los

intercalados necesarios. De esta forma, el usuario del componente puede utilizar la im-

plementación del mismo de forma transparente y al mismo tiempo se pueden intercalar

dinámicamente los elementos AOP.

Una de las grandes falencias de Spring AOP es la falta de un verdadero lenguaje

de pointcuts. Es por esto que en la nueva versión 2.0, actualmente en fase beta, se incor-

porará la implementación de AspectJ dentro del framework.

3.6.4. CaesarJ

CaesarJ [Mez 03] es un proyecto nacido en la Universidad Alemana de Darmstadt.

Actualmente se encuentra en la fase de desarrollo (versión 0.8) y esa fue una de las gran-

des desventajas al momento de seleccionar la implementación AOP para este trabajo.

Page 49: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 39

Al igual que AspectJ, CaesarJ es una extensión al lenguaje Java cuyo compilador

genera código intermedio compatible con cualquier JVM tradicional. CaesarJ también

utiliza el mismo modelo de pointcuts propuesto por AspectJ, es decir que soporta los

mismos pointcuts primitivos y la misma sintaxis de declaración tanto de pointcuts como

de advices.

Si bien los diseñadores de CaesarJ reconocen la importancia del modelo de point-

cuts dentro de una implementación AOP, también consideran importante una clara sepa-

ración entre la implementación de un aspecto y su vinculación dentro de una aplicación.

Implementaciones AOP como AspectJ no cuentan con un mecanismo explícito para dicha

tarea. Para solucionar este problema es que se plantea el concepto de “Interfaces de Cola-

boración de Aspectos” (ACI, del inglés Aspectual Collaboration Interfaces).

Las ACI son interfaces cuyas declaraciones de métodos se dividen en “provistos”

(provided) y “requeridos” (required), es decir lo que el aspecto brinda al contexto en don-

de es aplicado y lo que espera obtener de dicho contexto. La implementación (o imple-

mentaciones) de la interface deberá definir los métodos “provistos”, aunque puede tam-

bién referenciar métodos “requeridos” como si se trataran de métodos abstractos. Los

métodos “requeridos” deben ser definidos en módulos especiales denominados “bin-

dings”. En dichos módulos es también donde se definen detalladamente los pointcuts uti-

lizados por el aspecto. A través de las ACIs y su implementación dual, se permite des-

acoplar de una manera clara, la lógica propia del aspecto de la lógica específica a la apli-

cación dentro del contexto.

Existen clases especiales denominadas “weavelets” que son las encargadas de

definir la implementación y el binding que se utilizará con un ACI determinado. El me-

canismo es similar a una clase con una plantilla de 2 argumentos de Java 5. Es en este

punto en donde se observa claramente la flexibilidad que se logra al poder combinar una

implementación con cualquier binding y viceversa. Tener un “weavelet” dentro del grupo

de compilación no es suficiente para que el aspecto sea debidamente intercalado.

CaesarJ provee dos mecanismos para el intercalado de los aspectos. La opción

tradicional es realizar el intercalado en tiempo de compilación, definiendo un atributo con

los modificadores „static‟ y „final‟ en cualquier clase, del tipo del weavelet que se quiere

desplegar. La segunda opción consta de una cláusula llamada “deploy” que permite acti-

var a un determinado aspecto en tiempo de ejecución, y dentro de un bloque perfectamen-

te delimitado.

A pesar de que CaesarJ no provee cláusulas para especificar la política de instan-

ciación que se aplicará a un aspecto, todas las políticas provistas por AspectJ pueden ser

emuladas mediante construcciones particulares. Un weavelet en CaesarJ, por defecto es

instanciado en modo “singleton”. Si se quisiera instanciar en modo “perTarget” se deber-

ía utilizar un wrapper dentro de la implementación de la interface. Esto tiene como des-

ventaja un mayor trabajo al momento de querer aplicar una política no soportada directa-

mente por el lenguaje, lo que trae aparejado una dificultad adicional al momento de leer

la implementación de un aspecto. Por otro lado, es una ventaja el hecho de que las políti-

cas de instanciación puedan ser expresadas en términos de elementos primitivos y no de

cláusulas artificiales.

Page 50: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

40 Programación Orientada a Aspectos Diego M.S. Erdödy

3.6.5. Conclusiones

Una de las características requeridas de la herramienta de AOP para este trabajo es

la mayor expresividad posible en la definición de pointcuts. Es requisito que la herra-

mienta brinde la mayor cantidad de recursos posibles. Esto se debe a que se necesita ex-

plorar cada una de las opciones que brinda AOP al momento de abstraer y modularizar un

patrón de diseño. En esta categoría, AspectJ es el más apropiado, seguido por CaesarJ, ya

que este último utiliza el mismo modelo de pointcuts.

Las razones de la elección de AspectJ por sobre CaesarJ, son la madurez de la im-

plementación y el soporte que brinda la herramienta. En cuanto a soporte para el desarro-

llo, ambas cuentan con plug-ins que facilitan la tarea. El plug-in de AspectJ tiene consi-

derable ventaja en cuanto a la estabilidad y el testeo ya que fue uno de los primeros y más

completos plug-ins producidos.

Las siguientes tablas contienen un resumen de la comparación entre las herra-

mientas AOP analizadas en este trabajo. La primera tabla resume las características de la

implementación y cantidad de elementos que soporta mientras que la segunda muestra el

detalle de dichos elementos.

Page 51: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 41

Impl. AOP Ver. Lenguaje Intercala-do A

no

t.

PP

PE

AD

TI

DD

OD

Conclusiones

AspectJ 1.5 Extensión de Java

Dinámico Sí 13 3 5 4 2 4

Una de las herramientas más maduras y con mejor docu-mentación

Mejor integración a herramientas de desarrollo Mayor flexibilidad en cuanto a características AOP

AspectWerkz 2.0

Configura-ción XML /

Anotaciones de Java 5

En tiempo de carga

(javaagent) Sí 11 3 6 3 0 0

No admite chequeo sintáctico de expresiones Mejor integración a herramientas de desarrollo

JBossAOP 1.5

Configura-ción XML /

Anotaciones de Java 5

En tiempo de carga (classloa-

der)

Sí 11 - 1 4 1 3 No admite chequeo sintáctico de expresiones Introducción de interfaces a través de Mixins

SpringAOP 1.2.8 Configura-ción XML

En tiempo de carga (proxies

dinámicos)

No 5 - 4 2 1 0 Integración al contenedor IoC Orientado a componentes Modelo de pointcuts rudimentario

CaesarJ 0.8.5 Extensión de Java

Tiempo de compilación y ejecución

No 13 3 5 2 - 0 Implementación relativamente reciente, falta de madurez Incorpora el modelo de pointcuts de AspectJ Resuelve ciertos problemas de AspectJ

Referencias:

PP: Pointcuts Primitivos

PE: Pointcuts de entorno

AD: Tipos de Advices

TI: Tipos de instanciación

DD: Declaraciones de derivación

OD: Otras declaraciones

Page 52: Aplicación de programación orientada a aspectos a patrones de ...
Page 53: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Programación Orientada a Aspectos 43

Detalle de la cantidad de elementos AOP soportado por cada implementación

AspectJ AspectWerkz JBoss AOP Spring AOP CaesarJ

call x x x x

execution x x x

get x x x (Field Interc.) x

set x x x (Field Interc.) x

handler x x

adviceexecution x

within x x x

withincode x x x

cflow x x x

cflowbelow x

staticinitialization x x

initialization x (Constr.) x (Constr. Interc.) x

preinitialization x

hasmethod all (any member)

hasfield has (Method or

Constr.)

hasfield

field (get or set)

13 11 11 5 13

this x Acceso Reflexivo Acceso Reflexivo x

target x Acceso Reflexivo Acceso Reflexivo x

args x Acceso Reflexivo Acceso Reflexivo x

3 3 3 3 3

before x x x

after x x

after throwing x x x

after returning x x x

around x x x (Method Interc.) x

after finally

5 6 1 4 5

issingleton perJVM PER_VM x

perthis perInstance PER_INSTANCE x

pertarget PER_JOINPOINT

percflow

perClass PER_CLASS per class

4 3 4 2 1

parents imple-ments x x (Introd. Interc.)

parents extends

2 0 1 1 0

error x

warning x

soft

precedence x

4 0 3 0 0

Page 54: Aplicación de programación orientada a aspectos a patrones de ...
Page 55: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de diseño distribuidos 45

4. Patrones de diseño distribuidos

4.1. Patrones de diseño

Un patrón de diseño es la descripción de una solución repetible a un problema fre-

cuente dentro del diseño de software. Sin embargo no se puede considerar que sea una

solución final aplicable directamente. Se puede ver como una plantilla con una solución

efectiva y probada a una clase específica de problemas dentro de un entorno determinado.

Un patrón tiene cuatro componentes principales, según Gamma et. al [Gam 93], que

son:

I. Nombre: Es el identificador utilizado para describir la solución propuesta por

el patrón. Conocer el nombre de los patrones tradicionales es importante para

crear un vocabulario común. Dicho vocabulario puede ser utilizado en la do-

cumentación de un framework o incluso en la interacción entre colegas.

II. Problema: Describe el entorno al cual el patrón está dirigido. Dicho entorno

puede incluir prerrequisitos para que la aplicación del patrón tenga sentido.

III. Solución: Conjunto de elementos que forman el patrón de diseño. Estos ele-

mentos incluyen los elementos del patrón con sus roles, sus responsabilidades

y las relaciones entre ellos.

IV. Consecuencias: Describe los beneficios y las desventajas de aplicar el patrón.

Documenta las alternativas que presenta el patrón y como afectan las decisio-

nes de compromiso que deben tomarse.

Los 23 patrones tradicionales documentados están divididos en tres grupos, según

el propósito. Los patrones “de creación” tratan con los problemas de instanciación de

objetos. Los patrones “estructurales” están relacionados con la composición de clases u

objetos. Por último, los patrones “de comportamiento” describen los problemas asociados

a la vinculación y distribución de responsabilidades entre objetos.

Los micropatrones de diseño [Gil 05], a diferencia de los patrones de diseño, co-

rresponden a un menor nivel de abstracción. Los micropatrones pertenecen al grupo de

los patrones “traceables”, es decir, los patrones que pueden ser identificados automática-

mente y de una manera simple, dentro del código fuente de un sistema. Esto es posible,

ya que los micropatrones se relacionan con la cantidad y tipo de elementos que posee una

clase.

Por ejemplo, uno de los 27 micropatrones identificados se denomina “Designator” y

se define como una interface sin ningún miembro. Esta interface solamente sirve para

marcar roles dentro de un sistema. Este mecanismo es utilizado por diferentes patrones

del grupo GoF. Los micropatrones ayudan en la implementación en los patrones de dise-

ño y es por eso que se dice que los micropatrones se encuentran en un nivel intermedio

entre la codificación y los patrones de diseño.

4.1.1. Beneficios y problemas de los patrones de diseño

Page 56: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

46 Patrones de diseño distribuidos Diego M.S. Erdödy

Los patrones de diseño permiten la reutilización del conocimiento aplicado al dise-

ño de una solución particular. Es por eso que la documentación de dichas soluciones

permite un vocabulario universal que facilita la comprensión de arquitecturas complejas.

Los patrones pueden ser utilizados de forma “reactiva” o “proactiva” [Cli 96]. El

primer caso corresponde a la documentación de un diseño terminado, con un formato

estándar para poder almacenar el trabajo de análisis y resolución del problema en cues-

tión. El segundo implica la aplicación de los patrones previamente conocidos en un pro-

blema en particular, adaptándolos al entorno específico según los lineamientos que pro-

vee.

Uno de los grandes inconvenientes asociados a la mayoría de los patrones de diseño

es la imposibilidad de realizar una implementación reutilizable utilizando POO. Esto

quiere decir que cada vez que se desee implementar un patrón en un entorno distinto, se

deberá repetir el código utilizado en otros entornos. Si bien el problema tiene varios mo-

tivos que dependen del patrón en particular, se ha hallado que muchos de esos casos tie-

nen que ver con la falta de un mecanismo de abstracción de intereses transversales. En

este trabajo se analizará el grado de avance en este sentido con la aplicación de la POA

como técnica de abstracción transversal.

4.1.2. Descripción de patrones de diseño

Para la descripción de los patrones de diseño se analizaron las metodologías utiliza-

das por Gamma [Gam 95], Schmidt [Sch 00] y Powel Douglas [Dou 02]. Para este trabajo

se eligió una combinación de las metodologías antes mencionadas dado que el objetivo

principal no es analizar los beneficios del patrón en sí, sino explicar el uso del patrón y

analizar los beneficios o desventajas de la implementación orientada a aspectos. Las sec-

ciones que se describen por cada patrón son las siguientes:

Resumen: Breve descripción del patrón que tiene como objetivo dar una idea re-

sumida del propósito del mismo.

Otras denominaciones: Otros nombres bajo los cuales se puede conocer el

patrón, en caso de existir.

Problema: Descripción del conjunto de problemas que busca resolver el patrón de

diseño.

Solución: Descripción de la solución que propone el patrón.

Caso de estudio: Descripción del caso de estudio a analizar para el patrón. Este

caso de estudio es un ejemplo práctico de la aplicación del patrón, útil para des-

cribir el patrón de manera más sencilla y para poder desarrollar una implementa-

ción que será el elemento de análisis principal.

Estructura: Diagrama UML de estructura en donde se describen los elementos

intervinientes en el patrón. Se da una breve explicación general del diagrama en

su totalidad. También se describen en detalle los participantes involucrados en el

diagrama de estructura.

Estrategia de implementación orientada a aspectos: Se describen la estructura

general de la implementación orientada a aspectos junto con el detalle de cada

elemento interviniente en dicha implementación. La implementación estará en

Page 57: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de diseño distribuidos 47

inglés porque actualmente es un estándar y para poder compartir dicha implemen-

tación con otros grupos de estudio.

Análisis de la implementación: Se verifica en qué grado se cumple con las carac-

terísticas a analizar en cada patrón. Para cada una de las características se da una

justificación del nivel encontrado.

Componente gráfico: Detalle y descripción del componente gráfico desarrollado

con la ayuda del framework construido y explicación de su funcionamiento y ca-

racterísticas.

4.2. Uso en sistemas distribuidos y concurrentes

Se dice que un sistema es concurrente cuando está compuesto por tareas que deben

interactuar y que son ejecutadas simultáneamente. Estas tareas pueden ser, por ejemplo,

procesos o hilos de ejecución. Cuando dichas tareas se ejecutan en más de una máquina,

las cuales se encuentran conectadas a través de una red, se dice que el sistema es distri-

buido.

Si el sistema está sujeto a restricciones temporales, se lo llama de tiempo real. Es

decir que las operaciones tienen límites de tiempo claramente especificados. Los sistemas

de tiempo real se dividir en dos tipos. En el primer caso, si las operaciones deben reali-

zarse indefectiblemente dentro de un límite de tiempo prefijado, entonces se dice que es

un sistema de tiempo real duro. Un ejemplo de este tipo de sistemas es el cálculo de la

presión de frenado en un automóvil. La presión debe ser calculada a tiempo, para evitar el

peligro de colisión. En el segundo caso, si las restricciones, aunque son altamente desea-

das, tienen un grado de flexibilidad, se dice que es un sistema de tiempo real blando. En

dicha categoría se encuentran los algoritmos de codificación y decodificación de audio y

video. Si se pierde una muestra, es probable que resulte imperceptible a la vista o audi-

ción humanas.

El objeto de este trabajo es analizar los patrones de diseño aplicado a entornos con-

currentes y distribuidos, sin tener en cuenta el estudio de las restricciones temporales.

Dichos patrones se pueden clasificar en los siguientes grupos:

Patrones de Concurrencia y Sincronización: Son los patrones destinados a re-

solver problemas que surgen en la sincronización de recursos compartidos y tareas

que interactúan concurrentemente. En estos ambientes se debe asegurar que la in-

tegridad de los datos de los recursos compartidos se garantice y que las tareas que

acceden o interactúan entre si no entren en deadlock o starvation. El primero de

los problemas ocurre cuando todas las tareas están esperando por algún evento sin

que ninguna de las partes pueda proseguir. El segundo inconveniente se produce

cuando una tarea espera por un recurso, que si bien es liberado, nunca le es asig-

nado.

Patrones de Manejo de Eventos: Son los patrones que permiten la comunicación

distribuida entre tareas utilizando el modelo de eventos. Los eventos permiten in-

dependizar el comportamiento y las responsabilidades de los participantes de un

sistema distribuido. Se utiliza especialmente al momento de interactuar con una

capa de transporte sincrónica. En el análisis previo de los patrones se detectó una

Page 58: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

48 Patrones de diseño distribuidos Diego M.S. Erdödy

similitud en el esquema de trabajo de los distintos patrones por lo que se eligió

analizar en profundidad el patrón más representativo del grupo.

Patrones de Seguridad y Fiabilidad: Son los patrones encargados de la integri-

dad de un sistema distribuido. Proveen soluciones para mantener la integridad del

sistema ante fallos, tanto aleatorios como sistemáticos. Los fallos aleatorios se ba-

san generalmente en mal funcionamiento de hardware o condiciones externas. Los

sistemáticos en cambio, se deben habitualmente a errores en el diseño o construc-

ción del sistema. Para poder mantener la integridad, estos patrones se basan en

proveer redundancia para actuar en caso de que ocurran los fallos. Dado que el

esquema que utilizan estos patrones es muy similar en todos los casos, se tomó un

patrón en representación del grupo.

Algunos de los patrones que se han elegido, son representantes de un grupo de pa-

trones que poseen características similares. Los patrones analizados en este trabajo son:

Categoría Patrón Notas

Concurrencia

y sincroniza-

ción

Rendezvous

Observer Versión distribuida del patrón descripto por GoF

Optimistic Locking

Balking

Patrones similares:

Guarded Suspension,

Single Threaded Execution

Manejo de

Eventos Reactor

Patrones similares:

Proactor,

Acceptor,

Half Synch/ Half Asynch,

Leader/Followers

Seguridad y

Fiabilidad Watchdog

Patrones similares:

Monitor Actuator,

Sanity Check,

Safety Executive

Page 59: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Metodología de Análisis de patrones 49

5. Metodología de Análisis de patrones

5.1. Objetivos

El objetivo principal de este trabajo consta en analizar características específicas de

las implementaciones orientadas a aspectos de los distintos patrones de diseño distribui-

dos y concurrentes seleccionados y determinar las ventajas y desventajas de estas imple-

mentaciones. En este capítulo se describen los elementos a analizar en cada patrón de

diseño. También se especifica el lenguaje de modelado que se utilizará para describir la

implementación orientada a aspectos de cada caso de estudio, el cual estará basado en

UML [UML 06].

5.2. Descripción de las características a analizar

Siguiendo el trabajo de Hannemann [Han 02], las características que se analizarán

en cada caso son las que se describen a continuación.

5.2.1. Reusabilidad

Indica la posibilidad de reutilizar en otro entorno, el código fuente que compone el

patrón de diseño. En el patrón de diseño GoF “Facade” [Gam 95], por ejemplo, que cons-

ta de una clase que encapsula la complejidad interna de un componente para un usuario,

la reutilización es nula. Esto se debe a que la clase de fachada, tiene siempre lógica atada

al entorno en donde se está aplicando.

5.2.2. Transparencia de composición

La transparencia de composición se define como la habilidad de combinar patrones

de diseño sin que ello afecte el comportamiento que presenta cada uno por separado. Por

ejemplo, el patrón “Observer”, puede ser aplicado más de una vez sobre el mismo sujeto,

para exponer cambios sobre distintas propiedades. La posibilidad de aplicar el patrón

varias veces sobre el mismo sujeto, prueba que cumple con la propiedad de transparencia

de composición.

5.2.3. Independencia

El nivel de acoplamiento que hay entre los roles que componen el patrón de diseño

y las probabilidades de supervivencia que tiene cada rol fuera del patrón. Para el caso del

patrón “Singleton”, el objeto sobre el cual se aplica el patrón sigue teniendo sentido fuera

de éste. Si la implementación del patrón puede lograr dicho desacoplamiento de forma

transparente, para el objeto sobre el cual se aplicó, se dice que es independiente.

5.2.4. Localidad del código

Page 60: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

50 Metodología de Análisis de patrones Diego M.S. Erdödy

La proximidad física del código fuente que implementa el patrón de diseño. Si el

patrón de diseño puede ser implementado con una sola unidad de implementación dentro

del lenguaje elegido (por ejemplo un aspecto en el caso de AspectJ o una clase en Java)

entonces se dice que la localidad es absoluta. Si en cambio, el código se encuentra dise-

minado en varias unidades de implementación entonces la localidad es menor. Mientras

más unidades de implementación se encuentren involucradas, menor será el grado de lo-

calidad de la implementación del patrón. Para el caso de la implementación clásica del

patrón “Observer”, no existe localidad ya que la implementación se encuentra dividida en

más de un módulo (sujeto y observador).

5.3. Notación UML

La notación de diseño que se utiliza es una extensión compatible con UML 1.2 ba-

sada en el trabajo hecho por Stein [Ste 02]. La extensión definida en dicho trabajo se basa

en utilizar las herramientas de personalización del lenguaje UML, es decir, estereotipos,

etiquetas y plantillas. La incorporación de comportamiento transversal, se lleva a cabo a

través de colaboraciones que permiten vincular ambas partes. Para algunos elementos,

como las declaraciones de derivación hubo que extender el trabajo y definir la forma de

representarlos. Dichos elementos serán explicados en las siguientes secciones.

Se elige adoptar una política basada en la notación UML existente principalmente

por la disponibilidad de herramientas para trabajar y la estandarización lograda por el

lenguaje de modelado.

Para poder hacer más legibles los diagramas, se utilizó un color distinto de relleno

para cada elemento que se encuentra al mismo nivel de una clase, dependiendo del este-

reotipo que posea. Los colores elegidos son los siguientes:

Naranja para las clases. Esta es la coloración estándar.

Verde para las interfaces.

Celeste para los aspectos.

Amarillo para las introducciones.

A continuación se define la notación utilizada en este trabajo, para cada elemento

de la POA. Los ejemplos han sido tomados de los patrones que serán analizados más ade-

lante.

5.3.1. Aspect

El aspecto se representa como el estereotipo « aspect », aplicable a elementos del

tipo “clase”. Tanto el aspecto como la clase, comparten gran parte de los atributos ya que

ambos pueden tener métodos, atributos y clases internas. Sin embargo, un aspecto posee

elementos adicionales tales como el pointcut, advice o introduction. Otra diferencia es

que a un aspecto se le puede indicar la política de instanciación requerida por medio de

una etiqueta de UML, la cual llamaremos “instantiation”. El valor de dicha etiqueta con-

tiene la instrucción en AspectJ que indica el método de instanciación especificado. Para

Page 61: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Metodología de Análisis de patrones 51

hacer más visible la diferencia con una clase regular en un diagrama complejo, se utiliza

el color celeste de relleno.

El siguiente diagrama muestra un ejemplo de un aspecto llamado Pacemaker-

WatchDogSignal con una política de instanciación prefijada (pertarget).

Figura 5-1: Ejemplo de notación UML para un Aspecto

5.3.2. Pointcut

El aspecto es una clase de UML estereotipada. Por esa razón los puntos de corte se

modelarán como métodos de un aspecto, indicándolo por medio del estereotipo « pointcut

». Este estereotipo sólo se puede aplicar a métodos y el nombre del método deberá coin-

cidir con el nombre del punto de corte.

Para puntos de corte concretos, el join point se indicará por medio de la etiqueta de

UML “base”. El siguiente diagrama contiene un aspecto llamado BalkingHandler, con

un ejemplo de un punto de corte concreto:

Figura 5-2: Ejemplo de notación UML para un Pointcut

El punto de corte corresponde a la siguiente línea en AspectJ:

public pointcut executionCall() : call (void Flusher.flush());

Los puntos de corte abstractos se representarán de la misma forma que un método

abstracto (en UML se escriben en letra itálica) y sin utilizar la etiqueta “base”.

5.3.3. Advice

Los elementos del tipo advice se representarán también con estereotipos aplicados a

métodos. El nombre del método en este caso corresponderá con el tipo de advice (after,

before, etc.) precedido opcionalmente por un identificador del advice. El identificador

surge de la necesidad de que no haya dos métodos con el mismo nombre. El punto de

<<instantiation>>

<<aspect>>

PacemakerWatchDogSignal

{instantiation = pertarget(initCall(Resetable))}

<<base>> <<pointcut>>+watchableCall( r : Resetable ){base = execution (void Pacemaker+.markBeat()) && target(r)}

<<base>> <<pointcut>>+initCall( resetable : Resetable ){base = execution (void Pacemaker+.init()) && target(r)}

<<aspect>>

BalkingHandler

<<pointcut>> <<base>>+executionCall(){base = call (void Flusher.flush())}

Page 62: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

52 Metodología de Análisis de patrones Diego M.S. Erdödy

corte o la expresión compuesta por puntos de corte, será especificado como valor de la

etiqueta “base” del método.

El siguiente diagrama representa un ejemplo para este caso:

Figura 5-3: Ejemplo de notación UML para un Advice simple

La última línea indica que el aspecto BalkingProtocol posee un advice alrededor

del punto de corte executionCall(), sin especificar ningún parámetro. Esto corresponde a la

siguiente línea de AspectJ:

void around() : executionCall() { … }

Si es necesario, se pueden agregar los argumentos del advice de la misma manera

que se haría con un método. En ese caso, se deben usar dichos argumentos dentro de la

expresión indicada en la etiqueta base. El siguiente diagrama representa un ejemplo de

este caso:

Figura 5-4: Ejemplo de notación UML para un Advice con argumentos

El advice del tipo “before” de la última línea, utiliza un argumento llamado “mem-

ber” que luego es usado como parámetro para el punto de corte synchronizingCall(), sobre

el cual se aplica el advice. Esto corresponde a la siguiente línea en AspectJ:

before(RendezvousMember o) : synchronizingCall(o) { … }

5.3.4. Introduction

<<aspect>>

BalkingProtocol

-busy : boolean

<<base>> <<advice>>+around(){base = executionCall()}

<<pointcut>>+executionCall()

<<aspect>>

RendezvousProtocol

-rvs : Map<String, Rendezvous>

<<advice>> <<base>>~before( member : RendezvousMember ){base = synchronizingCall(member)}

<<setter>>+setRendezvous( groupName : String, rendezvous : Rendezvous ) : void

<<pointcut>>+synchronizingCall( member : RendezvousMember )

<<getter>>+getRendezvous( groupName : String ) : Rendezvous

Page 63: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Metodología de Análisis de patrones 53

Las introducciones de elementos en clases externas son los elementos con menor

soporte en la especificación actual de UML. Para poder representarlas se usan “colabora-

ciones” de UML. Por un lado se especifica sobre cuál de las clases se realiza la introduc-

ción, dentro del aspecto correspondiente, con una colaboración especializada con el este-

reotipo « introduction ». Dicha colaboración sólo contiene el nombre de la clase afectada.

Por otro lado se especifica una colaboración conteniendo el detalle de los elementos a

introducir sobre la clase afectada. Esto se hace agregando una clase dentro de la colabo-

ración con el nombre BaseType que contendrá los métodos o atributos a introducir. Esta

colaboración debe estar asociada a la clase o interface que está afectando para dar más

claridad al diagrama.

El siguiente es un diagrama de estructura que contiene la especificación de una in-

troducción:

Figura 5-5: Ejemplo de notación UML para una Introducción

En este ejemplo se está indicando que el aspecto RendezvousProtocol realiza una

introducción sobre la interface RendezvousMember. A esta interface, que sólo contiene el

método getGroup(), se le introduce un atributo privado llamado group y dos métodos, get-

Group() y setGroup(). Nótese que originalmente la interface sólo contenía la declaración

del método getGroup() pero en la introducción se le está agregando la implementación del

método.

5.3.5. Declare

Para representar un elemento del tipo declare, también se usa una colaboración pero

en este caso especializada con el estereotipo « declare » y se agrega el tipo de declara-

ción que se esté utilizando (parents, warning, error, soft y precedence). Dentro de la cola-

boración, se introduce el cuerpo de la declaración. Dicha colaboración deberá ir dentro

del aspecto que especifique la declaración.

<<aspect>>

RendezvousProtocol

-rvs : Map<String, Rendezvous>

<<advice>> <<base>>~before( member : RendezvousMember ){base = synchronizingCall(member)}

<<setter>>+setRendezvous( groupName : String, rendezvous : Rendezvous ) : void

<<pointcut>>+synchronizingCall( member : RendezvousMember )

<<getter>>+getRendezvous( groupName : String ) : Rendezvous<<introduction>>

RendezvousMember

BaseType

-group : String

<<setter>>+setGroup( groupName : String ) : void

<<getter>>+getGroup() : String

<<introduction>>

RendezvousMember

RendezvousMember

<<getter>>+getGroup() : String

<<crosscut>>

Page 64: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

54 Metodología de Análisis de patrones Diego M.S. Erdödy

Figura 5-6: Ejemplo de notación UML para una declaración de implementación

El ejemplo anterior indica que dentro del aspecto RendezvousHandler se especifica

una declaración que indica que la clase RoboArm implementa la interface Rendezvous-

Handler.

<<aspect>>

RendezvousHandler

<<pointcut>> <<base>>+synchronizingCall( member : RendezvousMember ){base = call (void RoboArm.executeAction()) && target(o)}

<<declare parents>>

RoboArm implements RendezvousMember

Page 65: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 55

6. Framework de Visualización

6.1. Introducción

Junto con el análisis de los distintos patrones de diseño distribuidos y concurrentes,

se ha desarrollado un framework de visualización de componentes para la mejor com-

prensión de los casos de estudio. Este framework permite visualizar, configurar y relacio-

nar los componentes pertenecientes a cada patrón y al mismo tiempo analizar los resulta-

dos de su ejecución.

6.2. Frameworks

Dada la dificultad que existe para definir un framework, se han tomado las siguien-

tes definiciones complementarias [Joh 97] [Sch 03]:

I. “diseño reutilizable completo o parcial de un sistema representado por un

conjunto de clases abstractas y la forma en que interactúan”

II. “esqueleto de una aplicación que puede ser personalizado para cumplir con

los requerimientos de un sistema”

Un framework es una de las técnicas de reutilización que existen en la POO. La di-

ferencia con otras técnicas, como los patrones de diseño, los componentes o un middle-

ware, es el contenido que permite reutilizar y la forma de llevarlo a cabo.

La primera definición indica que un framework permite reutilizar el diseño. Tam-

bién nos indica que se puede llevar a cabo a partir de clases abstractas, interfaces y/o la

interacción que existe entre los distintos componentes o unidades funcionales. Un frame-

work permite reutilizar el diseño aplicado a un dominio en particular, utilizando las técni-

cas básicas de la POO (abstracción, polimorfismo y herencia) y aplicando también las

unidades de diseño que le siguen en complejidad, o sea, los patrones de diseño. Una de

las herramientas principales que presenta un framework para la reutilización de diseño, es

la “inversión de control”. El mecanismo consiste en que los componentes provistos por el

usuario del framework, sean invocados por éste cuando sea necesario, en vez de producir-

se el flujo inverso. Dicha invocación se puede producir ante un evento externo, como por

ejemplo, la llegada de una petición HTTP en un framework de aplicaciones Web. De esta

forma, el modo en que el evento es manejado y redireccionado, es decir, el diseño del

manejo de peticiones, puede ser reutilizado y el usuario puede independizarse de su pro-

blemática.

La segunda definición, por otro lado, cubre intuitivamente el otro tipo de contenido

que un framework permite reutilizar, o sea, la funcionalidad o código. Esta funcionalidad

base o primaria es la que se implementa en el “esqueleto” que representa al framework,

junto con las bases de la interacción que debe existir entre los componentes y la forma en

que se deben distribuir los métodos.

Page 66: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

56 Framework de Visualización Diego M.S. Erdödy

En tercer lugar, un framework permite la reutilización del análisis del dominio, ya

que permite identificar rápidamente cuáles son los objetos importantes y provee una ter-

minología para enfocar el problema.

Desde el punto de vista de la reutilización, existe el concepto clásico de que los pa-

trones de diseño solamente permiten la reutilización del diseño de software. Con la intro-

ducción de la POA [Han 02], se ha demostrado que la reutilización de código a nivel de

patrón de diseño, es posible en la mayoría de los casos, por lo menos en los patrones tra-

dicionales (GoF). Dado que una implementación AOP de un patrón de diseño se modula-

riza en una biblioteca totalmente reutilizable, es necesario marcar una diferencia entre

dicha implementación y un framework. En este sentido, los elementos que componen la

implementación abstracta de un patrón de diseño, difieren de un framework principal-

mente en tamaño (un framework está compuesto por muchos patrones de diseño) y en la

carencia de dominio específico.

Si bien un framework permite la reutilización de diversos elementos, el problema

típico que padece es la alta complejidad en el diseño e implementación. Esto es fácil de

comprender si se tiene en cuenta que el objetivo es que, tanto el diseño como la imple-

mentación, puedan ser reutilizados por diversos sistemas. Es por eso que a menudo existe

una fuerte decisión de compromiso entre la flexibilidad o generalidad y la verticalidad en

los problemas que soluciona. Es decir, que mientras el framework intente resolver más

detalles de un dominio, más difícil será hacerlo lo suficientemente flexible para que sea

adecuadamente reutilizado por distintas aplicaciones.

Los frameworks pueden ser categorizados según la forma en que se deben utilizar.

Si se pueden utilizar los componentes que brinda el framework sin necesidad de conocer

su implementación, entonces se los denomina del tipo “caja negra”. Si en cambio, el fra-

mework requiere que el usuario conozca y utilice elementos de la implementación, se los

conoce como del tipo “caja blanca”. En el primer caso, por ejemplo, solo sería necesario

instanciar clases y utilizar los objetos resultantes. Un ejemplo clásico del segundo son las

extensiones de clases abstractas por parte del usuario, en donde debe conocer cuál es el

mecanismo en la implementación de dicha clase, para poder insertar la nueva funcionali-

dad correctamente. Muchos de los frameworks se encuentran en un punto intermedio en-

tre ambas categorías.

En resumen, los siguientes elementos han sido reconocidos como característicos de

un framework:

Orientado a ayudar en un dominio en particular

Representa una solución parcialmente completa para un dominio específico

que puede ser personalizada

Permite la reutilización de diseño a partir de técnicas básicas de POO y pa-

trones de diseño

Permite la reutilización de funcionalidad

Permite la reutilización de análisis del dominio

Una vez definido y analizado el concepto de framework, se describe el framework

desarrollado para este trabajo.

Page 67: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 57

6.3. Características de ACVF

El framework de visualización está implementado en forma de plug-in (o extensión)

de Eclipse 3.1+ y en esta sección se describen sus características principales.

6.3.1. Orientación a Componentes

El framework desarrollado, se denomina “orientado a componentes” ya que el

componente es el elemento atómico fundamental, que representa visualmente un rol o un

actor dentro del caso de estudio. El segundo elemento importante dentro del framework,

es el diagrama, en donde los componentes pueden ser desplegados y asociados entre sí a

través de relaciones. Una vez desplegados, relacionados y configurados apropiadamente,

el diagrama puede ser “ejecutado” a través de una simulación, la cual mostrará a los

componentes interactuar entre sí.

El plug-in que se desarrolló como implementación del framework, posee una paleta

principal asociada al diagrama, que contiene una lista de los componentes disponibles,

agrupados por categorías, como muestra el ejemplo en la siguiente figura:

Figura 6-1: Paleta de componentes

Los componentes pueden ser arrastrados al diagrama para armar un entorno que re-

presente el patrón a estudiar.

Cada componente puede tener asociados los siguientes tipos de elementos:

Page 68: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

58 Framework de Visualización Diego M.S. Erdödy

Propiedades comunes: Son atributos comunes para todos los componentes que

controlan la visualización básica. Se pueden observar y modificar en la vista de

propiedades de Eclipse.

Nombre: Nombre identificador del componente

Posición: Valores absolutos de las componentes X e Y dentro del diagra-

ma.

Tamaño: Valores de ancho y alto del componente donde corresponda.

Color: Color de fondo del componente para hacer más sencilla la visuali-

zación.

Modo Interactivo: Propiedad booleana que especifica si el componente va

a ser ejecutado en modo interactivo o no. Más adelante se detalla el signi-

ficado del modo interactivo.

Figura 6-2: Propiedades comunes a todos los componentes

Propiedades propias del componente: Son propiedades inherentes al componente.

Estas se pueden dividir en dos tipos:

Estáticas: Atributos que controlan el comportamiento del componente y

son de escritura/lectura. Se visualizan dentro del panel de propiedades bajo

una agrupación particular en forma de pestaña. Puede haber más de una

agrupación. El siguiente es un ejemplo de las propiedades estáticas de un

componente del tipo “RoboArm”.

Figura 6-3: Propiedades particulares para el componente RoboArm

Page 69: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 59

Dinámicas: Propiedades de salida del componente cuya evolución se pue-

de apreciar a lo largo de una simulación, interactiva o no, en tiempo real.

Se visualizan dentro del componente mismo. La siguiente figura muestra

un componente del tipo “OptimisticRecord” con tres propiedades dinámi-

cas, denominadas “id”, “attrib” y “version”.

Figura 6-4: Ejemplo de un Componente

Acciones: Son pedidos que se le pueden hacer al componente en el modo de si-

mulación interactiva. Están representados por un botón dentro del componente. La

figura anterior muestra un componente con dos acciones denominadas “save” y

“retrieve”. Vale la pena aclarar que solo los componentes que posean acciones,

pueden ejecutarse en modo interactivo, ya que de lo contrario no habría forma de

interactuar con el componente.

Consola: Panel dentro del componente en donde se muestran mensajes informati-

vos de su estado. La siguiente figura muestra un ejemplo de información mostrada

en la consola de dos componentes:

Figura 6-5: Relaciones entre Componentes

Representación gráfica: Cada componente puede reflejar su estado también por

medio de una representación gráfica. Dicha representación constituye un modelo

gráfico del componente que provee una respuesta visual a los cambios de estado y

hace al componente más intuitivo y didáctico.

Page 70: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

60 Framework de Visualización Diego M.S. Erdödy

La siguiente es una vista de la edición de un diagrama con varios componentes interac-

tuando entre sí.

Figura 6-6: Ejemplo de un diagrama con varios componentes y relaciones

6.3.2. Relaciones

Cada componente interactúa con otros por medio de relaciones. Las relaciones se

indican con flechas dirigidas que unen componentes. Cada componente tiene habilitada la

interacción con un conjunto de tipos de componentes en particular, por lo general son los

que pertenecen al mismo grupo de la paleta de componentes. Esto quiere decir que un

componente puede relacionarse sólo con otro componente que sea de un tipo específico.

Por ejemplo, un registro optimista se puede relacionar con una tabla, pero no con un bra-

zo robótico. Por otro lado, hay casos en que un componente puede relacionarse con más

de un componente. En otros casos la relación puede ser sólo uno a uno.

6.3.3. Simulación

Page 71: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 61

El objetivo del diagrama es que los componentes puedan ejecutarse, interactúen en-

tre si y que dicha interacción sea visible. La simulación se inicia con el botón “Run” de la

barra de herramientas, que se habilita cuando se está editando un diagrama. Una vez ini-

ciada la simulación, se puede detener con el botón “Stop”.

Cuando la simulación se está ejecutando, cada componente se comporta de la mane-

ra preestablecida a partir de los valores proporcionados para sus propiedades específicas.

Esto quiere decir que es en este momento en donde entra en juego la lógica propia de

cada componente.

Ciertos componentes tienen dos modos de actuar frente a una simulación: preesta-

blecido o interactivo.

En el modo preestablecido, el componente ejecuta la rutina que tiene prefijada y

el usuario sólo puede ver su comportamiento pero no puede interactuar con el

componente.

En el modo interactivo el componente espera a que el usuario ejecute alguna de

sus acciones.

Sólo los componentes que tienen definidas acciones, tienen la propiedad “Interacti-

ve” en donde se puede definir el modo de ejecución.

Por ejemplo, para el caso de estudio del patrón “optimistic locking”, se dispone de

dos componentes: la tabla y el registro. Un registro se puede asociar a una tabla. La tabla

no posee modo de simulación interactiva dado que no posee acciones, sólo se puede vi-

sualizar el contenido. En cambio, el registro posee un modo interactivo ya que se puede

interactuar con el componente, pidiéndole por ejemplo que almacene su valor local en la

tabla asociado que lo obtenga de la tabla.

6.3.4. Vista de resumen

El panel de vista de resumen (“outline” en inglés) provee un listado de los compo-

nentes existentes en el diagrama. La lista contiene el nombre de cada componente prece-

dido por el tipo de componente. De esta forma se puede acceder rápidamente a un com-

ponente en particular haciendo doble click en el elemento deseado.

Figura 6-7: Vista de resumen

Page 72: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

62 Framework de Visualización Diego M.S. Erdödy

6.4. Arquitectura y Diseño

El framework provee interfaces y clases de ayuda para la creación de componentes.

Las clases abstractas provistas encapsulan el comportamiento por defecto, con el objetivo

de minimizar la cantidad de código necesario para implementar un componente relativa-

mente sencillo.

El framework está implementado sobre la base del subproyecto de Eclipse denomi-

nado GEF (Graphical Editing Framework). GEF es un framework que ayuda al desarrollo

de editores gráficos y a su vez, está basado sobre Draw2D. Este último es un estándar en

el modelado en dos dimensiones y representa una capa de abstracción sobre la biblioteca

de Eclipse denominada SWT (Standard Widget Toolkit).

La siguiente figura muestra un resumen de la interacción de las distintas capas y sus

funcionalidades principales:

Figura 6-8: Capas de la arquitectura del Framework y sus características principales

GEF implementa el patrón Model-View-Controller para el desarrollo de editores

gráficos y por ende permite una clara separación de responsabilidades. También permite

GEF

SWT

Draw2D

CVF

Contiene el modelo de componentes e

interacciones

Soporta el uso de simulaciones

Incorpora figuras para visualización y manejo

de componentes

Implementa los patrones de diseño

distribuídos y concurrentes estudiados

Responsable del renderizado de figuras y

conexiones

Permite el control de presentación de figuras

Posee un sistema de coordenadas flexible

Permite el ajuste de tamaño

Implementa MVC de editores gráficos

Se integra con el Workbench de Eclipse

(acciones, menúes, barra de herramientas,

etc).

Permite la interacción entre el usuario y la

representación visual del modelo

Biblioteca nativa para interfaces gráficas de

la plataforma Eclipse

Utiliza los controles nativos del sistema

operativo siempre que sea posible

Page 73: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 63

una integración con el Workbench de Eclipse lo que posibilita el manejo de diagramas

dentro de un entorno integrado.

6.4.1. GEF Framework

GEF pone énfasis en desacoplar las distintas capas de un editor gráfico y brinda es-

pecial soporte para la implementación del controlador. En GEF, el controlador es el en-

cargado, entre otras cosas, de hacer de intermediario entre la vista y el modelo. El esque-

ma de trabajo de alto nivel es el siguiente:

Figura 6-9: Interacción entre las distintas capas MVC del framework

A continuación se detalla cada una de las capas:

Modelo

El Modelo consta de la información de base que interesa almacenar en un editor. La

información que contenga el Modelo es la que va a ser persistida al momento de guardar

o cerrar un editor y con la que se contará al momento de abrirlo.

Si bien GEF no pone restricciones en cuanto a las interfaces o clases abstractas que

debe extender el Modelo, es necesario que dicho Modelo cuente con un mecanismo para

notificar adecuadamente sus cambios a terceras partes. Este mecanismo es necesario para

que el Controlador pueda actuar al momento de registrar un cambio en el Modelo.

Dado que GEF no suministra ninguna clase base para el armado del modelo, se con-

feccionó una clase abstracta denominada BaseElement, la cual brinda las características

principales comunes para todos los elementos del modelo. Una de las características más

importantes, es la posibilidad de registrarse para ser notificado ante el cambio de cual-

quiera de las propiedades del elemento, como se verá más adelante.

Vista

(IFigure)

Controlador

(EditPart)Modelo

(BaseElement)

Notificaciones

GUI

Usuario

Comandos

Page 74: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

64 Framework de Visualización Diego M.S. Erdödy

Los cambios realizados sobre el modelo por parte del Controlador (generalmente a

pedido del usuario) son representados por Comandos. Los comandos, sólo deben conocer

la existencia del modelo (es por eso que se pueden considerar una extensión de éste), y

deben contener la lógica para efectuar o deshacer los cambios requeridos por el Controla-

dor.

Vista

La Vista compone la capa visual del editor. Dada la gran separación entre capas que

propone GEF, la vista no puede conocer o hacer referencia a ningún objeto del modelo, ni

tampoco tener lógica asociada al editor. Sí debe contener información propia de la repre-

sentación visual de los elementos que se pretenden graficar.

GEF utiliza Draw2D como capa visual base y en ella, el elemento atómico es la fi-

gura, representada por la interface IFigure. Draw2D provee una amplia gama de figuras

elementales prediseñadas y la composición entre ellas permite un amplio espectro de po-

sibilidades con un mínimo esfuerzo. Por lo general, un elemento del modelo tiene una

asociado una figura de la Vista, aunque no es una limitación del framework.

Controlador

El Controlador tiene el papel de mediador entre el usuario, la vista y el modelo. En

GEF, el controlador es llamado EditPart.

Principalmente, actúa de observador del modelo, reflejando los cambios en la vista

cuando es necesario. Por lo general existe un EditPart por cada elemento del modelo

(aunque no es una limitación), y entre los distintos EditParts se forma una estructura de

árbol, siendo el nodo raíz el correspondiente al diagrama.

Los EditParts también son los encargados de administrar los pedidos de cambio del

usuario, denominados Requests, y transformarlos en Comandos. Por ejemplo para el tipo

de pedido “delete” (borrar), la política de edición deberá identificar el tipo elemento a

borrar y crear el comando de borrado, correspondientemente. La administración también

consta de aceptar, ignorar o rechazar los Requests, a través de clases que encapsulan las

políticas de edición.

6.4.2. ACVF Framework

El ACVF está basado en GEF, y por lo tanto provee extensiones de cada una de las

capas MVC.

Modelo

El modelo de ACVF consta de una clase abstracta base que contiene el comporta-

miento común a todos los elementos, como el soporte de propiedades, ser “serializable” y

la habilidad de ser “observable”. Luego existe un elemento raíz, que representa el dia-

grama y que contiene una lista de los elementos que lo componen. Estos elementos pue-

den ser Componentes o Conexiones. Vale la pena aclarar que el framework deja abierta la

Page 75: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 65

posibilidad de incorporar nuevos tipos de elementos en caso de querer extender el editor,

como por ejemplo, etiquetas de texto, figuras para dibujo libre, etc.

El siguiente es el diagrama de estructura con una descripción de los elementos prin-

cipales:

Figura 6-10: Capa de Modelo de ACVF

BaseElement: Clase abstracta que contiene la funcionalidad común de todos los

elementos del modelo como el soporte de propiedades, de ser observable y la ca-

pacidad de ser serializable para poder mantener un estado persistente. Los méto-

dos que provee la clase son:

addPropertyChangeListener(), removePropertyChangeListener(): Permiten agregar o

quitar un “Observador” de los cambios de valores de las propiedades del ele-

mento, a través de la interface PropertyChangeListener, que contiene un

método para informar dicho tipo de eventos. getPropertyValue(), setPropertyValue(), getPropertyDescriptors(), isPropertySet(), re-

setPropertyValue(): Métodos asociado al manejo de propiedades de los elemen-

ComponentElement

<<JavaElement>> <<setter>>+setPropertyValue( propertyId : Object, value : Object ) : void{JavaAnnotations = @Override}

<<JavaElement>> <<getter>>+getPropertyDescriptors() : IPropertyDescriptor"[]"{JavaAnnotations = @Override}

<<JavaElement>> <<getter>>+getPropertyValue( propertyId : Object ) : Object{JavaAnnotations = @Override}

<<constructor>>+ComponentElement( pc : PatternComponent )

<<getter>>+getRunnable() : ComponentRunnable

<<getter>>+getComponent() : PatternComponent

<<setter>>+setInteractive( value : boolean ) : void

<<setter>>+setRunning( value : boolean ) : void

<<getter>>+getThreadGroup() : ThreadGroup

<<setter>>+setStatus( value : String ) : void

<<getter>>+getInteractive() : boolean

<<getter>>+getTypeName() : String

<<getter>>+getRunning() : boolean

<<getter>>+getAllowedSources()

<<getter>>+getStatus() : String

<<getter>>+getIcon() : Image

+toString() : String

+preStart() : void

+start() : void

+stop() : void

...

BaseElement

...

+removePropertyChangeListener( l : PropertyChangeListener ) : void{guarded}

+addPropertyChangeListener( l : PropertyChangeListener ) : void{guarded}

<<setter>>+setPropertyValue( id : Object, value : Object ) : void

<<getter>>+getPropertyDescriptors() : IPropertyDescriptor"[]"

<<getter>>+getPropertyValue( id : Object ) : Object

<<getter>>+isPropertySet( id : Object ) : boolean

<<getter>>+getEditableValue() : Object

+resetPropertyValue( id : Object ) : void

...

Element

<<setter>>+setPropertyValue( propertyId : Object, value : Object ) : void

<<getter>>+getPropertyDescriptors() : IPropertyDescriptor"[]"

<<getter>>+getSourceConnections() : List<E->Connection>

<<getter>>+getTargetConnections() : List<E->Connection>

<<getter>>+getPropertyValue( propertyId : Object ) : Object

<<setter>>+setLocation( newLocation : Point ) : void

<<setter>>+setSize( newSize : Dimension ) : void

<<setter>>+setColor( newColor : RGB ) : void

<<setter>>+setName( name_ : String ) : void

<<getter>>+getSize() : Dimension

<<getter>>+getLocation() : Point

<<getter>>+getName() : String

<<getter>>+getIcon() : Image

<<getter>>+getColor() : RGB

...

Connection

<<constructor>>+Connection( source : Element, target : Element )

+reconnect( newSource : Element, newTarget : Element ) : void

<<setter>>+setPropertyValue( id : Object, value : Object ) : void

<<getter>>+getPropertyValue( id : Object ) : Object

<<setter>>+setLineStyle( lineStyle : int ) : void

<<getter>>+getSource() : Element

<<getter>>+getTarget() : Element

<<getter>>+getLineStyle() : int

+disconnect() : void

+reconnect() : void

PatternWorkbenchDiagram

<<getter>>+getChildren() : List<E->Element>

+addChild( elem : Element ) : boolean

+removeChild( s : Element ) : boolean

Page 76: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

66 Framework de Visualización Diego M.S. Erdödy

tos (obtener el valor de una propiedad determinada, cambiar el valor, obtener

la lista de descriptores de propiedades, consultar si la propiedad tiene algún

valor y limpiar el valor de una propiedad, respectivamente). Si bien esta clase

no define ningún tipo de propiedades, implementa los métodos con valores por

defecto para poder ser referenciados por las clases derivadas que componen el

modelo.

PatternWorkbenchDiagram: Elemento raíz del modelo que actúa de contenedor

del resto de los elementos. Los métodos provistos son:

addChild(), removeChild(), getChildren(): Métodos de acceso a los elementos hijo

del modelo. Permiten agregar, quitar u obtener los hijos, respectivamente.

Connection: Representa una conexión dirigida entre dos elementos del modelo, el

origen (source) y el destino (target). Posee además una propiedad que representa

el tipo de conexión que se visualizará (sólida, punteada, etc.). Los métodos prin-

cipales son:

Connection(): La conexión debe construirse indicando los elementos origen y

destino.

disconnect(), reconnect(): Permiten indicar a los elementos que están asociados

por esta conexión, que dicho vínculo debe eliminarse o volverse a establecer.

getSource(), getTarget(): Métodos de acceso a los elementos origen y destino.

Element: Clase abstracta que incorpora el comportamiento de un elemento del

modelo genérico, visible gráficamente. Cuenta con referencias a las conexiones de

las que participa y métodos para acceder a dichas conexiones. Además posee pro-

piedades y métodos de acceso para los siguientes atributos:

height, width: Dimensiones del elemento, en alto y ancho.

xpos, ypos: Posición del elemento dentro del diagrama (coordenadas X e Y).

color: Color distintivo del elemento (para distinguir los elementos del mismo

tipo de una manera sencilla y visual).

instanceName: Nombre del elemento que lo identificará en el diagrama.

ComponentElement: Elemento del modelo principal de ACVF que representa un

componente. Cuenta con las siguientes propiedades:

running: Indica que el componente se encuentra ejecutando la simulación.

status: Texto que muestra el estado en el componente.

interactive: Modo en que se ejecutará la simulación.

Además, posee los siguientes métodos:

Page 77: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 67

getComponent(): Devuelve la instancia de la clase PatternComponent asociada a

este componente. Dentro de dicha instancia se almacena la información del

componente, provista por el usuario del framework.

getRunnable(): Devuelve el objeto de simulación que se ejecutará cuando se ini-

cie la simulación del diagrama.

getTypeName(): Indentificador único del componente.

getAllowedSources(): Devuelve una lista con los tipos de componentes que se

pueden conectar con este componente.

getIcon(): Obtiene el icono a utilizar en las representaciones visuales del com-

ponente.

start(): Inicia el flujo de simulación para este componente.

preStart(): Preinicialización del componente, inmediatamente previo al inicio

de la simulación. La tarea típica de preinicialización de un componente es cre-

ar la instancia del objeto de simulación.

stop(): Detiene la ejecución de la simulación para este componente.

Más adelante se explica en detalle el ciclo de vida de una simulación, resumido en

un diagrama de secuencia.

Vista

La vista es la capa responsable de representar visualmente el estado del modelo.

Debe ser actualizada cada vez que el modelo cambie, ya sea por acción de la interacción

con el usuario o por cambios internos. La vista no debe almacenar información sobre el

modelo y solamente debe poseer el comportamiento asociado a la visualización.

Para la implementación del framework, la vista se compone de dos elementos prin-

cipales: los componentes y las conexiones entre ellos. Los componentes se representan

con figuras similares a las de una clase en UML y se dividen en secciones denominadas

compartimientos. Los compartimientos disponibles para un componente son:

Figura 6-11: Compartimientos del componente

Acciones del componente

Figura personalizada del componente

Estado del componente

componente

Propiedades dinámicas del componente

componente

Encabezado del componente (Color,

Tipo y nombre de instancia)

Page 78: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

68 Framework de Visualización Diego M.S. Erdödy

El siguiente es un diagrama de estructura que representa el diseño de la vista utili-

zado y una descripción de su composición:

Figura 6-12: Capa de Vista de ACVF

IFigure, Figure: Interface que define el comportamiento de una figura en

Draw2D y su implementación abstracta.

CompartmentFigure: Figura que representa un compartimiento dentro del

rectángulo principal. Es muy similar a la representación en UML de una clase, en

la cual un compartimiento agrupa elementos de naturaleza semejante, como ser

atributos o acciones del componente.

ComponentFigure: Figura que representa un componente. Posee los siguientes

métodos:

ComponentFigure(): Constructor de la figura. Debe recibir como parámetros, el

nombre del componente junto con la figura personalizada que lo representa.

setMsgEnabled(): Indica el estado en que deben estar los botones que represen-

tan las acciones. El estado puede ser “habilitado” o “deshabilitado”.

setStatus(): Especifica un mensaje de estado pasado como parámetro de texto,

que se debe mostrar dentro del componente.

addProperty(): Agrega una propiedad al compartimiento correspondiente.

setPropertyValue(): Especifica el valor que debe tener una propiedad previamen-

te adicionada.

addMessage(): Agrega una acción al componente. Los parámetros que requiere

son el método a ejecutar y el observador que se encargará de ejecutar dicho

método cuando se dispare la acción.

setBackgroundColor(): Establece el color de fondo del componente.

Controlador

ComponentFigure

<<JavaElement>> <<setter>>+setBackgroundColor( bg : Color ) : void{JavaAnnotations = @Override}

<<setter>>+setPropertyValue( prop : String, newValue : Object, oldValue : Object ) : void

<<constructor>>+ComponentFigure( name : Label, custFig_ : IFigure )

+addMessage( msg : Method, actList : ActionListener ) : void

<<setter>>+setMsgEnabled( value : boolean ) : void

<<setter>>+setStatus( st : String ) : void

+addProperty( msg : Method ) : void

...

CompartmentFigure

~layout : ToolbarLayout = new ToolbarLayout()

<<constructor>>+CompartmentFigure()

<<setter>>+setAlign( al : int ) : void

IFigure

(org.eclipse.draw2d) Figure

(org.eclipse.draw2d)

Page 79: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 69

La capa del controlador de ACVF consta básicamente de un EditPart por cada ele-

mento del modelo. Para poder actuar en caso de que alguna de las propiedades de los

elementos del modelo cambie, los EditParts implementan la interface PropertyChange-

Listener para poder registrarse como observadores de dichas propiedades. La interface

PropertyChangeListener forma parte de la biblioteca integrada de Java y posee un método

“propertyChange” que es llamado por el objeto observable cada vez que se produce un

cambio sobre los atributos observados, para poder notificar a los observadores. El dia-

grama de estructura y el detalle de los elementos es el siguiente:

Figura 6-13: Capa de Controlador de ACVF

AbstractGraphicalEditPart, AbstractConnectionEditPart: Clases abstractas que

implementan la funcionalidad común de un EditPart gráfico en general y de co-

nexión en particular, respectivamente. Los métodos principales que provee son:

activate(): Indica que el controlador ha sido activado y permite llevar a cabo ta-

reas de inicialización como la registración en calidad de observador al elemen-

to del modelo correspondiente.

deactivate(): Marca la finalización del ciclo de vida del controlador, para poder

realizar tareas de limpieza.

createEditPolicies(): Se crean las políticas de edición, que son básicamente las

encargadas de convertir los pedidos del usuario (requests) en comandos enten-

dibles por el modelo.

createFigure(): Método destinado a la construcción de la figura que representará

gráficamente al componente.

ElementEditPart

<<getter>>+getSourceConnectionAnchor( connection : ConnectionEditPart ) : ConnectionAnchor

<<getter>>+getTargetConnectionAnchor( connection : ConnectionEditPart ) : ConnectionAnchor

<<getter>>+getSourceConnectionAnchor( request : Request ) : ConnectionAnchor

<<getter>>+getTargetConnectionAnchor( request : Request ) : ConnectionAnchor

-refreshProperty( prop : String, newValue : Object, oldValue : Object ) : void

<<getter>>#getConnectionAnchor() : ConnectionAnchor

+propertyChange( evt : PropertyChangeEvent ) : void

<<getter>>-getCastedModel() : ComponentElement

<<getter>>-getCastedFigure() : ComponentFigure

<<getter>>#getModelSourceConnections() : List

<<getter>>#getModelTargetConnections() : List

+actionPerformed( event : ActionEvent ) : void

<<getter>>+getColor( rgb : RGB ) : Color

-createFigureForModel() : IFigure

#createEditPolicies() : void

#refreshRunning() : void

#createFigure() : IFigure

#refreshVisuals() : void

#refreshStatus() : void

+deactivate() : void

+activate() : void

DiagramEditPart

<<getter>>-getCastedModel() : PatternWorkbenchDiagram

+propertyChange( evt : PropertyChangeEvent ) : void

<<getter>>#getModelChildren() : List

#createEditPolicies() : void

#createFigure() : IFigure

+deactivate() : void

+activate() : void

PropertyChangeListener

+propertyChange( event : PropertyChangeEvent ) : void

ConnectionEditPart

+propertyChange( event : PropertyChangeEvent ) : void

<<getter>>-getCastedModel() : Connection

#createEditPolicies() : void

#createFigure() : IFigure

+deactivate() : void

+activate() : void

AbstractConnectionEditPart

AbstractGraphicalEditPart

Page 80: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

70 Framework de Visualización Diego M.S. Erdödy

DiagramEditPart: Controlador que representa al diagrama en su totalidad. Juega

el papel de nodo raíz en la jerarquía de controladores y brinda la política de edi-

ción que permite resolver los distintos tipos de elementos del diagrama. Agrega

los siguientes métodos, aparte de la personalización de los provistos por las clases

base:

getModelChildren(): Permite acceder a los elementos del modelo del primer ni-

vel, por debajo del nodo raíz.

getCastedModel(): Obtiene la referencia al elemento raíz del modelo transfor-

mado al tipo correcto.

ElementEditPart: Controlador principal del framework, encargado de la media-

ción entre la capa de vista y modelo de cada componente del diagrama. Los méto-

dos adicionales provistos son:

getModelSourceConnections(), getModelTargetConnections(): Métodos para acceder

a la lista de conexiones entrantes o salientes del componente, respectivamente.

getSourceConnectionAnchor() y derivados: Especifica el tipo de terminación que

tendrá la conexión.

propertyChange(), refresh*(): Método que indica que una propiedad ha cambiado

en el componente asociado. Para actualizar la capa visual de los tipos de pro-

piedades conocidos se invoca al método refresh correspondiente.

actionPerformed(): Ejecuta la acción especificada sobre el componente.

ConnectionEditPart: Controlador para las conexiones entre componentes.

Componentes

La capa de componentes brinda la funcionalidad común a la administración de los

componentes. Algunos ejemplos de las dicha funcionalidad son: el descubrimiento de

propiedades dinámicas y acciones, vinculación automática de las propiedades, manejo del

ciclo de vida de la simulación y ayuda para la representación gráfica.

También establece una interface con la información que necesita de cada compo-

nente adicional que se desee agregar al framework.

El diagrama de estructura y la descripción de los elementos principales es el si-

guiente:

Page 81: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 71

Figura 6-14: Capa de Componentes de ACVF

PatternComponent: Es la interface que define las operaciones que debe imple-

mentar un componente para cumplir con los requerimientos del framework. Los

métodos necesarios son:

getType(): Debe proveer la identificación única del tipo de componente, en

forma de texto.

getRunnableClass(): Especifica la clase que hará de objeto ejecutable durante la

simulación y se encargará de representar visualmente el estado a lo largo del

tiempo. Dicha clase debe implementar la interface ComponentRunnable.

createRunnable(): Método encargado de crear el objeto de ejecución del compo-

nente.

postCreate(): Método que se ejecuta una vez que ha sido creado el objeto ejecu-

table e inmediatamente posterior a iniciar la simulación.

getLinkSources(): Provee un grupo de tipos de componentes que pueden conec-

tarse como origen a este componente.

getLinkDestinations(): Provee un grupo de tipos de componentes que pueden co-

nectarse como destino a este componente.

getActions(): Especifica el conjunto de acciones que se pueden ejecutar sobre

este componente.

getPropertyDescriptors(): A través de este método se especifican las propiedades

que publicará el componente.

getPropertyValue(): Método para obtener el valor de una propiedad publicada.

setPropertyValue(): Método para establecer el valor de una propiedad publicada.

getFigure(): Especifica la figura que representará visualmente al componente.

PatternComponent

<<setter>>+setPropertyValue( propertyId : Object, value : Object ) : void

<<getter>>+getRunnableClass() : Class<T->ComponentRunnable>

<<setter>>+setElement( element : ComponentElement ) : void

<<getter>>+getPropertyDescriptors() : IPropertyDescriptor"[]"

<<getter>>+getPropertyValue( propertyId : Object ) : Object

+postCreate( runnable : ComponentRunnable ) : void

<<getter>>+getIconSmall() : ImageDescriptor

<<getter>>+getIconLarge() : ImageDescriptor

+createRunnable() : ComponentRunnable

<<getter>>+getActions() : List<E->Method>

<<getter>>+getLinkDestinations()

<<getter>>+getFigure() : IFigure

<<getter>>+getLinkSources()

<<getter>>+getType() : String

AbstractComponent

<<getter>>#getSources( type : String ) : Set<E->ComponentElement>

<<getter>>#getTargets( type : String ) : Set<E->ComponentElement>

<<setter>>+setElement( element_ : ComponentElement ) : void

+propertyChange( arg0 : PropertyChangeEvent ) : void

+postCreate( runnable : ComponentRunnable ) : void

<<getter>>+getElement() : ComponentElement

<<getter>>+getActions() : List<E->Method>

+createRunnable() : ComponentRunnable

<<getter>>+getLinkDestinations()

<<getter>>+getFigure() : IFigure

<<getter>>+getLinkSources()

<<introduction>>

ComponentRunnable

ComponentRunnable

<<setter>>+setElement( element : ComponentElement ) : void

<<setter>>+setDisplay( display : Display ) : void

<<getter>>+getElement() : ComponentElement

<<getter>>+getDisplay() : Display

+stopComponent() : void

BaseType

-element : ComponentElement

-display : Display

+setElement( element : ComponentElement )

+getElement() : ComponentElement

+setDisplay( display : Display )

+writeAsync( text : String )

+getDisplay() : Display

<<aspect>>

ComponentRunnableImpl

...

<<introduction>>

ComponentRunnable

ComponentN UIComponent2 UIComponent1 UIComponent NComponent1 Component2...

Page 82: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

72 Framework de Visualización Diego M.S. Erdödy

getIconSmall(): Representación iconográfica del componente, en su versión pe-

queña. Se utiliza para mostrar en las listas como, por ejemplo, la paleta o el

sumario.

getIconLarge():Representación iconográfica del componente, en su versión au-

mentada. Se utiliza para mostrar en el diagrama.

setElement(): Le asigna el elemento de la capa de modelo, para poder obtener

información como, por ejemplo, los componentes conectados.

AbstractComponent: Implementa las operaciones básicas de un componente

haciendo mucho más sencilla la tarea de crear un nuevo componente.

getLinkSources(): Devuelve un grupo vacío.

getLinkDestinations(): Devuelve un grupo vacío.

setElement(): Asigna el elemento de modelo a un atributo protegido para poder

ser usado por las clases derivadas.

getElement(): Acceso al elemento de modelo.

getFigure(): Devuelve la figura por defecto.

getTargets(),getSources(): Devuelve una lista de los elementos del modelo que

actúan en una conexión como destino u origen, respectivamente,.

postCreate(): Por defecto, especifica el atributo “element” en el objeto de simu-

lación. También asigna el “display” activo, para poder utilizarlo dentro de la

simulación al hacer llamadas asíncronas, ya que se deben correr en un hilo de

ejecución distinto al principal.

propertyChange(): Implementación vacía del método, en el caso que no se re-

quieran propiedades.

createRunnable():Instancia un nuevo objeto de la clase devuelta por getRunna-

bleClass() llamando al constructor por defecto (sin argumentos).

getActions(): Por defecto, devuelve la lista de métodos de la clase definida por

getRunnableClass() que están modificados con la anotación “Action”.

ComponentRunnable: Es la interface que especifica la interacción con los objetos

que implementarán el comportamiento dinámico del componente, utilizado en el

momento de la simulación.

stopComponent(): Método para poder detener el objeto de simulación.

setElement(), getElement(): Permite especificar u obtener el objeto del modelo

asociado al componente.

setDisplay(),getDisplay(): Permite especificar u obtener el “display” a utilizar pa-

ra realizar las operaciones que impliquen cambios visuales.

ComponentRunnableImpl: Es el aspecto que implementa la interface Compo-

nentRunnable. De esta forma se utiliza el mecanismo que provee AOP para poder

asociar comportamiento directamente a una interface. Es un mecanismo similar a

la herencia múltiple pero implementado de forma más natural.

Page 83: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 73

Anotaciones Utilizadas

El ACVF utiliza anotaciones de Java 1.5 para identificar de forma clara, ciertos

atributos de los componentes. Las anotaciones introducidas por ACVF son:

Action: Se aplica a los métodos de los objetos de simulación (los que imple-

mentan ComponentRunnable) que se deseen publicar como acciones del

componente. El método getActions() de la clase AbstractComponent, obtiene

los métodos que estén marcados con esta anotación y los devuelve para ser

incluidos en el compartimiento correspondiente de la representación gráfica.

DynamicProperty: Se aplica a los métodos del tipo “setter” de los objetos de

simulación cuyo atributo se desee publicar dinámicamente. Esto implica que

el atributo aparecerá en el compartimiento de propiedades dinámicas de la

vista y su valor podrá ser seguido visualmente en tiempo de simulación.

Property: Diseñado para ser aplicado a los atributos del componente que se

deseen mostrar en el panel de propiedades. Dichos atributos componen la

configuración del componente. Posee los siguientes argumentos:

o name: identificador único interno de la propiedad.

o description: descripción a mostrar en el panel de propiedades

o caption: nombre de la propiedad

o category: nombre de la categoría del panel de propiedades en donde

se ubicará la propiedad.

Interacción de las distintas capas en la ejecución de un Componente

En el siguiente diagrama se muestra la interacción entre los distintos elementos de

cada capa MVC, para el movimiento de un componente dentro de un diagrama.

Figura 6-15: Diagrama de secuencia para el movimiento de un componente

VISTA CONTROLADOR MODELO

: ElementSetConstraintCommand

: ElementXYLayoutEditPolicy : Element : ComponentFigure: ElementEditPartGEF GEF

redo()4:

setSize(newSize=)5:

setLocation(newLocation=)10:

(Element, )2:

firePropertyChange(property=, oldValue=, newValue=)6:

propertyChange(evt=)7:

refreshVisuals()8:

setBounds(rectangle=)9:

createChangeConstraintCommand(child=, constraint=)1:

execute()3:

Page 84: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

74 Framework de Visualización Diego M.S. Erdödy

Los pasos se pueden dividir en dos grupos, por un lado la creación del comando,

que se realiza al iniciar el movimiento del componente dentro del diagrama (pasos 1 y 2),

y por otro lado la ejecución del comando, realizada al “soltar” el componente (pasos del 3

al 10). A su vez, los elementos que intervienen en la interacción se dividen en tres grupos

correspondientes a las distintas capas MVC, como lo indica el diagrama.

1) El framework GEF, invoca a la política de edición (EditPolicy) provista por

ACVF, requiriéndole la creación de un comando del tipo “ChangeCons-

traint”, correspondiente al pedido del usuario de cambiar la posición del

componente.

2) El EditPolicy crea el comando correspondiente, pasándole como parámetro

una referencia del elemento en cuestión.

3) Un vez establecido el nuevo lugar del componente (cuando el usuario lo

“suelta” dentro del diagrama, el framework GEF envía un mensaje al co-

mando para que se ejecute.

4) Internamente, el comando invoca al método “redo” que contiene la lógica de

ejecución del comando.

5) El comando le informa el nuevo tamaño al elemento, a través del mensaje

setSize().

6) El cambio en el valor de la propiedad del elemento, dispara la notificación

de todos los observadores registrados al elemento.

7) El EditPart asociado al elemento, al ser uno de los observadores, es notifi-

cado del nuevo valor a través del mensaje propertyChange().

8) El EditPart, al enterarse del cambio de valor, invoca al método que infor-

mará a la capa visual de dicho cambio, llamado refreshVisuals().

9) El controlador informa el cambio a la figura que representa el componente,

enviando el mensaje setBounds()

10) El proceso se repite para el atributo “location”.

A continuación se describe la interacción que se produce al momento de iniciar una

simulación dentro del diagrama ACVF:

Page 85: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 75

Figura 6-16: Diagrama de secuencia para el inicio de la simulación

1) El usuario hace click en el botón de “Run” de la barra de herramientas para

iniciar la simulación.

2) La acción asociada al botón “Run” obtiene una referencia al editor y le en-

vía un pedido de inicio de simulación.

3) El editor, itera sobre todos los elementos hijos del modelo del tipo Compo-

nentElement y les envía un mensaje de preinicialización.

4) En este paso, el elemento del modelo invoca al componente para crear el ob-

jeto de simulación.

5) Internamente, la instancia del componente, obtiene la clase que va a repre-

sentar al objeto de simulación (patrón Template Method).

6) El objeto de simulación es instanciado, utilizando el mecanismo de re-

flexión.

7) Nuevamente el editor itera sobre todos los elementos hijos del modelo del

tipo ComponentElement y les envía un mensaje de inicio de simulación.

8) El componente envía un mensaje de postCreate() al objeto de simulación para

que pueda inicializar sus valores, por ejemplo, a partir de componentes co-

nectados.

9) 10) 11) Por último, se crea un nuevo hilo de ejecución para correr la simula-

ción para ese componente y se inicia. De esta forma cada componente del

diagrama, se corre simultáneamente, en un hilo de ejecución distinto. Inter-

namente, el hilo llama al método run() de la interface Runnable que imple-

menta el objeto de simulación.

[ ]

[ ]

par

Un thread por

cada

componente

loop

: PatternComponentcomponent

: ComponentRunnablerunnable

: ComponentElementmodel

runnableThread : Thread

: RunActionaction : PWEditoreditor: Useruser

Para todos los componentes

del diagrama

getRunnableClass()5:

6:

createRunnable()4:

postCreate(runnable=)8:

9:

start()10:

run()11:

startCycle()2:

preStart()3:

start()7:

run()1:

[ ]

[ ]

par

Un thread por

cada

componente

loop

Page 86: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

76 Framework de Visualización Diego M.S. Erdödy

6.5. Otros Frameworks de Visualización

JHotDraw [JHD 06] es un framework de visualización implementado en Java y

orientado a diagramas técnicos y estructurados. Fue desarrollado originalmente por Erich

Gamma y Thomas Eggenschwiler como un caso de estudio para mostrar la aplicación de

los patrones de diseño.

Si bien la versión original estaba basada en la biblioteca de gráficos AWT, las nue-

vas versiones incorporaron la biblioteca más moderna Swing. JHotDraw está basado en

dos proyectos, HotDraw, un framework de visualización implementado en SmallTalk, y

E++, un framework de aplicaciones hecho en C++.

El framework soporta el uso de una barra de herramientas, diferentes vistas, figuras

personalizadas y manejo de persistencia de diagramas (guardado, carga e impresión). La

arquitectura del framework, al igual que GEF y ACVF está basada en el patrón MVC

brindado especial soporte en la capa de control. La estructura básica del framework es la

siguiente:

Figura 6-17: Diagrama de estructura básico del framework de visualización JHotDraw

En JHotDraw las aplicaciones están compuestas por un diagrama (Drawing), una

vista del diagrama (DrawingView), un conjunto de figuras (Figure) y al menos una

herramienta (Tool). Las herramientas permiten ejecutar acciones sobre el diagrama, como

por ejemplo, crear una figura. Por último, los Handles son porciones de la figura que

permiten interactuar con la misma, por ejemplo para agregar una conexión.

Si bien técnicamente es un producto bien construido y las características son simila-

res a las provistas por GEF, las desventajas que se le encontraron, por las cuales no fue

utilizado para la implementación de ACVF son:

JHotDraw está diseñado para trabajar como una aplicación independiente. No

posee integración con un entorno de desarrollo como GEF y Eclipse, en don-

Page 87: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Framework de Visualización 77

de se puede optar por desarrollar un plug-in integrable o transformar dicho

plug-in en una aplicación cliente, con un pequeño cambio en configuración.

La documentación existente no es muy detallada y se basa en la autodocu-

mentación de las clases dentro de los patrones de diseño utilizados.

El estado actual y futuro del proyecto es incierto. Se encontraron distintos

emprendimientos cuyo objetivo es extender y continuar con el framework,

pero no existe un plan de soporte a largo plazo.

6.6. Conclusión

Para verificar que ACVF es un framework, a continuación se analiza si cumple con

las propiedades que lo definen como tal:

Orientado a ayudar en un dominio en particular: ACVF está diseñado para

proveer una infraestructura que soporte la visualización de componentes tanto

de una forma estática como dinámica, posibilitando el mejor entendimiento

de las interacciones intervinientes. De esta forma cumple con la propiedad

por estar específicamente construido con tal propósito.

Representa una solución parcialmente completa para un dominio específico

que puede ser personalizada: El dominio de ACVF es el descripto en el pun-

to anterior. ACVF provee comportamiento de base para la implementación de

representaciones visuales de componentes, compuesto por clases abstractas y

por implementación de elementos comunes como la vista de “outline”. La

personalización consiste de los distintos componentes “acoplables” (plugga-

ble) y de la extensión del comportamiento de base.

Permite la reutilización de diseño a partir de técnicas básicas de POO y pa-

trones de diseño: El diseño de ACVF provee una separación en capas bien

definidas y desacopladas, la interacción definida entre ellas y la definición de

la interface con los servicios que se espera de cada componente. Este es el

mayor aporte que este framework provee a los usuarios. En él se utiliza una

gran variedad de patrones, entre los que se encuentran:

o Abstract Factory: Este patrón se utiliza en la creación de los controla-

dores, a partir de los elementos del modelo.

o Template Method: Utilizado, por ejemplo, por la clase AbstractCom-

ponent, para poder crear el objeto de simulación a partir de la clase

provista por el método getRunnableClass(). Cada componente debe so-

brescribir el método para especificar la clase adecuada.

o Mediador: La capa del controlador está basada en este concepto, en

donde coordina y desacopla la interacción entre las capas del modelo

y de la vista.

o Composite: El modelo está implementado bajo este patrón, ya que po-

see una naturaleza inherentemente jerárquica.

o Command: Cada pedido del usuario es transformado en un comando

que luego es aplicado al modelo. De esta forma se puede almacenar

Page 88: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

78 Framework de Visualización Diego M.S. Erdödy

un historial de comandos ejecutados e implementar un mecanismo de

“deshacer” y “rehacer” de manera simple.

o Obervador: Implementado, por ejemplo, por el controlador para ac-

tuar frente a cambios en el modelo.

Permite la reutilización de funcionalidad: La funcionalidad o comportamien-

to que provee el framework se reparte entre las clases abstractas, que deberán

implementar los usuarios, y los elementos comunes que resuelven problemas

específicos del dominio y no necesitan modificaciones adicionales. Un ejem-

plo del primer caso es la clase AbstractComponent, mientras que la clase de

modelo Connection se encuentra en el segundo grupo.

Permite la reutilización de análisis del dominio: Tal vez no es muy evidente

en este caso, pero las posibilidades que brinda el framework, como armar un

diagrama, editar componentes, conectarlos entre si y visualizar su interacción

en una simulación, son todos casos de uso que se tuvieron que definir antes

de desarrollar el framework, y es un valor agregado que éste le provee al

usuario.

Page 89: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 79

7. Patrones de concurrencia y sincronización

7.1. Rendezvous

7.1.1. Resumen

El patrón de diseño “Rendezvous” tiene como objetivo modelar las precondi-

ciones para la sincronización o encuentro de distintos hilos de ejecución. Es un patrón

general y fácil de aplicar para asegurar que las condiciones requeridas (las cuales pue-

den ser complejas) sean cumplidas en tiempo de ejecución. El modelo de comporta-

miento consiste en que a medida de que cada hilo está listo para “encontrarse” con el

resto, éste se registra ante el Rendezvous y es bloqueado. Una vez que las restriccio-

nes de concurrencia se cumplen el Rendezvous libera a los participantes registrados,

por ejemplo al llegar a un número predefinido de participantes registrados.

7.1.2. Otras denominaciones

Punto de encuentro.

7.1.3. Problema

El problema que soluciona el patrón de diseño es la abstracción de la aplicación

de precondiciones en la ejecución de una acción dada que se encuentra compartida

entre más de un componente.

7.1.4. Solución

La solución consiste en delegar la sincronización en un objeto externo, llamado

rendezvous, que administre en forma centralizada la información de cada una de las

partes involucradas. Cada hilo de ejecución deberá registrarse con el rendezvous y

requerir permiso para proseguir en el momento en que la sincronización sea necesaria.

El rendezvous, con la ayuda de una política de sincronización encapsulada en otro

componente, será el encargado de informarle a cada hilo de ejecución, cuándo es co-

rrecto proceder.

7.1.5. Caso de estudio

Como ejemplo ilustrativo del patrón se utilizó una línea de montaje en donde el

procesamiento de cada etapa se encuentra a cargo de un brazo robótico. En dicho en-

torno existe la limitación de que cada etapa no puede ser iniciada hasta no tener la

confirmación que el resto de las etapas han terminado. En este caso, el punto de en-

cuentro está indicado por la finalización de las tareas de cada etapa, en cada ciclo de

procesamiento. De esta forma todos los brazos empezarán su tarea simultáneamente,

sin importar cuánto dure cada tarea.

Page 90: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

80 Patrones de concurrencia y sincronización Diego M.S. Erdödy

7.1.6. Estructura

La estructura clásica del patrón es la siguiente:

Figura 7-1: Diagrama de Estructura del Patrón “Rendezvous”

Este diagrama, sugerido por Powell Douglass [Dou 02], muestra a una clase

central llamada Rendezvous que representa el punto de encuentro de los objetos que

necesiten sincronizarse. Es el Rendezvous el que verifica que en cada registración de

un participante se cumpla o no la política de sincronización y en caso afirmativo libe-

ra a dichos participantes. Los participantes están representados por la clase ClientTh-

read y el mecanismo para liberarlos por la interface Callback.

A continuación se detallan las funciones de cada uno de los participantes de la

estructura del patrón.

Client Thread: Representa los hilos de ejecución, por lo menos dos, que nece-

sitan un mecanismo de sincronización. Al llegar al punto de sincronización se

registran con el Rendezvous pasando como argumento su referencia. Este me-

canismo recibe el nombre de Callback. Al cumplirse con las precondiciones,

los hilos son liberados para poder proseguir con su ejecución.

Rendezvous: Administra la sincronización entre los hilos participantes. Posee

un método de registración el cual es invocado por los hilos de ejecución para

indicar que han llegado al punto de sincronización.

Synch Policy: Es una abstracción del conjunto de precondiciones que necesita

verificar el Rendezvous para poder liberar a los integrantes. La política más

sencilla es simplemente contar los integrantes registrados y liberarlos al llegar

al número preestablecido de miembros.

Callback: Interface utilizada para la reactivación de los hilos de ejecución.

7.1.7. Estrategia de implementación Orientada a Aspectos

Synch Policy

+reset()

+register(in callback : Callback)

+release()

Rendezvous

Callback

+notify()

Client Thread

1

1

1 1..*

1

*

Page 91: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 81

La implementación realizada, posee dos modalidades: la versión local o simple,

en donde todos los brazos robóticos se encuentran en la misma máquina; y por otro

lado la versión distribuida, que puede sincronizar brazos robóticos en distintas máqui-

nas.

En el trabajo realizado por Jiménez-Peris et al. [Jim 98] se analiza una imple-

mentación distribuida y orientada a objetos del patrón de diseño rendezvous, en

ADA95. En ese trabajo se optó por estudiar las ventajas de implementar el servidor

con un hilo de ejecución por cliente (multithreaded). En el presente trabajó se utilizó

un solo hilo para implementar el servidor ya que el tiempo de procesamiento de cada

petición de un cliente no es significativo y el objetivo no es realizar una implementa-

ción de alta performance.

NÚCLEO

El núcleo del patrón de diseño se encuentra en el aspecto abstracto Rendez-

vousProtocol junto con las interfaces Rendezvous y RendezvousMember. El siguiente

es el diagrama de estructura de dichos elementos:

Figura 7-2: Núcleo de la estructura Orientada a Aspectos del Patrón “Rendezvous”

La idea principal de la implementación consta en desacoplar la lógica de sincro-

nización del objeto a sincronizar. Esto se logra por medio del punto de corte syncroni-

zingCall() definido en el aspecto abstracto, que representa el conjunto de sitios donde

la sincronización es requerida. De esta forma, el objeto a sincronizar, en nuestro caso

el brazo robótico, no necesita contener lógica asociada a la sincronización con el resto

de los brazos, ni tampoco saber de su existencia.

El Rendezvous es el objeto encargado de aplicar la política de sincronización a

los participantes que se registran en el mediante el método register(). Los participantes

deben implementar la interface RendezvousMember para poder identificar a qué gru-

po de sincronización pertenecen. Un grupo de sincronización es una entidad lógica

<<aspect>>

RendezvousProtocol

-rvs : Map<String, Rendezvous>

<<advice>> <<base>>~before( member : RendezvousMember ){base = synchronizingCall(member)}

<<setter>>+setRendezvous( groupName : String, rendezvous : Rendezvous ) : void

<<pointcut>>+synchronizingCall( member : RendezvousMember )

<<getter>>+getRendezvous( groupName : String ) : Rendezvous<<introduction>>

RendezvousMember

BaseType

-group : String

<<setter>>+setGroup( groupName : String ) : void

<<getter>>+getGroup() : String

<<introduction>>

RendezvousMember

Rendezvous

<<setter>>+setParticipants( part : int ) : void

+register( ob j : Object ) : void

+release() : void

+close() : void

+reset() : void

RendezvousMember

<<getter>>+getGroup() : String

<<crosscut>>

Page 92: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

82 Patrones de concurrencia y sincronización Diego M.S. Erdödy

que permite al aspecto poder correlacionar un participante con un Rendezvous especí-

fico y de esta forma poder servir a más de un Rendezvous a la vez. Como se ve en el

diagrama, el aspecto abstracto implementa el método que la interface requiere, llama-

do getGroup() y provee el método setGroup() para poder especificar el grupo de sincro-

nización sobre un participante.

A continuación se detalla cada elemento:

Rendezvous: Interface que representa un objeto de sincronización en donde distintos

componentes pueden registrarse y expresar su necesidad de suspender su ejecución

hasta que le sea dicho que es correcto proseguir. Esto se logra a través del método

register() cuyo argumento es el componente registrado. El método reset() brinda la po-

sibilidad de volver al rendezvous a su estado original mientras que release() es usado

cuando se necesite liberar a los participantes registrados. Por último, el método close()

realiza todas las operaciones de limpieza necesarias para finalizar el ciclo de vida del

rendezvous.

RendezvousMember: Interface que identifica a un miembro capaz de registrarse ante

un rendezvous. Los miembros setGroup() y getGroup() son los que permiten obtener y

especificar a qué grupo lógico de encuentro pertenece este miembro. Este nombre de

grupo permite tener más de un conjunto de miembros capaces de registrarse simultá-

neamente. La implementación de esta interface, que para aspectos se denomina “in-

troducción”, se efectúa en el aspecto abstracto que implementa el protocolo. La reali-

zación, en este caso por parte de la clase RoboArm, se lleva a cabo en el aspecto con-

creto permitiendo así indicar qué clase podrá ser miembro del Rendezvous sin que

ésta tenga que ser alterada con código específico del patrón de diseño.

RendezvousProtocol: Aspecto abstracto encargado de definir las interacciones comu-

nes del patrón de diseño. En primer lugar se define el punto de corte abstracto llamado

synchronizingCall() que representa el punto de sincronización del patrón. De esta forma,

en vez de agregar código adicional en el miembro para registrarse en el Rendezvous y

agregar un nivel de dependencia entre ambos objetos, la llamada queda a cargo del

aspecto permitiendo la abstracción del mecanismo. Por otro lado se definen los méto-

dos getRendezvous() y setRendezvous(), encargados de especificar qué Rendezvous mane-

jará la sincronización del grupo cuyo nombre es pasado como argumento. El advice

que se agrega sobre el punto de corte es el encargado de obtener el Rendezvous espe-

cificado para el miembro que se está procesando. Una vez obtenido el Rendezvous

llama al método register(). Por último, se implementa la interface RendezvousMember

que posee métodos para administrar a qué grupo pertenece el miembro.

APLICACIÓN del NÚCLEO sobre EL CASO DE ESTUDIO

Si bien se logró encapsular la lógica general del patrón en el aspecto abstracto

previamente explicado, es necesario algún elemento que vincule esa lógica con el

problema específico a atacar, en este caso la sincronización de brazos robóticos. El

aspecto concreto RendezvousHandler se encarga de dicha tarea, es decir que aplica la

lógica del rendezvousProtocol a objetos del tipo RoboArm, clase que representa el

brazo robótico. Las funciones del aspecto concreto son:

Transformar la clase RoboArm en un participante de un Rendezvous

haciendo que dicha clase implemente la interface RendezvousMember.

Page 93: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 83

Indicar que el punto de corte syncronizingCall() incluya las llamadas al

método executeAction() del brazo robótico.

En el siguiente diagrama de estructura se representan dichos elementos con las

asociaciones correspondientes:

Figura 7-3: Estructura de la aplicación del patrón “Rendezvous”

RoboArm: Representa el brazo robótico. Se le asigna un identificador (atributo id) y

se puede configurar el límite superior e inferior del tiempo de su acción principal

(atributos minTaskTime y maxTaskTime). Por defecto estos valores están especifica-

dos en 1 seg. y 5 seg., respectivamente. Cada vez que se ejecute, el tiempo real de

duración de la tarea será un número aleatorio comprendido entre dichos límites. Posee

un método run() para iniciar la simulación y otro stop() para detenerla.

RendezvousHandler: Aspecto concreto que agrega los detalles necesarios para aplicar

el patrón definido en el aspecto abstracto. Aquí se determina qué clase se utilizará

como miembro del Rendezvous y cuál será el punto de sincronización. En nuestro

caso es la clase RoboArm y su método execute().

IMPLEMENTACIONES DEL RENDEZVOUS

Hasta ahora se ha mostrado solo la interface que debe implementar un Rendez-

vous. Para este caso de estudio se han analizado y desarrollado dos implementaciones

distintas. La primera, llamada SimpleRendezvous, es una versión local que permite la

sincronización de hilos de ejecución dentro de una misma máquina. La segunda, lla-

mada RemoteRendezvous, consiste en una versión remota que permite sincronizar

hilos que se ejecuten en distintas máquinas.

Para el caso remoto, el objeto RemoteRendezvous se deberá conectar con un

servidor detallado en la siguiente sección, que coordinará las acciones de las distintas

<<aspect>>

RendezvousHandler

<<pointcut>> <<base>>+synchronizingCall( member : RendezvousMember ){base = call (void RoboArm.executeAction()) && target(o)}

<<aspect>>

RendezvousProtocol

-rvs : Map<String, Rendezvous>

<<advice>> <<base>>~before( member : RendezvousMember ){base = synchronizingCall(member)}

<<setter>>+setRendezvous( groupName : String, rendezvous : Rendezvous ) : void

<<pointcut>>+synchronizingCall( member : RendezvousMember )

<<getter>>+getRendezvous( groupName : String ) : Rendezvous

<<declare parents>>

RoboArm implements RendezvousMember

~log : Logger = Logger.getLogger(RoboArm.class)

-maxTaskTime : long = 5000

-minTaskTime : long = 1000

-stopped : boolean = false

-random : Random

-id : String

<<setter>>+setMaxTaskTime( maxTaskTime_ : long ) : void

<<setter>>+setMinTaskTime( minTaskTime_ : long ) : void

<<constructor>>+RoboArm( id_ : String )

<<getter>>+getMaxTaskTime() : long

<<getter>>+getMinTaskTime() : long

<<getter>>+getRAId() : String

-createRandom() : Random

#calculateTime() : long

+executeAction() : void

+toString() : String

+stop() : void

+run() : void

RoboArm

<<introduction>>

RendezvousMember

RendezvousMember

<<getter>>+getGroup() : String

Page 94: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

84 Patrones de concurrencia y sincronización Diego M.S. Erdödy

instancias de RemoteRendezvous. A diferencia de la versión simple, el Rendezvous

remoto implementa la interface Callback, dado que se necesita que sea llamado por el

servidor de Rendezvous una vez que la política de sincronización ha sido cumplida y

los participantes del Rendezvous pueden ser liberados. Esto se logra a través de una

llamada remota utilizando RMI desde el servidor al método finished() de la instancia de

RemoteRendezvous. Téngase en cuenta que en el caso del Rendezvous simple este

mecanismo no era necesario ya que el Rendezvous directamente bloqueaba el hilo de

ejecución al registrarse el participante y luego cuando debía ser liberado, lo desperta-

ba.

El siguiente es el diagrama de estructura:

Figura 7-4: Estructura de la distintas implementaciones del Rendezvous

Callback: Interface de retro-llamada que declara el método finished(). Cuando en un

mensaje se pasa como argumento una referencia del objeto iniciador de la llamada,

esta interface permite que el objeto al cual se está llamando pueda informarle al objeto

iniciador en una manera asincrónica que el procesamiento asociado a la llamada ha

sido finalizado. En este caso el objeto que necesita ser notificado es el RemoteRen-

dezvous y el notificador es el servidor que a través del método finished() le indicará al

Rendezvous que sus participantes pueden ser liberados.

SimpleRendezvous: Versión sencilla o local del rendezvous. Simplemente bloquea al

hilo de ejecución de cada miembro registrado hasta que las precondiciones sean cum-

plidas, usando una llamada al método wait(). Cuando se cumplen las precondiciones

llama al método notifyAll() sobre el monitor liberando así todos los hilos.

RemoteRendezvous: Versión remota del rendezvous. En este caso las llamadas se

delegan a un servidor de rendezvous via RMI el cual es el encargado de coordinar las

acciones. El constructor recibe como argumento la dirección de la máquina donde

~log : Logger = Logger.getLogger(RemoteRendezvous.class)

-objs : Set<E->Object> = new HashSet<Object>()

-server : RendezvousServer

-maxParticipants : int = 2

RemoteRendezvous

<<constructor>>+RemoteRendezvous( serverAddress : String )

<<setter>>+setParticipants( part : int ) : void

+register( obj : Object ) : void

+finished() : void

+release() : void

+close() : void

+reset() : void

SimpleRendezvous

#objs : Set<E->Object> = new HashSet<Object>()

-maxParticipants : int = -1

<<constructor>>+SimpleRendezvous( maxParticipants_ : int )

<<setter>>+setParticipants( part : int ) : void

<<constructor>>+SimpleRendezvous()

+register( obj : Object ) : void{guarded}

-checkParticipants() : void

+release() : void

+close() : void

+reset() : void

Rendezvous

<<setter>>+setParticipants( part : int ) : void

+register( ob j : Object ) : void

+release() : void

+close() : void

+reset() : void

Callback

+finished() : void

Page 95: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 85

reside el servidor de Rendezvous. Implementa la interface Callback para permitir ser

llamado por el servidor al momento de ser liberado, a través del método finished().

IMPLEMENTACIÓN REMOTA

Para la implementación remota del Rendezvous, es necesario especificar un ser-

vidor que pueda coordinar los Rendezvous sobre distintas máquinas de una forma

centralizada. Dicho servidor es accesible via RMI y permite que los RemoteRendez-

vous actúen de proxy entre los participantes del rendezvous y él. De esta forma al

servidor le llega la información las registraciones de participantes en cada una de las

máquinas y él puede distribuir la orden de liberación una vez que la política de sin-

cronización ha sido cumplida. El diagrama de estructura es el siguiente:

Figura 7-5: Estructura de la implementación remota del Rendezvous

RendezvousServer: Es la interface que define a un servidor de rendezvous. Esta se

aplica en los casos en que los miembros pueden encontrarse en máquinas distintas y

por lo tanto es necesario coordinar hilos de ejecución remotos. Al igual que un ren-

dezvous tiene un método register() para indicar que un miembro ha llegado al punto de

sincronización. Los otros dos métodos, addClient() y removeClient(), agregan o quitan

clientes activos, es decir instancias de RemoteRendezvous, a este servidor. Para poder

agregar un cliente, es necesario indicarle al servidor cuántos participantes tiene bajo

su control para que pueda calcular el número total de participantes y de esta forma

saber en qué momento están todos registrados.

RendezvousServerImpl: Implementación del servidor de rendezvous utilizando RMI.

El diagrama de estructura completo es el siguiente:

RendezvousServerImpl

-participantsByClient : Map<Publisher, List<Subscriber>><K->Callback, V->Integer> = new HashMap<Callback,Integer>()

~log : Logger = Logger.getLogger(RemoteRendezvous.class)

~serialVersionUID : long = 1{readOnly}

-maxParticipants : int

-registered : int

-name : String

<<constructor>>+RendezvousServerImpl( name_ : String )

+addClient( client : Callback, part : int ) : void

+register( client : Callback ) : void{guarded}

+removeClient( client : Callback ) : void

#unregister() : void

#register() : void

-release() : void

RendezvousServer

+addClient( client : Callback, part : int ) : void

+removeClient( client : Callback ) : void

+register( client : Callback ) : void

Page 96: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

86 Patrones de concurrencia y sincronización Diego M.S. Erdödy

Figura 7-6: Estructura completa para el Rendezvous

7.1.8. Análisis

Como se vio en la descripción de la implementación, la utilización de un aspecto abs-

tracto para encapsular la lógica general del patrón ha hecho factible tener un elemento

reutilizable y localizado. Esto implica que al momento de aplicar el patrón solo haga

falta indicar sobre qué lugares del sistema actuarán los puntos de corte definidos en el

aspecto abstracto y distribuir los roles especificados por el mismo. El detalle de cada

una de las características es el siguiente:

Localidad del código: Todo el código relacionado al manejo del Rendezvous

se encuentra concentrado en el protocolo así como también en las implementa-

ciones específicas de la interface.

Reusabilidad: Dada la abstracción que se logró del protocolo principal del

Rendezvous, el aspecto abstracto es totalmente reutilizable e incluso configu-

rable con una implementación particular de la interface.

Independencia: Desde el momento que el brazo robótico no tiene ningún co-

nocimiento de las restricciones que se le está aplicando, se puede aseverar que

es totalmente independiente del patrón. Si se necesitara que funcione un brazo

independientemente, no haría falta ningún cambio en absoluto en el código de

la clase RoboArm.

Transparencia de composición: Un brazo puede participar en más de un Ren-

devous sin necesidad de agregar restricciones adicionales ni afectar el compor-

tamiento del mismo.

<<aspect>>

RendezvousHandler

<<pointcut>> <<base>>+synchronizingCall( member : RendezvousMember ){base = call (void RoboArm.executeAction()) && target(o)}

RendezvousServerImpl

-participantsByClient : Map<Publisher, List<Subscriber>><K->Callback, V->Integer> = new HashMap<Callback,Integer>()

~log : Logger = Logger.getLogger(RemoteRendezvous.class)

~serialVersionUID : long = 1{readOnly}

-maxParticipants : int

-registered : int

-name : String

<<constructor>>+RendezvousServerImpl( name_ : String )

+addClient( client : Callback, part : int ) : void

+register( client : Callback ) : void{guarded}

+removeClient( client : Callback ) : void

#unregister() : void

#register() : void

-release() : void

<<aspect>>

RendezvousProtocol

-rvs : Map<String, Rendezvous>

<<advice>> <<base>>~before( member : RendezvousMember ){base = synchronizingCall(member)}

<<setter>>+setRendezvous( groupName : String, rendezvous : Rendezvous ) : void

<<pointcut>>+synchronizingCall( member : RendezvousMember )

<<getter>>+getRendezvous( groupName : String ) : Rendezvous

<<declare parents>>

RoboArm implements RendezvousMember

<<introduction>>

RendezvousMember

~log : Logger = Logger.getLogger(RemoteRendezvous.class)

-objs : Set<E->Object> = new HashSet<Object>()

-server : RendezvousServer

-maxParticipants : int = 2

RemoteRendezvous

<<constructor>>+RemoteRendezvous( serverAddress : String )

<<setter>>+setParticipants( part : int ) : void

+register( obj : Object ) : void

+finished() : void

+release() : void

+close() : void

+reset() : void

SimpleRendezvous

#objs : Set<E->Object> = new HashSet<Object>()

-maxParticipants : int = -1

<<constructor>>+SimpleRendezvous( maxParticipants_ : int )

<<setter>>+setParticipants( part : int ) : void

<<constructor>>+SimpleRendezvous()

+register( obj : Object ) : void{guarded}

-checkParticipants() : void

+release() : void

+close() : void

+reset() : void~log : Logger = Logger.getLogger(RoboArm.class)

-maxTaskTime : long = 5000

-minTaskTime : long = 1000

-stopped : boolean = false

-random : Random

-id : String

<<setter>>+setMaxTaskTime( maxTaskTime_ : long ) : void

<<setter>>+setMinTaskTime( minTaskTime_ : long ) : void

<<constructor>>+RoboArm( id_ : String )

<<getter>>+getMaxTaskTime() : long

<<getter>>+getMinTaskTime() : long

<<getter>>+getRAId() : String

-createRandom() : Random

#calculateTime() : long

+executeAction() : void

+toString() : String

+stop() : void

+run() : void

RoboArm

BaseType

-group : String

<<setter>>+setGroup( groupName : String ) : void

<<getter>>+getGroup() : String

<<introduction>>

RendezvousMember

RendezvousServer

+addClient( client : Callback, part : int ) : void

+removeClient( client : Callback ) : void

+register( client : Callback ) : void

Rendezvous

<<setter>>+setParticipants( part : int ) : void

+register( obj : Object ) : void

+release() : void

+close() : void

+reset() : void

RendezvousMember

<<getter>>+getGroup() : String

Callback

+finished() : void

<<crosscut>>

Page 97: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 87

7.1.9. Componente gráfico

Existen tres componentes implementados:

RoboArm: Brazo robótico. Se puede configurar los límites de tiempo de la du-

ración de su tarea así como también el nombre de la instancia.

Rendezvous: Representación del rendezvous. Si no se especifica una dirección

de servidor actúa en modo “simple”, es decir en forma local. De lo contrario se

conecta con el servidor especificado y pasa a actuar en forma remota pudiendo

sincronizarse con todos los rendezvous conectados a ese servidor. Es necesario

que se le especifique un nombre de grupo en caso de que exista más de un

rendezvous.

RendezvousServer: Servidor coordinador y aceptor de llamadas de rendezvous

remotos.

Cada roboArm que se quiera sincronizar debe ser conectado con el correspon-

diente rendezvous. El nombre del grupo para el brazo robótico se obtiene automáti-

camente del Rendezvous, por eso es importante especificar un nombre distinto para

cada Rendezvous en caso de que haya más de uno en el diagrama.

Al momento de iniciar la simulación, cada brazo robótico comenzará a ejecutar

su acción y se representa dicho estado con el color rojo. Una vez finalizada la acción,

que tardará un número aleatorio de milisegundos acotado por los límites impuestos,

vuelve al estado libre, representado por el color verde. Es en este momento actúa la

sincronización y no permite que el brazo vuelva a ejecutar su acción hasta que todos

los otros brazos participantes del rendezvous hayan finalizado. Si el brazo no formara

parte de un rendezvous, se lo vería constantemente ocupado, es decir, en color rojo.

A continuación se puede observar una captura de una configuración con un

RendezvousServer por un lado (diagrama superior) y un Rendezvous que sincroniza a

tres brazos robóticos por otro lado (diagrama inferior).

Page 98: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

88 Patrones de concurrencia y sincronización Diego M.S. Erdödy

Figura 7-7: Diagrama ACVF del caso de estudio para el patrón “Rendezvous”

7.2. Balking

7.2.1. Resumen

Si se llama a un método sobre un objeto dado, cuando éste se encuentra en un

estado inapropiado, entonces la llamada al método no se ejecutará.

7.2.2. Otras denominaciones

Barrera de llamada.

7.2.3. Problema

Un objeto puede encontrarse en un estado inapropiado para atender una llamada

a un método determinado. Una posible solución sería dejar en espera a la llamada has-

ta que llegue el momento en que el estado del objeto sea el adecuado, pero esto no

siempre cumple los requerimientos deseados (por ejemplo si hay restricciones en el

tiempo de respuesta).

7.2.4. Solución

Page 99: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 89

La solución que plantea este patrón de diseño, es simplemente ignorar la llama-

da y es por eso que sólo se puede aplicar en entornos donde la ejecución no sea crítica

dentro del sistema. No podría aplicarse en una situación tan crítica como es, por

ejemplo, el latido de un marcapasos.

7.2.5. Caso de Estudio

El ejemplo que se eligió para analizar este patrón, es la interacción entre un re-

trete y las distintas formas que pueden existir de activar su vaciado. Ejemplos de for-

mas de activación son un botón o un sensor de proximidad. Evidentemente, no tiene

sentido iniciar un vaciado una vez que otro vaciado se encuentra en curso. Una solu-

ción posible es verificar el estado del retrete antes de realizar el pedido de vaciado. El

problema con esta solución es que se necesita introducir lógica que no pertenece al

interés principal del cliente, que es simplemente realizar el vaciado del retrete. Es por

eso que se propone encapsular en un aspecto dicho mecanismo para poder aplicarlo de

una forma transparente al cliente.

7.2.6. Estructura

Veamos el diagrama de colaboración de la estructura típica:

Figura 7-8: Diagrama de estructura del patrón “Balking”

El patrón se basa sobre una estructura en la cual un componente es accedido, ya

sea en forma remota o local, por un objeto cliente.

A continuación se describen los roles de los participantes involucrados en el

patrón.

Component: Es el objeto sobre el cual se va a aplicar la llamada y el cual ne-

cesita una política de manejo de las llamadas en momentos inapropiados.

Client: Objeto que actúa como cliente del componente y por ende el responsa-

ble de efectuar la llamada al método en cuestión. Según el patrón de diseño

puede esperar que el resultado sea nulo o hasta recibir una excepción en el ca-

so de que el estado del componente no sea el adecuado para procesar la llama-

da.

7.2.7. Estrategia de implementación Orientada a Aspectos

La implementación se basa en extraer el mecanismo básico del patrón en un as-

pecto abstracto llamado BalkingProtocol. La implementación además incluye los

objetos representantes del retrete y sus activadores, junto con el aspecto concreto que

indica sobre cuales elementos debe aplicarse el mecanismo abstraído en el protocolo.

Page 100: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

90 Patrones de concurrencia y sincronización Diego M.S. Erdödy

NÚCLEO

Para la implementación del núcleo del patrón se ha optado por ignorar la llama-

da en cuestión si es que ya se encuentra en ejecución al momento de iniciar el pedido.

Una opción más compleja hubiese sido abstraer el comportamiento que se ejecuta en

dicho caso y permitir al usuario aplicar otras políticas alternativas, como por ejemplo

registrar el pedido o llamar a otro componente. Se ha elegido el camino simple ya que

de cualquiera de las dos maneras se pueden observar los mecanismos básicos de la

implementación AOP, que se pretenden analizar.

El diagrama de estructura es el siguiente:

Figura 7-9: Estructura del Núcleo del patrón “Balking”

BalkingProtocol: Aspecto abstracto que define el mecanismo principal del patrón.

Posee una definición abstracta de pointcut llamada executionCall() la cual representa la

llamada que se quiere controlar. Asimismo cuenta con un advice aplicado alrededor

de dicho pointcut. El pointcut controla que la llamada sea ejecutada si no hay otra

llamada del mismo tipo en proceso, y que sea ignorada en cualquier otro caso.

APLICACIÓN CONCRETA al CASO DE ESTUDIO

En la aplicación del patrón de diseño se implementó un objeto simulador del re-

trete, en el cual se pueden configurar características tales como la duración del vacia-

do. El retrete puede contener uno o más tipos de activación, representado por la inter-

face FlusherActivator al cual se le han implementado dos modos, FlashButton y

LightSensor, es decir, a través de un botón mecánico o un sensor de proximidad. Por

último se cuenta con la implementación concreta del aspecto que indica sobre cuales

elementos se debe aplicar el patrón.

El diagrama de estructura es el siguiente:

<<aspect>>

BalkingProtocol

-busy : boolean

<<base>> <<advice>>+around(){base = executionCall()}

<<pointcut>>+executionCall()

Page 101: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 91

Figura 7-10: Estructura de la aplicación del patrón “Balking”

Clases

Flusher: Clase que representa el funcionamiento de un retrete. El mensaje flush() es el

que realiza el proceso de vaciado del mismo. Es posible configurar el tiempo que to-

ma este proceso por medio del método setFlushTime().

FlusherActivator: Clase abstracta que representa una entidad capaz de accionar la

cadena del retrete. Permite vincular (y desvincular) Flushers a los cuales se quieren

controlar, a través del método addFlusher(). Implementa también la funcionalidad bási-

ca de simulación de la entidad en la cual cada cierto tiempo (especificado con el

método setMeanTime()), se acciona la cadena de los retretes vinculados. La simulación

se puede iniciar o parar con los métodos run() (de la interface Runnable) y stopActiva-

tor().

FlusherButton: Especialización de la clase FlusherActivator que representa un botón

para el accionamiento de la cadena del retrete.

LightSensor: Especialización de la clase FlusherActivator que representa un sensor

de movimiento para el accionamiento de la cadena del retrete.

Aspectos

BalkingHandler: Aspecto concreto que representa la aplicación del patrón a nuestro

ejemplo particular. Para ello lo único que necesita especificar es cuál será la llamada a

controlar. Por eso es que define el pointcut executionCall() y lo asigna al método flush()

de la clase Flusher.

7.2.8. Análisis

<<aspect>>

BalkingHandler

<<pointcut>> <<base>>+executionCall(){base = call (void Flusher.flush())}

~log : Logger = Logger.getLogger(FlusherActivator.class)

#flushers : Set<E->Flusher> = new HashSet<Flusher>()

-stopRequested : boolean = false

#meanTime : int

FlusherActivator

<<constructor>>+FlusherActivator( flusher : Flusher )

<<setter>>+setMeanTime( ms : int ) : void

+removeFlusher( fl : Flusher ) : void

<<constructor>>+FlusherActivator()

+addFlusher( fl : Flusher ) : void

+actionPerformed() : void

+stopActivator() : void

+run() : void

LightSensor

<<constructor>>+LightSensor( flusher : Flusher )

Flusher

~log : Logger = Logger.getLogger(Flusher.class)

-flushTime : int = 3000

<<setter>>+setFlushTime( ms : int ) : void

+flush() : voidFlashButton

<<constructor>>+FlashButton( flusher : Flusher )

<<aspect>>

BalkingProtocol

Page 102: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

92 Patrones de concurrencia y sincronización Diego M.S. Erdödy

La lógica asociada al patrón se ha podido abstraer utilizando el mismo meca-

nismo del aspecto abstracto. A continuación se detalla el análisis de la implementa-

ción:

Localidad del código: Todo el código relacionado al manejo del Balking se

encuentra concentrado en el aspecto abstracto sin necesidad de complicar la

lógica propia del Flusher ni otro componente.

Reusabilidad: Dada la abstracción que se logró del protocolo principal del

BalkingProtocol, el aspecto abstracto es totalmente reutilizable e incluso con-

figurable con una implementación particular de la interface.

Independencia: El código que maneja el procedimiento a seguir en caso de que

el retrete se encuentre en un estado inadecuado para procesar el pedido de va-

ciado, se encuentra desacoplado de la lógica de dicho procedimiento. Es por

eso que cada interés logra el nivel de independencia necesario para poder evo-

lucionar por separado.

Transparencia de composición: Si fuera necesario aplicar el patrón a otro

método o aplicarlo al mismo método para manejar otros estados, no habría in-

terferencia entre cada uno, ya que se encuentran modularizados y el único pun-

to de encuentro es la invocación al método.

7.2.9. Componente gráfico

Los componentes que fueron implementados para este caso son:

Flusher: Representación del retrete. Se puede configurar la duración del va-

ciado.

FlusherActivator: Activador de retrete. Cuenta con dos modos de activación,

uno interactivo en donde el usuario puede activar el componente a través de

una acción y otro automático en donde el componente se activa aleatoriamente

cada cierto tiempo.

Es posible conectar un activador con uno o varios retretes y de la misma forma

cada retrete puede ser activado por uno o más activadores. Se puede comprobar, dada

la aplicación del patrón de diseño en cuestión, que cualquier pedido de vaciado a un

retrete que se encuentra en proceso de vaciamiento, es ignorado.

El siguiente es un ejemplo que muestra todas las posibles combinaciones de en-

lace:

Page 103: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 93

Figura 7-11: Diagrama ACVF del caso de estudio para el patrón “Balking”

El diagrama corresponde a una simulación en el modo interactivo. El primer ac-

tivador actúa sobre ambos retretes simultáneamente, mientras que el segundo retrete

es activado por cualquiera de los dos activadores.

7.3. Observador

7.3.1. Resumen

El concepto central de este patrón de diseño es que uno o más objetos llamados

observadores puedan registrarse con otro objeto llamado „sujeto‟, el cual notificará un

determinado evento a dichos observadores.

7.3.2. Otras denominaciones

Publisher – Subscriber

7.3.3. Problema

El problema consiste en hallar una forma de poder notificar a un grupo de obje-

tos, en el momento en que ocurre un cierto evento asociado a otro objeto dado. Dicho

evento puede ser el cambio de valor de uno de sus atributos, la llamada a un método o

cualquier acción que pueda llegar a afectar su estado. Una alternativa es que cada ob-

jeto cliente trate de averiguar el estado de dicho evento activamente, lo cual trae apa-

rejado un gasto de recursos innecesario.

Page 104: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

94 Patrones de concurrencia y sincronización Diego M.S. Erdödy

7.3.4. Solución

La solución que propone el patrón consta de dos fases. Por un lado, los objetos

que necesitan ser notificados de los cambios (observadores), deben “registrarse” al

objeto fuente de dichos eventos (sujeto). De esta forma, solicitan que se les “avise”

cuando un cambio pertinente tenga lugar. Por otro lado, el sujeto debe “notificar” a

los observadores cuando dicho cambio ocurre. Para ello, invocará el método prefijado

de la referencia que le hayan provisto los observadores al momento de la registración.

En dicha invocación, se provee información acerca del evento que originó la llamada.

7.3.5. Caso de estudio

Se eligió como caso de estudio, la interacción entre un sensor de velocidad de

un auto y un medidor que actúa de interface con el usuario. El problema es que el me-

didor debe ser informado cada vez que el sensor detecta un cambio.

7.3.6. Estructura

La estructura que sugiere el patrón propone un desacoplamiento entre los obser-

vadores y el sujeto, al incorporar un mecanismo de suscripción basado en abstraccio-

nes de cada rol. Al mismo tiempo, permite notificar a los observadores en el momento

preciso en que el evento es capturado, o poco tiempo después. El diagrama de estruc-

tura es el siguiente:

Figura 7-12: Diagrama de estructura del patrón “Observador”

Los participantes del patrón son:

-value

Data

+subscribe(in client : AbstractClient)

+unsubscribe(in client : AbstractClient)

AbstractSubject

+accept(in data)

AbstractClient

ConcreteClient ConcreteSubject

1

1

* 1

Puede ser una referencia o una copia del dato

Page 105: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 95

AbstractSubject: Actúa como servidor de información para los Observadores

(AbstractClient) que consumen dicha información. Permite incorporar o eli-

minar asociaciones con clientes mediante los métodos subscribe() y unsubscri-

be(). Es su tarea informar a los clientes cuando está disponible la información.

Un ejemplo típico de dicha información es el cambio en el valor de uno de sus

atributos.

AbstractClient: Representa un objeto que desea conocer la información que un

sujeto (AbstractSubject) tiene para brindar. Contiene el método accept() que es

llamado para proveerle la información deseada.

ConcreteClient: Subclase específica de la aplicación de la clase abstracta Ab-

tractClient. Contiene la funcionalidad específica de la aplicación del patrón.

ConcreteSubject: Subclase especifica de la aplicación de la clase abstracta

AbstractSubject. Contiene la funcionalidad específica de la aplicación del

patrón.

Data: Contiene la información que el Sujeto conoce y le transmitirá a todos

los Observadores subscriptos.

7.3.7. Estrategia de implementación Orientada a Aspectos

La implementación orientada a aspectos, se divide en dos partes. Por un lado, el

núcleo del patrón, con la lógica que se abstrae y modulariza. Por otro lado, la aplica-

ción de dicho núcleo y los objetos propios del caso de estudio.

NÚCLEO

La implementación del núcleo, consta de un aspecto abstracto que contiene el

protocolo del patrón y por otro lado dos interfaces de “marca” que define los roles

definidos por el patrón. Una interface de marca es aquella que no contiene métodos ni

atributos, y sólo sirve para identificar tipos de objetos. El diagrama de estructura es el

siguiente:

Figura 7-13: Estructura del Núcleo del patrón “Observador”

Interfaces

-perPublisherSubscribers : Map<Publisher, List<Subscriber>>

<<aspect>>

ObserverProtocol

<<base>> <<advice>>+after( publisher : Publisher ){base = publisherChanges(publisher)}

#updateSubscriber( publisher : Publisher, observer : Subscriber ) : void

+unsubscribe( publisher : Publisher, observer : Subscriber ) : void

+subscribe( publisher : Publisher, subscriber : Subscriber ) : void

<<pointcut>>+publisherChanges( publisher : Publisher )

#getSubscribers( publisher ) : List<Subscriber>

SubscriberPublisher

Page 106: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

96 Patrones de concurrencia y sincronización Diego M.S. Erdödy

Publisher: Indica que el objeto será observado frente a determinados cambios.

Subscriber: Indica que el objeto actuará de suscriptor, es decir, podrá ser notificado

cuando el objeto del tipo Publisher al cual se suscribió cambie en alguna de las for-

mas predeterminadas.

Aspectos

ObserverProtocol: Aspecto abstracto que define el mecanismo principal del patrón.

Posee un atributo, perPublisherSubscriber, que almacena las relaciones entre Publishers

y Subscribers para las suscripciones realizadas. Para acceder a dichas suscripciones

desde un aspecto derivado, posee un método llamado getSubscribers() el cual recibe el

Publisher del cual se quieren consultar suscriptores, como parámetro.

Posee también dos métodos para el manejo de suscripciones, suscribe() y unsuscribe()

los cuales reciben el par Publisher, Subscriber como parámetros. Nótese que ambos

métodos son parte del aspecto, por lo que el manejo de suscripciones es ahora desaco-

plado tanto del sujeto como del suscriptor para pasar a formar parte de una entidad

localizada que maneje el vínculo entre ellos. El único pointcut abstracto definido en el

aspecto, publisherChanges(Publisher), representa los puntos indicadores de un cambio en

la clase (o las clases) definida como Publisher. Por último se define e implementa un

advice sobre este pointcut, el cual simplemente llama al método protegido abstracto

(Template Method [Gam 95]) updateSubscriber (Publisher, Subscriber) para cada subs-

criptor asociado al Publisher en cuestión.

APLICACIÓN CONCRETA al CASO DE ESTUDIO

La aplicación del patrón al caso de uso, se realiza con un aspecto concreto que

especifica que join points debe capturar el pointcut y como notificará a los suscripto-

res del evento esperado. También se indica, a través del aspecto concreto, quien cum-

ple cada rol especificado en el núcleo del patrón.

Para el modelado del caso de estudio, se cuenta con dos objetos que cumplen

con las funciones de velocímetro y sensor de velocidad. Estos objetos cumplirán el

papel de observador y sujeto, respectivamente. El diagrama de estructura es el si-

guiente:

Page 107: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 97

Figura 7-14: Estructura de la aplicación del patrón “Observador”

Clases

SpeedSensor: Clase que representa un sensor de velocidad. Es este caso el atributo

que nos interesa monitorear es precisamente la velocidad (speed). El método run()

provee la simulación del cambio de velocidad a períodos regulares y el método speed-

Changed() indica que dicha velocidad se ha modificado. El método getSpeed() permite

obtener la velocidad actual y por último el método stop() detiene la simulación.

SpeedMeter: Clase que representa un medidor de velocidad el cual actúa como inter-

face hacia el usuario y requiere información externa, en nuestro caso un sensor. Posee

un método llamado speedChanged(int) el cual provee la información externa sobre cam-

bios en la velocidad a mostrar.

Aspectos

ObserverHandler: Aspecto concreto derivado de ObserverProtocol. Por un lado es-

pecífica las clases que cumplen los roles de Publisher y Subscriber, es decir, Speed-

Sensor y SpeedMeter. Por otro lado determina que el join point para el pointcut pu-

blisherChanges será la llamada al método speedChanged() de la clase SpeedSensor e im-

<<aspect>>

ObserverHandler

<<base>> <<pointcut>>+publisherChanges( publisher : Publisher ){base = execution (void SpeedSensor.speedChanged()) && target(publisher)}

#updateSubscriber( publisher : Publisher, observer : Subscriber ) : void

<<declare parents>>

SpeedMeter implements Subscriber

<<declare parents>>

SpeedSensor implements Publisher

SpeedSensor

~log : Logger = Logger.getLogger(SpeedSensor.class)

-stopped : boolean = false

-_speed : int

<<getter>>+getSpeed() : int

+speedChanged() : void

+stop() : void

+run() : void

SpeedMeter

~log : Logger = Logger.getLogger(SpeedMeter.class)

+speedChanged( speed : int ) : void

<<aspect>>

ObserverProtocol

SubscriberPublisher

Page 108: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

98 Patrones de concurrencia y sincronización Diego M.S. Erdödy

plementa el método updateSubscriber() con una llamada al método speedChanged(int) de

la clase SpeedMeter. Este aspecto actúa de “mediador” entre el aspecto abstracto que

implementa el mecanismo general del patrón y las clases a las cuales se lo quiere apli-

car.

7.3.8. Análisis

Este patrón es un caso de abstracción total del comportamiento del aspecto y se ha

podido modularizar en un aspecto reutilizable, como se demuestra en la aplicación al

caso de estudio. A continuación se analizan los distintos puntos de estudio.

Localidad del código: Este patrón es un claro ejemplo de localidad de código

generada de forma inherente a las características de la programación orientada

a aspectos. El interés transversal (mecanismo de observación) ha sido abstraí-

do y materializado en un único aspecto, ObserverProtocol.

Reusabilidad: El aspecto abstraído, además de estar localizado, es totalmente

reutilizable dado que para una nueva aplicación sólo basta con crear un aspec-

to concreto derivado que indique cuales van a ser los participantes de la obser-

vación y que se va a observar.

Independencia: Al no tener ninguno de los componentes conocimiento alguno

sobre las interacciones involucradas en la implementación del patrón, cada uno

de ellos puede evolucionar de manera independiente sin afectar el comporta-

miento de ninguna de las partes.

Transparencia de composición: La forma de manejo implementada de las re-

ferencias suscriptas garantiza que no haya interferencia entre distintas aplica-

ciones del patrón. Por otro lado, al mantener los niveles de invasión por parte

del aspecto sobre los componentes que actúan en cada rol (observador y suje-

to), la composición con otros patrones no traería inconvenientes.

7.3.9. Componente gráfico

Los siguientes componentes fueron implementados para este patrón:

SpeedSensor: Dispositivo sensor de velocidad. Obtiene una lectura periódica

de velocidad cuyo valor es el atributo “observable” del componente.

SpeedMeter: Representación del velocímetro que mostrará la información

provista por el sensor.

El medidor de velocidad mostrará el registro obtenido del sensor que tenga aso-

ciado, de manera casi simultánea a la obtención de dicha medición por parte del sen-

sor. Nótese que cada sensor puede tener más de un medidor asociado en cuyo caso

todos mostrarán el mismo registro simultáneamente. El siguiente es un ejemplo que

muestra todas las posibles combinaciones de enlace:

Page 109: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 99

Figura 7-15: Diagrama ACVF del caso de estudio del patrón “Watchdog”

La simulación sólo puede correrse en modo no-interactivo, y consta de valores

aleatorios que genera el sensor y muestra en el compartimiento de estado. Los ve-

locímetros, simplemente reproducen el valor del sensor que tengan asociado, también

en el compartimiento de estado.

7.4. Optimistic Locking

7.4.1. Resumen

El acceso y modificación concurrente del contenido de un recurso compartido

(por ejemplo una tabla de una base de datos), puede generar inconsistencia en el con-

tenido de dicho recurso, si no se toman las precauciones pertinentes. El bloqueo opti-

mista es una solución intermedia que supone el caso más optimista (nadie modificó el

elemento desde la última vez que se accedió) y se toman acciones en caso de que di-

cho supuesto sea incorrecto.

7.4.2. Otras denominaciones

Control Optimista de Concurrencia

7.4.3. Problema

El acceso a un recurso de lectura-escritura compartido trae aparejado problemas

de consistencia si no se establece una política de sincronización adecuada.

7.4.4. Solución

Page 110: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

100 Patrones de concurrencia y sincronización Diego M.S. Erdödy

Cuando es necesario tener acceso de lectura y escritura concurrente sobre ele-

mentos compartidos en un entorno distribuido, existen 3 políticas posibles a aplicar.

La política simplista consiste en no tomar ninguna acción si el recurso es modificado

por dos o más clientes a la vez. Se obtiene como resultado un esquema en donde “el

último en modificar es el que gana”. Es decir, un cliente puede acceder a la informa-

ción, manipularla, luego almacenarla y estar sobrescribiendo una actualización que se

hizo sobre la misma información en el transcurso de la manipulación. Esta política

trae aparejada pérdida de modificaciones por manipulación de información local des-

actualizada. En el otro extremo del espectro, se sitúa la política pesimista. Esta polí-

tica consiste en bloquear el elemento a acceder y no liberarlo hasta no haber termina-

do de manipularlo y almacenarlo. Por un lado, esta política asegura la consistencia en

todo momento pero tiene como gran desventaja una disminución considerable de la

performance en los casos donde accesos de lectura concurrentes al mismo elemento

son altamente probables.

En un punto intermedio se encuentra la política optimista. El concepto princi-

pal es suponer que el recurso no cambiará mientras se está actualizando. Por consi-

guiente, para mantener la consistencia, es necesario detectar cuando no se cumple.

Para realizar dicha verificación, al momento de almacenar el nuevo valor, se debe

constatar que no haya sido modificado por otro desde la última lectura. Para ello se

debe agregar un indicador al recurso a modo de meta-información, como por ejemplo,

el número de versión o la fecha de última modificación. Este indicador sirve para veri-

ficar que no hubo una operación de actualización simultánea. Si ninguna modificación

ha existido, entonces se procede de manera normal (la suposición optimista se ha

cumplido). En caso contrario, se debe informar al usuario (por ej. a través de una ex-

cepción o código de error) que debe repetir la operación, lo cual implica obtener nue-

vamente el recurso.

La política optimista se debe aplicar en un entorno en el cual los cambios sobre

un mismo recurso no sean muy frecuentes. En caso contrario, se corre el riesgo que

una actualización requiera demasiados intentos para poder concretarse.

7.4.5. Caso de estudio

El caso de estudio que se ha elegido para este patrón es el acceso concurrente a

un registro genérico en una tabla de una base de datos. Dicho registro solo contiene un

atributo a modo de ejemplo y una clave primaria.

7.4.6. Estructura

Los participantes del patrón no tienen una relación estructural entre sí, por lo

cual se eligió un diagrama de interacción para representar al patrón. En este caso, la

interacción de los participantes es más relevante que la estructura de los mismos. El

diagrama de interacción es el siguiente:

Page 111: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 101

Figura 7-16: Interacción del patrón de concurrencia optimista

El diagrama muestra a los siguientes participantes que componen el patrón:

Cliente: Usuario del recurso compartido.

Recurso: Recurso compartido que se pretende sincronizar. Se parte de la base

de que no hay restricciones sobre el acceso al mismo.

Administrador de Concurrencia Optimista: Encargado de controlar que la su-

posición optimista se cumpla, y en consecuencia mantener la consistencia de

los datos. Esto quiere decir que al momento de realizar una operación de al-

macenamiento sobre el recurso, el controlador debe asegurarse que no ha

habido una modificación desde la última vez que ese cliente accedió al mismo.

La interacción que representa al patrón posee los siguientes pasos:

1) El cliente accede a los datos del recurso, con una operación de lectura.

2) El cliente procesa y modifica el valor local de los datos obtenidos del recur-

so.

3) Antes de poder almacenar el valor, el cliente le pide al controlador que vali-

de el estado del recurso.

4) El controlador debe obtener meta-información sobre el recurso, para contro-

lar que no se haya modificado desde que se realizó el paso 1.

5) En el caso de que la suposición optimista se cumple, el cliente procede a al-

macenar los nuevos valores en el recurso compartido.

La interacción previamente descripta corresponde al caso exitoso. En cambio, si la

suposición optimista no se cumpla en el paso 4, el controlador debe informar la situa-

ción al cliente y el recurso debe ser leído nuevamente para retomar la secuencia desde

el paso 2.

Controlador de

Concurrencia Optimista

RecursoCliente

controlar4:

obtener()1:

modificar2:

validar3:

almacenar5:

Page 112: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

102 Patrones de concurrencia y sincronización Diego M.S. Erdödy

7.4.7. Estrategia de implementación Orientada a Aspectos

La implementación se divide en un núcleo reusable y la aplicación del mismo al

caso de estudio.

NÚCLEO

El núcleo consta de un aspecto abstracto que contiene los pointcuts que deben

ser especificados y la lógica reusable del controlador optimista de concurrencia. Por

otro lado, se definen las interfaces para el recurso (BaseRecord) y se provee imple-

mentación para dichas interfaces. A continuación se muestra el diagrama de interac-

ción y la descripción de los componentes:

Figura 7-17: Estructura del Núcleo del patrón “Optimistic Locking”

Interfaces

BaseRecord: Define los atributos comunes a todos los tipos de registros a definir en el

sistema. El único atributo identificado es el “id” que contiene la clave del registro, con

un acceso de sólo-lectura (solamente posee un método getter).

<<aspect>>

OptimisticProtocol

~log : Logger = Logger.getLogger(OptimisticProtocol.class)

<<advice>> <<base>>+after( record : OptimisticRecord, rs : ResultSet ){base = implementationLoad(record, rs)}

<<advice>> <<base>>+after( record : OptimisticRecord ){base = implementationUpdate(record)}

<<advice>> <<base>>+after ( record : OptimisticRecord ){base = implementationCreate(record)}

<<advice>> <<base>>+before( record : OptimisticRecord ){base = update(record)}

<<pointcut>>+ implementationLoad( record : OptimisticRecord, result : ResultSet )

<<pointcut>>+ implementationUpdate( record : OptimisticRecord )

<<pointcut>>+ implementationCreate( record : OptimisticRecord )

#updateVersion( record : OptimisticRecord ) : void

<<pointcut>>+update( record : OptimisticRecord )

+getCurrentVersion( id : OptimisticRecord ) : int

<<introduction>>

OptimisticRecord

-version : int

BaseType

-setVersion( version : int ) : void

<<getter>>+getVersion() : int

-increaseVersion() : void

<<introduction>>

OptimisticRecord

OptimisticRecord

<<getter>>+getVersion() : int

BaseRecord

<<getter>>+getId() : int

Page 113: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 103

OptimisticRecord: Identifica a los registros que van a ser tratados de forma optimista,

adicionándole un atributo de sólo-lectura que identificará la versión del registro (“ver-

sion”).

Aspectos

OptimisticProtocol: Aspecto abstracto que posee el comportamiento común del

patrón. Define un pointcut llamado update que sirve para especificar el momento en el

cual se guarda el registro sobre el cual se aplica el patrón. Sobre este pointcut se espe-

cifica un advice, que es la parte principal del patrón, en donde se verifica que la ver-

sión actual del registro sea igual a la de la información a guardar, sino, se lanza una

excepción para informar al usuario que el registro fue actualizado por un tercero y que

debe obtener la última versión y volver a procesarlo antes de poder guardarlo.

En este aspecto también se realiza la implementación (o introducción) del atributo

version de la interface OptimisticRecord.

Por último, para el manejo automático de la versión, se definen tres pointcuts en don-

de se definirán los momentos de carga, creación y actualización de los registros (im-

plementationLoad, implementationCreate e implementationUpdate). Para cada uno se especi-

fica un advice que agrega la lógica de manejo de la versión. Para ello se agregan dos

métodos abstractos getCurrentVersion() y updateVersion() que serán invocados cuando se

necesite obtener la versión actual o actualizar dicha versión, respectivamente.

APLICACIÓN CONCRETA al CASO DE ESTUDIO

La aplicación al caso de estudio consiste en la definición del registro y el aspec-

to concreto que especifica los pointcuts y comportamiento necesario para el manejo

de la meta-información del recurso. Como se verá más adelante, el manejo de la meta-

información hace que la implementación del patrón no sea completamente localizada.

Page 114: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

104 Patrones de concurrencia y sincronización Diego M.S. Erdödy

Figura 7-18: Estructura de la aplicación del patrón “Optimistic Locking”

Interfaces

Record: Define los atributos correspondientes al registro. En el ejemplo sólo posee un

atributo llamado “attrib”.

Clases

RecordManager: Responsable de administrar los registros encapsulando así el acceso

a la base de datos. Posee un método por cada operación posible sobre un registro. El

método newRecord() tiene una doble función, en el caso de que el id ya exista, se obtie-

ne el registro; si por el contrario el id no existe, entonces se procede a crear un nuevo

registro vacío. El método saveRecord() permite guardar el contenido de un registro y

por último se puede borrar un registro llamando a deleteRecord()

RecordImpl: Implementación del registro. Además de implementar el atributo reque-

rido por la interface, posee la lógica protegida para obtener, crear o actualizar los da-

tos del registro (load(), save() y update()). El método save() efectúa una creación o actua-

lización del registro según el estado en el que se encuentre (si ya fue creado o no).

Estos métodos son utilizados por el RecordManager cada vez que una operación es

requerida sobre un registro. Por último, el método fillAttributes() se encarga de popular

el registro con los datos que se obtienen de la base de datos.

<<aspect>>

OptimisticRecordAspect

<<pointcut>> <<base>>+ implementationLoad( record : OptimisticRecord, result : ResultSet ){base = execution(void RecordImpl.fillAttributes(ResultSet)) && args(rs) && target(record)}

<<pointcut>> <<base>>+update( record : OptimisticRecord ){base = execution (public void RecordManager+.saveRecord(Record)) && args(record)}

<<pointcut>> <<base>>+ implementationUpdate( record : OptimisticRecord ){base = execution(void RecordImpl.update()) && target(record)}

<<pointcut>> <<base>>+ implementationCreate( record : OptimisticRecord ){base = execution(void RecordImpl.create()) && target(record);}

#updateVersion( record : OptimisticRecord ) : void

+getCurrentVersion( id : OptimisticRecord ) : int

<<declare parents>>

Record implements OptimisticRecord

RecordImpl

~log : Logger = Logger.getLogger(RecordImpl.class)

-isDirty : boolean = false

-isNew : boolean = true

-attrib : String

-id : int

<<setter>>+setAttrib( attrib : String ) : void

<<constructor>>+RecordImpl( id : int )

#fillAttributes( rs : ResultSet ) : void

<<getter>>+getAttrib() : String

<<getter>>+getId() : int

+load() : boolean

#update() : void

#create() : void

+delete() : void

+save() : void

Record

<<setter>>+setAttrib( attrib : String ) : void

<<getter>>+getAttrib() : String

RecordManager

+saveRecord( record : Record ) : void

<<constructor>>-RecordManager()

+deleteRecord( id : String ) : void

+newRecord( id : int ) : Record

OptimisticRecord

<<getter>>+getVersion() : int

BaseRecord

<<getter>>+getId() : int

<<aspect>>

OptimisticProtocol

Page 115: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de concurrencia y sincronización 105

ConnectionPool: Implementación para el soporte de un repositorio de conexiones de

base de datos. Para obtener una nueva conexión basta con llamar al método estático

getConnection(). Nótese que la implementación sólo soporta una base de datos y esto es

intencional, para simplificar el caso de estudio.

Aspectos

OptimisticRecordAspect: Aspecto concreto que extiende de OptimisticProtocol. Este

aspecto realiza la vinculación necesaria para aplicar el patrón al registro del caso de

estudio. La primera acción que toma, es extender la interface Record de Optimisti-

cRecord para poder hacer uso del atributo version. Luego, como definición del point-

cut update, define la llamada al método save() de la clase RecordManager o cualquiera

de sus derivados. También agrega la implementación específica de los métodos getCu-

rrentVersion() y updateVersion(), conectándose directamente a la base de datos y obte-

niendo o actualizando el atributo que representa el número de versión. Por último, se

mapean los pointcuts implementationLoad, implementationCreate e implementationUpdate

con la llamada a los métodos fillAttributes(), create() y update() de la clase RecordImpl.

7.4.8. Análisis

El patrón se ha podido modularizar y localizar, pero no en forma completa.

Quedan implementaciones tales como el manejo de la meta-información del recurso

que tiene que ser implementado para cada caso en particular, siendo parte central del

patrón. El análisis de las características es el siguiente:

Localidad del código: En este caso se puede catalogar el código de la imple-

mentación como „muy localizado‟ dado que ciertos métodos han tenido que

ser implementados en el aspecto concreto, pero el comportamiento asociado a

la sincronización optimista, se pudo abstraer en un modulo reusable.

Reusabilidad: La localidad del código lograda, permite alcanzar un alto nivel

de reusabilidad. La reusabilidad no es total, ya que los métodos getCurrentVer-

sion() y updateVersion() del aspecto concreto deben ser implementados por cada

aplicación.

Independencia: El nivel de independencia es alto pero no es total. La indepen-

dencia se pierde, por ejemplo, cuando la estructura del registro incorpora un

nuevo atributo que utiliza la misma denominación que el atributo utilizado pa-

ra identificar el número de versión.

Transparencia de composición: En este caso, no tiene sentido aplicar más de

una vez el patrón al mismo tipo de registro.

7.4.9. Componente gráfico

En este caso se implementaron los siguientes componentes visuales:

Table: Representa una tabla en la base de datos que contiene registros del tipo

“Record”. Se puede configurar el nombre de la tabla y se visualiza el conteni-

do de los registros.

Page 116: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

106 Patrones de concurrencia y sincronización Diego M.S. Erdödy

OptimisticRecord: Registro del tipo “Record” en su versión optimista el cual

se puede asociar a un elemento del tipo Table. Posee las siguientes propieda-

des:

o Record id: clave del registro con el que se desea trabajar.

o Record value: valor del atributo del registro.

En tiempo de simulación se pueden invocar las siguientes acciones:

o Save: Intenta guardar el registro en la base de datos.

o Retrieve: Sobrescribe la instancia del registro con el valor de la base de

datos.

En la siguiente figura se observa un diagrama con una tabla y dos registros, “re-

c1” y “rec2”, los cuales poseen el mismo id (0 en este caso):

Figura 7-19: Diagrama del patrón “Optimistic Locking”

Una vez iniciada la simulación, en caso de existir el id de algún registro, cada

registro obtiene su información de la base de datos. De manera interactiva, se puede

guardar cualquiera de los registros presionando el botón “save”. Como consecuencia,

se incrementa en uno el número de versión almacenado en la base de datos. En el dia-

grama se muestra que “rec1” ha sido recientemente guardado y posee el número de

versión 3. De la misma forma, se puede cargar el nuevo valor en “rec2” presionando

el botón “retrieve” del componente. Si en lugar de esto se hubiese querido quiere

guardar el valor de “rec2”, el mecanismo optimista se encargaría de avisar que se debe

actualizar el registro antes de poder guardarlo, dado que el número de versión que

contiene es menor al que se encuentra en la base de datos. Esta discrepancia indica

que alguien ha hecho una modificación desde que fue cargado por última vez. Este

caso es el que muestra la figura.

Page 117: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de manejo de eventos 107

8. Patrones de manejo de eventos

8.1. Reactor

8.1.1. Resumen

El patrón de diseño Reactor [Sch 95] separa las responsabilidades de un proveedor

de servicios en un entorno cliente-servidor distribuido, con acceso concurrente a los dis-

tintos servicios. El patrón está compuesto por un demultiplexor sincrónico, que tiene co-

mo responsabilidad acceder a los distintos canales de comunicación de manera sincrónica

e identificar y decodificar los eventos relevantes. También está compuesto por un notifi-

cador, es el encargado de recibir y administrar dichos eventos así como también de notifi-

car a los procesadores correspondientes. Por último, el EventHandler es el que procesa un

evento en particular, sin necesidad de intervenir en la administración de los eventos.

8.1.2. Otras denominaciones

Notificador, Despachante (“Dispatcher”).

8.1.3. Problema

El desarrollo de servidores concurrentes plantea ciertos problemas en cuanto al mo-

do de atender los pedidos. Las necesidades a tener en cuenta son:

El servidor debe brindar una separación clara de responsabilidades entre la

recepción de pedidos, el manejo de los eventos y el procesamiento de los

mismos por parte de los distintos servicios.

El servidor debe tener una alta disponibilidad. Esto implica que no debe

bloquear el ingreso de nuevos pedidos, al esperar el ingreso de un pedido

en particular o el procesamiento de otro pedido en curso.

El servidor se debe adaptar de manera sencilla a los cambios en el formato

de los requerimientos o a la incorporación de nuevos servicios.

El servidor debe brindar una alta performance. Se debe maximizar la can-

tidad de pedidos procesados por unidad de tiempo y al mismo tiempo mi-

nimizar la latencia y el consumo de procesador.

Una de las implementaciones más simples consta de un componente que esté escu-

chando alternativamente en cada canal, por un período de tiempo prefijado, y que al mo-

mento de recibir un pedido, inicie un hilo de ejecución en donde se procese dicho evento.

Un problema asociado a esta implementación es que la creación de nuevos hilos de eje-

cución es generalmente costosa en cuanto a recursos del sistema operativo (desde ya que

dependerá de la implementación del SO que se esté utilizando) y limita la cantidad de

pedidos que se pueden procesar concurrentemente.

Page 118: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

108 Patrones de manejo de eventos Diego M.S. Erdödy

8.1.4. Solución

La solución propuesta por el patrón consiste en desacoplar los componentes de la

siguiente manera. Los proveedores del servicio, responsables de procesar un tipo de even-

to específico, serán implementaciones de una interfaz común denominada EventHandler.

Los EventHandler se registran a un componente llamado InitiationDispatcher, que será el

encargado de interceptar los eventos y transmitirlos al EventHandler adecuado. Para esta

tarea cuenta con un Event Demultiplexer cuyo objetivo es la recepción física y decodifi-

cación del evento de una manera sincrónica.

Esta solución aplica el concepto de Inversión de Control (IoC) ya que los proveedo-

res de los servicios no tienen que preguntar periódicamente por la llegada de un evento,

sino que la responsabilidad es delegada en otro componente que lo notificará en el mo-

mento adecuado. El mecanismo es similar al patrón Observador.

8.1.5. Caso de estudio

El caso de estudio elegido, basado en el trabajo original [Sch 95], es un servidor de

bitácora (log) distribuido. El servidor recibe mensajes de clientes, a través del protocolo

orientado a conexión TCP, y registra un archivo histórico de los mismos.

8.1.6. Estructura

El patrón se basa en separar los roles de recepción e identificación de eventos y el

procesamiento de los mismos. A continuación se muestra el diagrama de estructura co-

rrespondiente al patrón y la descripción de los participantes que cumplirán dichos roles:

Figura 8-1: Estructura del patrón “Reactor”

Los participantes del patrón son los siguientes:

EventHandler: Encargado de procesar un determinado tipo de evento. El proce-

samiento es llevado a cabo en el método handleEvent().

+handleEvent(in event : Event)

+getHandle() : Handle

«interface»

EventHandler

+handleEvents()

+registerHandler(in handler : EventHandler, in event : Event)

+deregisterHandler(in handler : EventHandler, in event : Event)

InitiationDispatcher

«interface»

Handle

1

1

1*

Synchronous Event Demultiplexer

1

1

1 *

Page 119: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de manejo de eventos 109

Handle: Objeto encargado del acceso a un canal de comunicaciones de entrada

(como por ejemplo un socket TCP), por el cual ingresan los eventos.

Synchronous Event Demultiplexer: Espera sobre un grupo de Handles e informa

cuando se recibió un evento relevante que puede ser procesado.

InitiationDispatcher: Objeto mediador entre el canal de comunicación y los

EventHandlers. Contiene un conjunto de pares “Event-EventHandler” que especi-

fican cual EventHandler deberá atender cierto tipo de evento. Define los métodos

registerHandler() y deregisterHandler() para agregar o quitar pares al conjunto, res-

pectivamente. El método handleEvents() utiliza el demultiplexer para esperar la

llegada de eventos y los entrega al EventHandler correspondiente.

8.1.7. Estrategia de implementación Orientada a Aspectos

El núcleo del patrón se divide en dos partes. Por un lado, los elementos involucra-

dos en el procesamiento de los eventos y por otro, los concernientes a la recepción y deri-

vación de dichos eventos.

NÚCLEO - Procesamiento de Eventos

La parte de procesamiento de eventos del núcleo, contiene las interfaces que defi-

nirán los puntos de extensión del patrón. También define los elementos básicos como el

evento a utilizar y la encapsulación de la conexión (Handle).

El diagrama de estructura es el siguiente:

Page 120: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

110 Patrones de manejo de eventos Diego M.S. Erdödy

Figura 8-2: Estructura del Núcleo (sector Event Handling) del patrón “Reactor”

Interfaces

EventHandler: Procesador de eventos que implementará un servicio en particular. Posee

un método handleEvent() dedicado al procesamiento propiamente dicho del evento al cual

se registró. El método getHandle() permite obtener la referencia del canal asociado al

evento, para poder acceder a los datos que formarán parte de la entrada del proceso.

Acceptor: Tipo especial de EventHandler cuya responsabilidad es recibir nuevas co-

nexiones. El Handle asociado debe ser de tipo servidor (para recibir conexiones) y cuan-

do se recibe una nueva conexión, el nuevo Handle creado se almacena bajo el atributo

peerHandle. Generalmente, se registra a eventos del tipo OPEN_SERVICE (nueva co-

nexión) y el procesamiento implica la registración de un EventHandler específico del

servicio que atenderá los eventos de datos de la conexión cliente.

Clases

Event: Clase que encapsula el evento que será transmitido. El evento se identifica por un

código numérico. Ya que se trata de un objeto inmutable (que no puede cambiar de esta-

do), dicho código se debe proveer al momento de construirlo y solo se puede acceder a

través del método getCode().

Handle: Encargado del acceso a un canal TCP. El acceso al canal se puede iniciar en mo-

do servidor, especificando solamente el puerto en el constructor, o en modo cliente, en

Event

<<JavaElement>>+equals( ev : Object ) : boolean{JavaAnnotations = @Override}

<<JavaElement>>+toString() : String{JavaAnnotations = @Override}

<<JavaElement>>+hashCode() : int{JavaAnnotations = @Override}

<<constructor>>+Event( code : byte )

<<getter>>+getCode() : byte

Handle

+waitForEvent( timeout : int, dispatcher : InitiationDispatcher ) : boolean

<<constructor>>+Handle( host : String, port : int )

<<setter>>+setInUse( b : boolean ) : void

<<constructor>>+Handle( s : Socket )

<<constructor>>+Handle( port : int )

<<getter>>+getLastEvent() : Event

+write( b : byte"[]" ) : void

+read( b : byte"[]" ) : void

+write( o : Object ) : void

+write( e : Event ) : void

+waitForDeath() : void

+read() : Object

+close() : void

<<introduction>>

Acceptor

<<introduction>>

EventHandler

BaseTypeA

-peerHandle : Handle

<<setter>>+setPeerHandle( handle : Handle )

<<getter>>+getPeerHandle() : Handle

<<setter>>+setPeerHandle( h : Handle ) : void

Acceptor

BaseTypeEH

-reactor : Reactor

-handle : Handle

<<setter>>+setReactor( reactor : Reactor )

<<setter>>+setHandle( handle : Handle )

<<getter>>+getReactor() : Reactor

<<getter>>+getHandle() : Handle

EventHandlerImpl

AcceptorImpl

EventHandler

<<getter>>+getHandle() : Handle

+handleEvent( e : Event ) : void

<<introduction>>

Acceptor

<<introduction>>

EventHandler

<<crosscut>>

<<crosscut>>

Page 121: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de manejo de eventos 111

cuyo caso se debe proveer además la dirección de destino. Posee métodos de lectu-

ra/escritura (read() y write() y de recepción sincrónica de eventos (waitForEvent()). También

se puede acceder al último evento recibido (getLastEvent()).

Aspectos

EventHandlerImpl: Aspecto encargado de la implementación de la interface EventHand-

ler. Introduce los atributos reactor y handle, y los métodos getter y setter de dichos atribu-

tos.

AcceptorImpl: Implementación de la interface Acceptor. Introduce el atributo peerHandle

y los métodos getter y setter asociados.

NÚCLEO – Direccionamiento de Eventos

La parte de direccionamiento de eventos del núcleo tiene como responsabilidad la

recepción y entrega de los eventos a los EventHandlers correspondientes. Para ello cuenta

con un mecanismo de registración de EventHandlers a eventos de un tipo específico.

El patrón original está pensado para lenguajes como C, que poseen mecanismos ta-

les como el select, el cual permite capturar eventos sobre múltiples Handles de manera

simultánea. Para reemplazar dicho mecanismo, se utilizó un esquema de round-robin so-

bre los handles con un tiempo de expiración ajustable.

El diagrama de estructura es el siguiente:

Figura 8-3: Estructura del Núcleo (sector Event Dispatching) del patrón “Reactor”

Clases

Reactor: Componente central del patrón. Actúa de fachada para el InitiationDispatcher

que opera por detrás. Posee métodos para registrar y quitar EventHandlers al mecanismo

de reacción. El método handleEvents() inicia dicho mecanismo. El método stopHandling()

detiene el mecanismo.

InitiationDispatcher: Encargado del mecanismo de reacción. Extiende de la clase Thread

para poder correr en un hilo de ejecución independiente. El método start() inicia el meca-

nismo que consiste en recorrer los distintos EventHandlers y esperar un determinado

tiempo a que ocurra algún evento. Ante la llegada de un evento se ejecuta el EventHand-

ler registrado. De lo contrario se sigue con el siguiente.

Reactor

+registerHandler( handler : EventHandler, type : Event ) : void

+removeHandler( handler : EventHandler, type : Event ) : void

+handleEvents( timeout : long ) : void

+stopHandling() : void

InitiationDispatcher

<<getter>>+getEventInfoManager() : HandleInfoManager

<<getter>>+getCurrentHandleInfo() : HandleInfo

+run() : void

+kill() : void

HandleInfoManager

+registerHandler( eh : EventHandler, e : Event ) : void

+removeHandler( eh : EventHandler, e : Event ) : void

<<getter>>+getCurrentHandleInfo() : HandleInfo

<<getter>>+getNextHandleInfo() : HandleInfo

HandleInfo

<<constructor>>+HandleInfo( eh : EventHandler )

<<getter>>+getEventHandler() : EventHandler

<<getter>>+getEvents() : Collection

+removeEvent( event : Event ) : void

<<getter>>+getHandle() : Handle

+addEvent( event : Event ) : void

EventHandler

Handle Event

Page 122: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

112 Patrones de manejo de eventos Diego M.S. Erdödy

HandleInfoManager: Encargado de administrar la información de registraciones de

EventHandlers y el recorrido de los mismos. Los métodos getCurrentHandleInfo() y get-

NextHandleInfo() permiten recorrer los EventHandlers.

HandleInfo: Contenedor de la asociación entre un EventHandler y los distintos eventos

a los cuales se registró. Posee métodos para el acceso al EventHandler y agregar o quitar

eventos. El método getHandle() devuelve el Handle asociado al EventHandler.

APLICACIÓN CONCRETA al CASO DE ESTUDIO

La aplicación del patrón consta de las implementaciones de las dos interfaces que

definen los puntos de extensión y un objeto que representa a un cliente del servicio. El

diagrama de estructura es el siguiente:

Figura 8-4: Estructura de la aplicación concreta del patrón “Reactor”

Clases

LoggingClient: Cliente encargado de enviar los pedidos de log al servidor. El constructor

debe recibir la información necesaria para conectarse con el servidor remoto, es decir, el

nombre de host y el puerto. El método log() envía el mensaje especificado mientras que el

método close() cierra la conexión.

LogginAcceptor: Aceptor de conexiones para el servicio de logging que implementa la

interface Acceptor. El método handleEvent() crea y registra un nuevo handler del tipo Log-

gingHandler sobre el peerHandler.

LoggingHandler: Procesador del servicio de logging. El método handleEvent() registra el

mensaje recibido.

8.1.8. Análisis

La implementación AOP de este patrón tiene poca relevancia ya que los aspectos

solamente se utilizaron para la implementación de las interfaces (en vez de usar clases

abstractas). Si bien existen características positivas en la implementación, como localidad

y reusablidad moderadas, es mérito del diseño OOP y no es una contribución por parte de

AOP. A continuación se detalla el análisis de la implementación:

LoggingClient

<<constructor>>+LoggingClient( host : String, port : int )

<<setter>>+setHostName( hostName : String ) : void

<<setter>>+setPort( port : int ) : void

<<getter>>+getHostName() : String

<<constructor>>+LoggingClient()

<<getter>>+getPort() : int

+log( s : String ) : void

+close() : void

+init() : void

<<constructor>>+LoggingHandler( handle : Handle )

<<constructor>>+LogginHandler()

+logMessage( message : String )

+handleEvent( evt : Event ) : void

+init()

LoggingHandler LoggingAcceptor

<<constructor>>+LoggingAcceptor( port : int )

<<constructor>>+LoggingAcceptor()

+handleEvent( e : Event ) : void

+init()

EventHandler Acceptor

Page 123: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de manejo de eventos 113

Localidad del código: La localidad lograda con OOP no se pudo mejorar con

AOP. El manejo de eventos dentro del Handler y el Acceptor en su totalidad, son

componentes propios del patrón que no han podido desacoplarse de la implemen-

tación del caso de estudio. Por lo tanto se considera que no hay localidad.

Reusabilidad: De la misma forma, la reusabilidad no ha mejorado con la imple-

mentación AOP y existe código propio del patrón que debe implementarse cada

vez que se aplique a un caso en particular.

Independencia: No existe la independencia, ya que el código no asociado al

patrón (el método log()) no tiene sentido sin los componentes que lo rodean.

Transparencia de composición: El mismo EventHandler puede intervenir en más

de un reactor de una manera transparente.

8.1.9. Componente gráfico

Los siguientes componentes fueron implementados:

LogClient: Cliente del servicio de logging. Permite enviar un mensaje de log a un

server en particular. Posee las siguientes propiedades:

o hostname: dirección del host donde reside el servidor, en caso de una co-

nexión remota.

o port: puerto TCP donde está instalado el servidor, para el caso de una co-

nexión remota.

o message: mensaje que se enviará al servidor.

El componente posee una acción para enviar el mensaje, denominada log(). Ya que

el componente no contiene lógica asociada a la ejecución de la simulación, sólo

tiene sentido ejecutarlo en modo interactivo y poder activarlo por medio de la ac-

ción.

El componente puede operar de forma local o remota. La primera opción se reali-

za a través de una conexión en el diagrama a un componente LogServer. Para la

opción remota, se deben configurar las propiedades hostname y port del servidor

remoto.

LogServer: Servidor de logging. Permite conexiones con componentes LogClient,

en cuyo caso se establece una conexión local. También permite conexiones remo-

tas, via TCP. La historia de los mensajes recibidos la muestra en el compartimien-

to de estado.

El siguiente es un ejemplo que muestra a un servidor conectado localmente a dos

clientes:

Page 124: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

114 Patrones de manejo de eventos Diego M.S. Erdödy

Figura 8-5: Diagrama ACVF del caso de estudio para el patrón “Reactor”

El diagrama corresponde a una simulación en donde se ha invocado la acción del

componente logclient dos veces y luego se ha repetido la operación sobre el componente

logclient2. En el componente logserver se puede ver la historia de los mensajes recibidos.

Page 125: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de seguridad y fiabilidad 115

9. Patrones de seguridad y fiabilidad

9.1. Watchdog

9.1.1. Resumen

Un Watchdog es un componente que supervisa el comportamiento de una carac-

terística determinada de otro componente. Dicha supervisión tiene como objetivo elimi-

nar errores groseros que pueden ocurrir dentro del sistema, como por ejemplo, el orden de

ejecución de diferentes pasos o restricciones de tiempo.

9.1.2. Otras denominaciones

Sentinela

9.1.3. Problema

Un sistema de tiempo real se podría simplificar en eventos que tienen que ocurrir

dentro de un período específico de tiempo, fuera del cual dichos eventos no tienen rele-

vancia o sentido. En estos sistemas, es necesario verificar que el funcionamiento básico

del sistema sea el correcto (ya sea en el dominio del tiempo, en la sucesión de eventos o

en algún otro criterio) y actuar, aunque sea de manera drástica, en consecuencia.

9.1.4. Solución

El fundamento del patrón, consiste en contar con un participante llamado Watch-

dog, que se encargará de verificar periódicamente el estado de salud del sistema. En caso

de detectar una anomalía, procederá con alguna acción predeterminada como puede ser la

reinicialización del sistema.

En sistemas de tiempo real, las verificaciones que se realizan sobre el sistema, ge-

neralmente están relacionadas a una base de tiempo que actúa de referencia.

9.1.5. Caso de estudio

El caso de estudio que se ha elegido para este patrón es el de un marcapasos vigila-

do por un supervisor. El supervisor debe asegurar que los latidos que indique el marcapa-

sos estén en un rango determinado de tiempo, es decir, la distancia entre dos latidos con-

secutivos no debe superar el límite superior ni estar por debajo del límite inferior.

Page 126: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

116 Patrones de seguridad y fiabilidad Diego M.S. Erdödy

9.1.6. Estructura

El siguiente es un diagrama de componentes del patrón:

Figura 9-1: Diagrama de estructura del patrón “Watchdog”

El diagrama presenta un caso general de procesamiento en tiempo real a verificar,

representado por el canal de actuación y sus componentes. El watchdog recibe por un

lado, la información enviada por los componentes de transformación y procesamiento de

salida, así como también, una referencia temporal independiente, para poder tomar deci-

siones en ese dominio. En caso de que el watchdog detecte una anomalía, inmediatamente

informará al sistema para que este tome las acciones necesarias, que pueden ser registrar

el incidente, apagar o efectuar una verificación de integridad del sistema.

Los participantes del patrón son:

Canal de Actuación: Canal a través del cual se comunican los distintos compo-

nentes que forman parte del circuito de actuación. Dicho circuito comprende tanto

las señales de entrada de los sensores, el procesamiento de los datos como así

también las señales de salida hacia los componentes de actuación.

Actuation Data Source: Representa la entrada de datos al sistema desde los dis-

positivos de sensado.

Procesador de Entrada: Transforma los datos enviados por los dispositivos de

sensado en datos que puedan ser comprendidos por el procesador.

Actuator: Dispositivo físico que ejecuta una acción sobre el sistema a partir de los

datos provistos por el canal de actuación.

Procesador de Salida: Encargado de transformar los datos de salida de forma tal

que sean correctamente comprendidos por el dispositivo actuador.

Procesador de Datos: Procesa los datos recibidos por los sensores, ya sea de ma-

nera secuencial (un solo dato permanece en el canal a la vez) o paralela (puede

haber múltiples datos en diferente etapa de procesamiento en el canal para un de-

terminado momento).

Base de tiempo: Referencia temporal independiente que guía el funcionamiento

del Watchdog.

Origen de

datos de actuaciónActuador

Base de tiempo

Procesamiento

de entrada

Tansformación

de datos

Procesamiento

de salida

Watchdog

Canal de actuación

Transición de procesamiento

Reportar anomalía

Señal de control

Page 127: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de seguridad y fiabilidad 117

Watchdog: Espera por una señal periódica enviada por los componentes del canal

de actuación. Si dicha señal no es recibida dentro del tiempo esperado, debe indi-

car la anomalía al canal.

9.1.7. Estrategia de implementación Orientada a Aspectos

El patrón se divide en una capa reusable o núcleo y la aplicación al caso de estudio

correspondiente.

NÚCLEO

El núcleo consta de un aspecto abstracto que contiene la lógica reusable del patrón

y dos interfaces que definen los roles del patrón. El siguiente es el diagrama de estructura

y la descripción de los elementos:

Figura 9-2: Estructura del Núcleo del patrón “Watchdog”

Interfaces

WatchDog: Definición de la interface de un watchdog. Posee un método init() para reali-

zar tareas de inicialización y el método principal processSignal() que será llamado cada vez

que la señal que supervisa sea activada.

Resetable: Indica que un componente puede ser reiniciado. Esto se realiza a través del

método reset().

Aspectos

WatchDogProtocol: Aspecto abstracto que posee el comportamiento generalizable del

patrón. Posee un atributo que almacena el Watchdog a utilizar y un método setWatchdog

<<aspect>>

WatchDogProtocol

#wd : WatchDog

<<advice>> <<base>>+after returning( r : Resetable ){base = watchableCall(r)}

<<advice>> <<base>>+before( r : Resetable ){base = initCall(r)}

<<pointcut>>+initCall( resetab le : Resetable )

+setWatchDog( watchdog : WatchDog ) : void

<<pointcut>>+watchableCall( r : Resetable )

#sendSignal( r : Resetable ) : void

#init( r : Resetable ) : void

WatchDog

+processSignal( r : Resetable ) : void

+init() : voidResetable

+reset() : void

Page 128: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

118 Patrones de seguridad y fiabilidad Diego M.S. Erdödy

para asignarlo. Define dos pointcuts abstractos, initCall(Resetable) y watchable-

Call(Resetable). El primero permite especificar cuál será el momento de inicialización del

componente a supervisar para que el watchdog pueda hacer alguna tarea de inicialización

acorde. El segundo permite especificar cuál será el punto a supervisar dentro del compo-

nente. También posee un advice asociado a cada uno de los pointcuts abstractos. El pri-

mer advice indica que antes de llamar al pointcut initCall, se llame al método protegido

init() del aspecto. Este llama al método init() del watchDog. El segundo advice indica que

luego de terminar con el pointcut watchableCall(), se llame al método protegido sendSig-

nal(), el cual llama al método processSignal() del watchDog.

APLICACIÓN CONCRETA al CASO DE ESTUDIO

La aplicación del patrón se lleva a cabo con la implementación de las interfaces

provistas para la definición de los roles y la especialización del aspecto abstracto, que

define los valores para los dos pointcuts. También se proveen los objetos que representan

a los participantes del caso de estudio, el Watchdog y el Pacemaker. El diagrama de es-

tructura y la descripción es el siguiente:

Figura 9-3: Estructura de la aplicación del patrón “Watchdog” al caso de estudio

Clases

Pacemaker: Representación de un marcapasos. Posee un método para inicializar el mar-

capasos llamado init() y uno para reiniciarlo, en caso de alguna falla, llamado reset(). El

método run() pone en funcionamiento la actividad del marcapasos, mientras que el méto-

do stop() lo detiene. Permite configurar tanto el tiempo medio de cada latido, como así

también el intervalo entre latidos, a través de los getters y setters de las propiedades bea-

<<instantiation>>

<<aspect>>

PacemakerWatchDogSignal

{instantiation = pertarget(initCall(Resetable))}

<<base>> <<pointcut>>+watchableCall( r : Resetable ){base = execution (void Pacemaker+.markBeat()) && target(r)}

<<base>> <<pointcut>>+initCall( resetable : Resetable ){base = execution (void Pacemaker+.init()) && target(r)}

<<declare parents>>

Pacemaker implements Resetable

<<setter>>+setBeatLength( beatLength : long ) : void

<<setter>>+setBeatInterval( interval : long ) : void

<<getter>>+getBeatInterval() : long

<<getter>>+getBeatLength() : long

#markBeat() : void

+toString() : String

+reset() : void

+stop() : void

+run() : void

+init() : void

Pacemaker

TimerWatchdog

<<setter>>+setMaxLevel( maxLevel : long ) : void

<<setter>>+setMinLevel( minLevel : long ) : void

+processSignal( r : Resetable ) : void

<<constructor>>+TimerWatchdog()

<<getter>>+getLastInterval() : long

<<getter>>+getMaxLevel() : long

<<getter>>+getMinLevel() : long

+init() : void

WatchDog

+processSignal( r : Resetab le ) : void

+init() : void

<<aspect>>

WatchDogProtocol

Resetable

+reset() : void

Page 129: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de seguridad y fiabilidad 119

tLength y beatInterval. Por último, el método markBeat() representa la funcionalidad del lati-

do en sí mismo.

TimerWatchdog: Implementación de la interface WatchDog. Se basa en la revisión del

tiempo de los intervalos delimitados por cada señal. Si en algún caso, dicho intervalo se

encuentra fuera de los límites prefijados, entonces se dispara la reinicialización del com-

ponente. Posee dos propiedades que representan el límite mínimo (minLevel) y el máxi-

mo (maxLevel) de tolerancia. También posee un método para obtener el intervalo medido

entre las dos últimas señales llamado getLastInterval().

Aspectos

PacemakerWatchDogSignal: Aspecto concreto que extiende de WatchDogProtocol y

configura la aplicación del patrón. Por un lado hace que Pacemaker implemente la inter-

face Resetable. Por otro lado, especifica que el pointcut a supervisar será la llamada al

método markBeat() de Pacemaker o cualquier clase derivada y que el pointcut de iniciali-

zación será el método init() del mismo conjunto de clases. Por último, se especifica que el

modo de instanciación del aspecto sea “por target” dado que el Watchdog a utilizar es

único. De no ser así, el mismo watchdog se haría cargo de todas las aplicaciones del

patrón dentro de la misma JVM, sin la posibilidad de configurar cada uno por separado.

9.1.8. Análisis

De los diagramas de estructura, se desprende que el patrón ha podido modularizarse de

forma completa, ya que en la aplicación del patrón sólo se definen puntos de inserción. A

continuación se analizan las características de la implementación:

Localidad del código: Hay localidad completa de la lógica inherente al patrón en

el aspecto abstracto.

Reusabilidad: Es total dado que sólo hace falta indicar los roles y pointcuts para

poder aplicar el patrón.

Independencia: El rol definido como elemento a observar sólo requiere que im-

plemente la interface Resetable. Dado que este comportamiento puede ser inserta-

do por medio de un aspecto, el objeto que debe implementar el rol se independiza

de manera completa del patrón.

Transparencia de composición: Varias aplicaciones del patrón pueden convivir

transparentemente dentro del mismo componente ya que no tiene requerimiento

alguno.

9.1.9. Componente gráfico

Para este caso se han implementado dos componentes gráficos. El primero, llamado

“Pacemaker” representa un marcapasos. Este tiene dos propiedades configurables, la du-

ración de cada latido y el intervalo entre latidos, ambos expresados en milisegundos. El

segundo, simula un Watchdog y se puede vincular al marcapasos que se quiera controlar.

Tiene como propiedades configurables, los límites de tiempo máximo y mínimo tolera-

Page 130: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

120 Patrones de seguridad y fiabilidad Diego M.S. Erdödy

bles entre latidos. El siguiente es un diagrama que muestra a ambos funcionando en una

simulación:

Figura 9-4: Simulación de patrón Watchdog

Los latidos del marcapasos se pueden visualizar en la zona de texto del componente

mientras que el Watchdog indica el tiempo que ha pasado desde la detección del último

latido. En caso de que este tiempo esté fuera de los límites prefijados, el Watchdog pro-

cede a reinicializar el componente controlado.

Vale aclarar que un marcapasos puede ser controlado por más de un Watchdog a la

vez, lo que deja en claro el alto nivel de transparencia de composición que presenta el

patrón.

Figura 9-5: Propiedades de los componentes gráficos Pacemaker y Watchdog

La simulación permite visualizar la interacción entre ambos componentes. Para el

caso del marcapasos, el compartimiento de estado muestra un mensaje cada vez que se

marca un latido, por el tiempo que dure. Dichos valores dependerán de la configuración

Page 131: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Patrones de seguridad y fiabilidad 121

del componente. El Watchdog, por su parte, muestra en el compartimiento de estado, la

duración entre los últimos dos latidos. También muestra si se ha salido de los parámetros

configurados y qué acción se ha tomado en caso afirmativo.

Page 132: Aplicación de programación orientada a aspectos a patrones de ...
Page 133: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Resultados y Conclusiones 123

10. Resultados y Conclusiones

La siguiente es una tabla comparativa de los resultados obtenidos luego del análisis

de los distintos patrones de diseño:

Nombre del patrón

Propiedades de modularidad Tipos de Roles

Locali-dad

Reusabilidad Transparen-cia de com-

posición

Inde-penden-

cia Únicos

Superpues-tos

Balking Sí Sí Sí Sí - BalkingClient, BalkingCom-

ponent

Observador Sí Sí Sí Sí - Publisher, Subscriber

Rendezvous Sí Sí Sí Sí Rendezvous Rendezvous-

Member

Watchdog Sí Sí Sí Sí Watchdog Watchdog-Component

Optimistic Alta4 Alta Sí Alta Optimistic-Controller

Client, Resource

Reactor No No Sí No Reactor, Acceptor, Handler

EventHandler

En la primera columna se listan todos los patrones de diseño analizados. Luego le

sigue el listado de las cuatro propiedades que han sido analizadas y por último una sepa-

ración de los roles de cada patrón según su tipo.

Al igual que en el trabajo hecho sobre los patrones GoF [Han 02], se han dividido

los roles que componen cada patrón en dos tipos y a continuación se verá qué relación

existe entre la cantidad de roles de cada tipo por patrón y la capacidad de cumplir con

cada una de las características analizadas.

Los roles únicos son los roles del patrón que son implementados por un componen-

te que no tiene funcionalidad más allá del rol que le es asignado. Esto quiere decir que

sólo existe para cumplir el rol dentro del patrón y, por lo tanto, es definido por él. En

cambio, los roles superpuestos son los roles cuyos componentes comparten la funciona-

lidad con roles fuera del patrón. Por ejemplo, el rol de Sujeto, en el patrón Observador, es

un rol superpuesto ya que quien lo implemente, siempre va a cumplir uno o más roles

adicionales. Si no fuera así, no habría nada que observar. Por otro lado, la implementa-

ción del rol Rendezvous en el patrón del mismo nombre, sólo cumple esa función, no

tiene ninguna responsabilidad fuera del patrón.

En el trabajo de Hannemann [Han 02], se dividen los patrones en tres grupos según

los tipos de roles que posean: (a) los que sólo poseen roles superpuestos, (b) los que po-

seen roles de ambos tipos y por último, (c) los que únicamente poseen roles únicos. En

este trabajo no se han identificado patrones del grupo c, aunque el más cercano por canti-

dad de roles únicos, es el patrón Reactor.

4 La clasificación “Alta” indica que faltaron algunos detalles para lograr el objetivo de la propiedad. No se

intenta utilizar una escala de graduación para cada propiedad. Sólo si se cumplió o no, con la salvedad de la

calificación “Alta” para identificar casos cercanos al Sí.

Page 134: Aplicación de programación orientada a aspectos a patrones de ...

Generación automática de redes neuronales con ajuste de parámetros basado en algoritmos genéticos

124 Resultados y Conclusiones Diego M.S. Erdödy

Los resultados obtenidos para los patrones analizados es similar al encontrado por

Hannemann. Para los patrones del grupo (a), todas las propiedades se cumplen comple-

tamente. Esto indica que la modularización ha sido total. Para el grupo (b), el resultado

varía levemente en algunos patrones, en nuestro caso para el patrón Optimista. Si bien el

grado de modularidad es elevado, existen detalles que no han podido abstraerse. Por últi-

mo, para el grupo (c), la utilidad de la aplicación de aspectos es limitada o nula. El patrón

Reactor se puede tomar como ejemplo de este caso.

Page 135: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Futuros trabajos 125

11. Futuros trabajos

El presente trabajo se realizó con una implementación de AOP “genérica” o de

propósito general, como lo es AspectJ. Para la aplicación en patrones concurrentes y dis-

tribuidos especialmente, sería más adecuada la utilización de una implementación orien-

tada específicamente a un entorno distribuido. Al comienzo del trabajo se analizó la

herramienta DJCutter, pero fue descartada por no contar con el nivel de madurez, soporte

y documentación suficiente.

DJCutter [Mug 03], es una herramienta pensada para la aplicación de AOP en en-

tornos distribuidos. DJCutter es una extensión al lenguaje AspectJ que permite declarar

pointcuts distribuidos, es decir, que capture joinpoints de JVMs situados en máquinas

diversas. Para dicha tarea provee de agentes que se encargan de la sincronización que

deben correr en cada máquina que participe.

En futuros trabajos, se pueden analizar los beneficios de implementar con DJCutter

(u otra herramienta de características similares) los patrones revisados en el presente tra-

bajo, para determinar si dicha implementación realmente provee ventajas sobre una im-

plementación de propósito general.

Page 136: Aplicación de programación orientada a aspectos a patrones de ...
Page 137: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Referencias 127

Referencias

[Ajdt 06] www.eclipse.org/ajdt (2006)

[Aks 92] Mehmet Aksit Lodewijk Bergmans and Sinan Vural (1992) An Object-

Oriented Language-Database Integration Model: The Composition-Filters

Approach, in Proceedings of ECOOP ‟92, Springer-Verlag

[Ale 02] Roger Alexander and James Bieman (2002) Challenges of Aspect-oriented

Technology, Proc. Internacional Conference of Software Engineering 2002

Workshop on Software Quality, Orlando, Florida, USA

[Alt 04] Rubén Altman, Alan Cyment (2004) SetPoint: Un enfoque semántico para la

resolución de pointcuts en AOP, Tésis de Licenciatura, Facultad de Ciencias

Exactas, UBA

[Asj 06] www.eclipse.org/aspectj (2006)

[AWerkz 05] http://aspectwerkz.codehaus.org (Noviembre 2005)

[Ber 01] Lodewijk Bergmans and Mehmet Aksit (2001) Composing Crosscutting Con-

cerns Using Composition Filters, Communications of the ACM, Oct.

2001/Vol. 44 No. 10, pp. 51-57, ACM Press

[Ber 94] Lodewijk Bergmans (1994) The Composition-Filters Object Model, Technical

report, Department of Computer Science, University of Twente, Netherlands

[Bur 03] Burke Bill, Brock Adrian (2003) Aspect-Oriented Programming and JBoss -

www.onjava.com/pub/a/onjava/2003/05/28/aop_jboss.html

[Cli 96] Marshall P. Cline (1996) The Pros and Cons of Adopting and Applying Design

Patterns in the Real World, Communications of the ACM, Oct. 1996/Vol. 39

No. 10, pp. 47-49, ACM Press

[Coh 04] Tal Cohen and Joseph (Yossi) Gil (2004) AspectJ2EE = AOP + J2EE, in the

8th European Conference on Object-Oriented Programming (ECOOP 2004).

[Dou 02] Bruce Powel Douglass (2002) Real-Time Design Patterns: Robust Scalable

Architecture for Real-Time Systems, Addison-Wesley

[Fow 04] Fowler M. (2004) Inversion of Control Containers and the Dependency Injec-

tion pattern, www.martinfowler.com/articles/injection.html

[Gam 93] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1993) De-

sign Patterns: Abstraction and Reuse of Object-Oriented Design, in Proceed-

ings of the 7th European Conference on Object-Oriented Programming

(ECOOP 2003), pp. 406-431, Kaiserslautern, Alemania.

[Gam 95] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1995) De-

sign Patterns: Elements of reusable Object-Oriented Software, Addison-

Wesley

[Gef 06] www.eclipse.org/gef/ (2006)

[Gil 05] Joseph Gil, Itay Maman (2005) Micro Patterns in Java Code, in Proceedings

of the 20th annual ACM SIGPLAN conference on Object oriented program-

ming, systems, languages, and applications, San Diego, CA, USA, pp 97 –

116, ACM Press

[Han 02] Hannemann J., -Kiczales G. (2002) Design Pattern Implementation in Java

and AspectJ, Proceedings of the 17th ACM SIGPLAN conference on Object-

Page 138: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

128 Referencias Diego M.S. Erdödy

oriented programming, systems, languages, and applications, pp. 161-173,

ACM Press

[Hur 95] Walter L. Hürsch and Cristina Videira Lopes (1995) Separation of Con-

cerns, Technical report by the College of Computer Science, Northeastern

University, Boston MA

[JBA 06] labs.jboss.com/portal/jbossaop (2006)

[JBS 06] jboss.com (2006)

[JHD 06] www.jhotdraw.org (2006)

[Jim 98] Ricardo Jiménez-Peris, Marta Patiño-Martínez y Sergio Arévalo (2002) Multithreaded Rendezvous: A Design Pattern for Distributed Rendezvous,

Universidad Politécnica de Madrid, Facultad de Informática, España

[Joh 97] Ralph E. Jonson (1997) Components, Frameworks, Patterns, Proceedings of

the 1997 Symposium on Software reusability, Boston, Massachusetts, United

Status, pp 10-17, ACM Press

[JSR 163] jcp.org/en/jsr/detail?id=163 (2006)

[Ker 05] Mik Kersten (2005), AOP@Work: AOP tools comparison, part 1,

www.ibm.com/developerworks/java/library/j-aopwork1

[Kic 01] Gregor Kiczales et al. (2001) An Overview of AspectJ, Lecture Notes In Com-

puter Science; Vol. 2072, Proceedings of the 15th European Conference on

Object-Oriented Programming, pp 327 – 353, Springer-Verlag

[Kic 91] Gregor Kiczales, Jim Des Rivieres, Daniel G. Bobrow (1991) The Art of the

Metaobject Protocol, MIT Press

[Kic 92] Gregor Kiczales (1992) Towards a New Model of Abstraction in Software En-

gineering, en Proceedings of the IMSA'92 Workshop on Reflection and Meta-

level Architectures

[Kic 97] Gregor Kiczales et al. (1997) Aspect-Oriented Programming, in Proceedings of

the European Conference on Object-Oriented Programming (ECOOP), Fin-

land. Springer-Verlag

[Koj 03] Sergei Kojarski, Karl Lieberherr, David H. Lorenz, Robert Hirschfeld

(2003) Aspectual Reflection, Proceedings of the AOSD 2003 Workshop on

Software-engineering Properties of Languages for Aspect Technologies,

March 17-21, 2003, Boston, Massachusetts

[Kop 04] Christian Koppen and Maximilian Stoerzer (2004) PCDiff: Attacking the

Fragile Pointcut Problem, in European Interactive Workshop on Aspects in

Software, Berlin, Germany, September 2004.

[Kru 92] Charles W. Krueger (1992) Software reuse, ACM Computing Surveys, Junio

1992, pp. 131-183, ACM Press

[Lie 96] Karl Lieberherr (1996) Adaptive Object-Oriented Software The Demeter Me-

thod, PWS Publishing Company

[Mez 03] Mira Mezini, Klaus Ostermann (2003) Conquering aspects with Caesar, Pro-

ceedings of the 2nd international conference on Aspect-oriented software de-

velopment, Boston, Massachusetts, pp. 90-99, ACM Press

[Mug 03] Muga Nishizawa, Shigeru Chiba and Michiaki Tatsubori (2003) Remote

Pointcut - A Language Construct for Distributed AOP, Proceedings of the 3rd

international conference on Aspect-oriented software development, pp. 7-15,

ACM Press

Page 139: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Referencias 129

[OWL 06] www.w3.org/2004/OWL/ (2006)

[Ram 03] Ramnivas Laddad (2003), AspectJ in Action, Manning

[Rus 04] Miles Russell (2004) An Introduction to Aspect-Oriented Programming with

the Spring Framework -

www.onjava.com/pub/a/onjava/2004/07/14/springaop.html

[Sch 00] Douglas C. Schmidt, Michael Stal, Hans Rohnert and Frank Buschmann

(2000) Pattern-Oriented Software Architecture, Patterns for Concurrent and

Networked Objects, Volume 2, Wiley & Sons

[Sch 03] Douglas C. Schmidt, Frank Buschmann (2003) Patterns, frameworks, and

middleware: their synergistic relationships, en Proceedings of the 25th Inter-

national Conference on Software Engineering, Portland, Oregon, pp. 694 –

704, IEEE Computer Society

[Sch 95] Douglas C. Schmidt (1995) Reactor: An Object Behavioral Pattern for Con-

current Event Demultiplexing and Dispatching, Pattern languages of program

design, pp. 529 – 545, ACM Press/Addison-Wesley Publishing Co.

[Ste 02] Dominik Stein, Stefan Hanenberg, and Rainer Unland (2002) Designing As-

pect-Oriented Crosscutting in UML, In AOSD-UML Workshop at AOSD '02,

Enschede, The Netherlands, Apr. 2002

[Sul 01] Gregory T. Sullivan (2001) Aspect-Oriented Programming Using Reflection

and Metaobject Protocols, Communications of the ACM, Oct. 2001/Vol. 44

No. 10, pp. 95-97, ACM Press

[UML 06] www.uml.org (2006)

[XDoc 06] xdoclet.sourceforge.net (2006)

Page 140: Aplicación de programación orientada a aspectos a patrones de ...
Page 141: Aplicación de programación orientada a aspectos a patrones de ...

TESIS DE GRADO EN INGENIERÍA INFORMÁTICA

Diego M.S. Erdödy Glosario 131

Glosario

AJDT: AspectJ Development Tool

AOP: Aspect Oriented Programming (Programación Orientada a Aspectos)

AOSD: Aspect Oriented Software Development (Desarrollo de Software Orientado a

Aspectos)

AWT: Abstract Window Toolkit. Biblioteca gráfica original de Java.

C3: Cross-Cutting Concern (Interés Transversal)

CJR: Core Java Reflection

ACVF: Aspectual Component Visualization Framework

EditPart: Elemento integrante de la capa de controlador perteneciente al modelo MVS

de GEF

GEF: Graphical Editing Framework

GoF: Gang of Four. Acrónimo con el que se reconoce a los cuatro autores de [Gam 95].

GUI: Graphic User Interface (Interface Gráfica de Usuario)

IoC: Inversion of Control (Inversión de Control)

MOP: Meta-Object Protocols (Protocolo de Meta-objetos)

MVC: Patrón de diseño Model-View-Controller

POA: ver AOP

POO: Programación Orientada a Objetos

POP: Procedural Oriented Programming (Programación Orientada a Procedimientos)

SoC: Separation of Concerns (Separación de Intereses)

SWT: Standard Widget Toolkit

UML: Unified Modeling Language (Lenguaje de Modelado Unificado)