Monografia Programacion Orientada a Aspectos

43
Universidad Tecnológica de Panamá Facultad de Ingeniería de Sistemas Computacionales Ambientes de Programación “Programación Orientada a Aspectos” Integrantes: Janice Martínez Steven Martínez Néstor Martínez Abdiel Martínez Profesora: Yadira Martínez

description

Programacion Orientada a Aspectos

Transcript of Monografia Programacion Orientada a Aspectos

Page 1: Monografia Programacion Orientada a Aspectos

Universidad Tecnológica de Panamá

Facultad de Ingeniería de Sistemas Computacionales

Ambientes de Programación

“Programación Orientada a Aspectos”

Integrantes:

Janice MartínezSteven MartínezNéstor MartínezAbdiel Martínez

Profesora: Yadira Martínez

Martes 18 de Agosto de 2009.

Page 2: Monografia Programacion Orientada a Aspectos

Introducción...........................................................................................................3Separación de Asuntos (Separation of Concerns)................................................4Programación Orientada a Aspectos.....................................................................7Lenguajes Programación Orientado a Aspectos.................................................11AspectJ................................................................................................................11

AspectJ Puntos de Unión.................................................................................13Aplicación de AspectJ.........................................................................................14

Estudiar la Solución Convencional primero..................................................142 Limitar la implementación..........................................................................153 Generalizar la Solución.............................................................................15

AspectJ y las Fases de Desarrollo......................................................................15Diseño..........................................................................................................15Implementación............................................................................................16Fase de Pruebas..........................................................................................18

Ejemplo de AspectJ.............................................................................................18Requerimientos................................................................................................18

Implementación Java...................................................................................19Implementación en C#.................................................................................21Implementacion C# con registro de sucesos en consola.............................22Implementación usando AspectJ.................................................................24

Implementación de Aspecto en .Net C#..............................................................26Ejemplo de Rastreo (Tracing) de Alto Nivel por Aspecto..............................26Implementación de XTraceMethodBoundaryAttribute..................................27Inicialización en Tiempo de Compilación.....................................................27Métodos en Tiempo de Ejecución................................................................29

Conclusión...........................................................................................................30Referencias.........................................................................................................31

2

Page 3: Monografia Programacion Orientada a Aspectos

IntroducciónLa industria de desarrollo de software ha evolucionado grandemente en los últimos

años. Algunas veces como desarrollador es difícil mantenerse al día con las nuevas

tecnologías o procesos que cada día se incorporan. Sin embargo a pesar de todos los

avances que se están dando existen problemas para los cuales todavía no se tiene una

solución ideal. Uno de estos problemas es la correcta modularización, en especial,

cuando se lidia con un sistema complejo y grande. La adopción de OOP (siglas en

ingles) ha ayudado grandemente a que se avance para subsanar este dilema; sin

embargo, no es suficiente. La programación orientada a aspectos va un paso más allá y

aunque lejos de ser una solución ideal, subsana algunos deficiencias del modelado que

se logra por medio de OOP .

3

Page 4: Monografia Programacion Orientada a Aspectos

Separación de Asuntos (Separation of Concerns)El principio de Separación de Asuntos fue propuesto en la década de 1970 por Edsger

W. Dijkstra en su ensayo: “Rol del pensamiento Científico”. En este ensayo Esdger

establecía que un problema dado debe ser separado en varios aspectos o asuntos.

Quince años después es evidente que el concepto de separación de asuntos es

grandemente adoptado por los profesionales de la computación. Como prueba de esto

podemos citar el libro publicado por Chris Reade “Elementos de Programación

Funcional”. En el cuales se describe la separación de asuntos de manera mas

detallada. Reade declara que el programador debe ser capaz de hacer varias funciones

a la vez:

- Describir lo que se va a computar

- Organizar la secuencia de computación en pequeños pasos

- Organizar la administración de la memoria durante la computación.

Como ya lo estableció Esdger en su ensayo, el proceso de separar un problema en la

suma de sus partes no es algo nuevo. El mismo se aplica en áreas diferentes a la

programación o en otras ingenierías. Como la construcción de objetos más tangibles,

por ejemplo podemos citar la construcción de un helicóptero

4

Page 5: Monografia Programacion Orientada a Aspectos

Podemos definir asuntos como los diferentes temas o asuntos de los que es necesario

ocuparse para resolver el problema. Una de ellos es la función específica que debe

realizar una aplicación, pero también surgen otros como por ejemplo distribución,

persistencia, replicación, sincronización, etc. Usualmente asuntos son equivalentes con

características o comportamientos del programa.

La Separación de Asuntos es la base que promovió el desarrollo de los lenguajes

orientados a objetos, en donde dado un buen diseño es posible alcanzar mayores

niveles de reutilización, independencia. Con miras a conseguir una mayor productividad,

también se han creado patrones de desarrollo que ayudan a alcanzar una mejor

separación de asuntos. Podemos mencionar Modelo – Vista- Controlador(Model View

Controller).

Las técnicas de modelado utilizadas actualmente en la etapa de diseño de un sistema

se basan en partirlo en varios subsistemas que resuelvan parte del problema o

correspondan a una parte del dominio sobre el que trata. Estas técnicas sufren en su

mayoría la llamada "tiranía de la descomposición dominante" que consiste en

guiarse al modelar, implícita o explícitamente, por una visión jerárquica determinada de

la organización del sistema.

El problema de estas técnicas es que no contemplan el hecho que hay puntos de

funcionalidades (usualmente la funcionalidades no principales del sistema) que se van a

repetir dentro de la jerarquía en secciones que no tienen relación entre sí. De tal

manera que estos puntos no se adaptan al principio básico de la separación de asuntos.

Actualmente la solución es repetir el código, lo que introduce una serie de problemas

5

Page 6: Monografia Programacion Orientada a Aspectos

como incremento en el costo de mantener el software, decremento en la reusabilidad,

entre otros.

Estas responsabilidades, que aparecen diseminadas en el código atravesando partes

del sistema no relacionadas en el modelo, se denominan asuntos transversales. Las

técnicas de modelado convencional no separan bien los asuntos transversales (cross-

cutting concern). Incluso los lenguajes orientados a objetos, a pesar de las muchas

ventajas que nos presentan sufren de esta desventaja en particular.

Los asuntos transversales dan lugar a código disperso y enredado (scattering and

tangling). En el caso de scattering en lugar que un componente se enfoque en

desarrollar un solo asunto, el componente desarrolla varios asuntos. Cómo

desarrollador debemos conocer sobre todos los asuntos que se están desarrollando en

el componente. Incrementando la curva de aprendizaje del código de la aplicación.

Los asuntos transversales se pueden clasificar en: Compañeros (Peers). Estos son

asuntos que se distinguen claramente uno de otros. Los mismos tienen el mismo nivel

de importancia. En el ejemplo familiar del ATM, retiro de efectivo, depósito,

transferencia de fondos todos son asuntos transversales compañeros (Peers).1 Estos

asuntos se pueden desarrollar como sistemas independientes, sin embargo al

desarrollarse dentro del mismo sistema nos encontramos con el hecho de que existe

sobreposición en la codificación de los mismos.

La otra categoría de asuntos transversales se denomina extensiones. Las extensiones

son componentes que se construyen sobre una base. Usualmente representan servicios

o características adicionales. Mantener las extensiones separadas nos permite que un

problema complejo sea entendible. El problema con las extensiones radica en que se

necesita incluir un llamado de las mismas en el componente base. Al hacer esto se ha

hecho un cambio intrusivo en el código base. Es decir el componente base estaba

completo antes de que decidiera añadir una nueva característica por medio de las

extensiones. El código con el cual se une un componente base a una extensión se

1 (Jacobson, et al., 2004)

6

Page 7: Monografia Programacion Orientada a Aspectos

denomina código de unión (glue code). No importa que tan bueno sea el diseño, con las

técnicas de modelado convencionales, el código de unión es necesario.

Un ejemplo clásico de asuntos transversales es el “logging” o registro de sucesos en

una aplicación. El registro de sucesos no es parte de la funcionalidad principal de la

aplicación y el mismo está diseminado prácticamente en todos los módulos de una

aplicación. En la Figura 2 es una representación gráfica de los distintos componentes

de una aplicación. Las secciones en rojo representan los llamados que se hacen al

código que graba los sucesos; los rectángulos representan los diferentes módulos de la

aplicación. Como se puede apreciar en la figura el código de registro de sucesos está

diseminado por diferentes componentes.

Programación Orientada a AspectosLas técnicas convencionales de modelado son un gran herramienta para estructurar un

sistema complejo de manera jerárquica; sin embargo, como ya hemos establecidos

presentan limitaciones.

Para superar estas limitaciones es necesaria una nueva metodología modular que nos

permita: alcanzar verdadera separación de los asuntos, incluyendo los asuntos

transversales, en todas las fases de desarrollo de software (requerimientos, análisis,

7

Page 8: Monografia Programacion Orientada a Aspectos

diseño, codificación y pruebas). Está nueva metodología también debe permitir la

composición de asuntos de manera coherente e integral.

Programación orientada a aspectos es una de las respuestas al problema de los

asuntos transversales. La programación orientada a aspectos son una serie de

tecnologías que tratan de proveer una mejor solución a la separación de asuntos

transversales. La solución que la AOP (Aspect Oriented Programming) presenta es la

modularización de los asuntos transversales. La modularización de los asuntos

transversales se denomina aspectos.

Debido a la escasa literatura en español sobre el tema, se presenta la terminología

original en inglés.

Aspect (Aspecto) es una funcionalidad transversal (cross-cutting) que se va a

implementar de forma modular y separada del resto del sistema. El ejemplo más

común y simple de un aspecto es el logging (registro de sucesos) dentro del

sistema, ya que necesariamente afecta a todas las partes del sistema que

generan un suceso.

Join point (Punto de Cruce o de Unión) es un punto de ejecución dentro del

sistema donde un aspecto puede ser conectado, como una llamada a un

método, el lanzamiento de una excepción o la modificación de un campo. El

código del aspecto será insertado en el flujo de ejecución de la aplicación para

añadir su funcionalidad.

Advice (Consejo) es la implementación del aspecto, es decir, contiene el código

que implementa la nueva funcionalidad. Se insertan en la aplicación en los

Puntos de Cruce.

8

Page 9: Monografia Programacion Orientada a Aspectos

Pointcut (Puntos de Corte) define los Consejos que se aplicarán a cada Punto

de Cruce. Se especifica mediante Expresiones Regulares o mediante patrones

de nombres (de clases, métodos o campos), e incluso dinámicamente en tiempo

de ejecución según el valor de ciertos parámetros. Un ejemplo sencillo se puede

aplicar a clases que representen figuras geométricas. En

Introduction (Introducción) permite añadir métodos o atributos a clases ya

existentes. Un ejemplo en el que resultaría útil es la creación de un Consejo de

Auditoría que mantenga la fecha de la última modificación de un objeto,

mediante una variable y un método setUltimaModificacion(fecha), que podrían

ser introducidos en todas las clases (o sólo en algunas) para proporcionarlas

esta nueva funcionalidad.

Target (Destinatario) es la clase aconsejada, la clase que es objeto de un

consejo. Sin AOP, esta clase debería contener su lógica, además de la lógica

del aspecto.

Proxy (Resultante) es el objeto creado después de aplicar el Consejo al Objeto

Destinatario. El resto de la aplicación únicamente tendrá que soportar al Objeto

Destinatario (pre-AOP) y no al Objeto Resultante (post-AOP).

Weaving (Tejido) es el proceso de aplicar Aspectos a los Objetos Destinatarios

para crear los nuevos Objetos Resultantes en los especificados Puntos de

Cruce. Este proceso puede ocurrir a lo largo del ciclo de vida del Objeto

Destinatario:

o Aspectos en Tiempo de Compilación, que necesita un compilador

especial.

o Aspectos en Tiempo de Carga, los Aspectos se implementan cuando el

Objeto Destinatario es cargado. Requiere un ClassLoader especial.

9

Page 10: Monografia Programacion Orientada a Aspectos

o Aspectos en Tiempo de Ejecución.2

2(Wikimedia Foundation, 2009)

10

Page 11: Monografia Programacion Orientada a Aspectos

Lenguajes Programación Orientado a Aspectos Como toda investigación lleva a una aplicación práctica la programación orientada a

aspectos no es la excepción. Existen varios lenguajes de programación que han

implementado, algunos más exitosos que otros, técnicas para poder aplicar los

aspectos. Algunos de estos programas son específicos a un dominio y no se pueden

usar como lenguajes multi-propósitos. Otros han sido iniciativas de universidades y al

carecer del respaldo económico no han tenido la adopción esperada, quedando en las

fases experimentales. Cómo un ejemplo de este último caso se puede mencionar a

Aspect.Net.

Aspect.Net es una implementación de programación orientada a aspectos para el

Framework .Net promovido por Vladimir O. Safonov de la Universidad de San

Petesburgo. Aspect.Net está conformado por dos herramientas:

Editor de Aspectos: permite añadir nuevos aspectos, explorar y seleccionar o no los

posibles puntos de unión.

Tejedor (Weaver): estadísticamente aplica el consejo (advice) a los puntos de unión que

se establece basado en las reglas descritas en el aspecto.

La implementación de Aspect.Net no utiliza reflexión (conjunto de clases que puede

inferir información sobre las mismas clases, métodos, etc.; incluyendo llamados

dinámicos), ya que los autores consideraron que el uso de reflexión no era suficiente

para la integración de los aspectos. Hay que resaltar que la iniciativa de Aspect.Net se

inicio en el 2005 y el Framework de .Net ha avanzado desde esa fecha. Sin embargo el

proyecto actual de Aspect.Net sólo es compatible con el Visual Estudio 2005 y el mismo

no es fácil de conseguir, a pesar de ser gratis. El autor todavía considera que está en

una fase experimental.

AspectJ

Es una extensión multi-propósito de Java que implementa la programación orientada a

aspectos. Está formada por una serie de herramientas que permiten a los

desarrolladores de Java administrar mejor los problemas inherentes de los sistemas

11

Page 12: Monografia Programacion Orientada a Aspectos

grandes y en general aplicar mejor la modularidad dentro de los mismos, en especial

aplicar correctamente la separación de los asuntos transversales. Originalmente fue

desarrollado por profesionales del Centro de Investigación de Palo Alto de Xerox, ahora

es parte del proyecto Eclipse.

Es un lenguaje práctico que provee, en un paquete compatible con Java, un set sólido

de características de Programación Orientada a Aspectos. No está diseñado para ser

una encarnación en blanco de las ideas de Programación Orientada a Aspectos, no es

una implementación formal ni un estudio agresivo del dominio y las oportunidades de la

POA.

AspectJ es una extensión compatible de Java que permite el manejo de asuntos

transversales (crosscutting concerns). Se entiende por compatibilidad los siguientes 4

puntos.

- Compatibilidad ascendente: todos los programas de Java legales deben ser

programas legales de AspectJ.

- Compatibilidad de plataforma: todos los programas legales de AspectJ deben

correr en máquinas virtuales estándares de Java.

- Compatibilidad de herramienta: debe ser posible extender herramientas actuales

para que soporten AspectJ; esto incluye IDEs, herramientas de documentación,

herramientas de diseño, etc.

- Compatibilidad de Programación: programar en AspectJ debe de ser como una

extensión natural de programar con Java.

AspectJ soporta dos implementaciones para los asuntos transversales. La primera se

denomina asuntos transversales dinámicos (dynamic crosscutting); por medio de este

mecanismo es posible definir implementaciones adiciones que sean ejecutadas en

puntos bien definidos de una aplicación. La otra implementación se llama asuntos

12

Page 13: Monografia Programacion Orientada a Aspectos

transversales estáticos (static crosscutting). En ella se definen nuevas operaciones en

tipos existentes.

AspectJ Puntos de UniónLos puntos de unión (Joint points) son un elemento crítico en el diseño de cualquier

mecanismo de un lenguaje orientado a aspectos. AspectJ no es la excepción. Este

modelo provee un marco de referencia que hace posible la ejecución coordinada de

código de aspectos junto con código que no hace referencia a los aspectos. La

implementación de los asuntos transversales dinámicos se logra mediante los puntos de

unión.

Los diferentes tipos de puntos de unión que AspecJ tiene se presentan en la siguiente

tabla:

Tabla 2.1 Dummy

Tipo de Punto de Unión Momento de ejecución en el Programa en

el cual…

- Llamada de un método

- Llamade de un constructor

El método (o el constructor de la clase) es

llamado. Los puntos de unión son el objeto

que hace el llamado. Si el método es

estático entonces es en ningún objeto.

- Recepción de la llamada de un

método

- Recepción del llamado de un

constructor

Un objeto recibe el llamado de un método

o un constructor. Puntos de unión de

recepción se dan antes que el método o

constructor se haya despachado. Ejemplo;

ellos ocurren dentro del objeto llamado, en

un punto del flujo de control después que

el control ha sido transferido al objeto que

hace el llamado, pero antes que cualquier

13

Page 14: Monografia Programacion Orientada a Aspectos

método/constructor haya sido llamado.

- Ejecución de un método

- Ejecución de un constructor

Un método individual o constructor es

invocado.

- Lectura de una propiedad Una propiedad de un objeto, clase o

interfase es leída.

- Escritura de una propiedad Una propiedad de un objeto, clase o

interfase es escrita.

- Ejecución de un manejo de

excepción

El manejo de excepción es invocado.

- Inicialización de una clase Inicializadores estáticos de una clase, si

existes, son ejecutados.

- Inicialización de un objeto Cuando los inicializadotes dinámicos de

una clase, si están presentes, son

ejecutados durante la creación de un

objeto

Aplicación de AspectJEstudiar la Solución Convencional primero —En este paso, se diagrama,

diseña, e incluso se crea un prototipo de la solución convencional. La solución

convencional resalta las ventajas de la solución que provee AspectJ, el propósito

principal es ayudar a entender el diseño necesario para una mejor solución con

AspectJ. La idea es identificar el código disperso y enredado (scattering and tangling) y

14

Page 15: Monografia Programacion Orientada a Aspectos

luego modularizarlo. Una vez se logra suficiente experiencia en este paso, se puede

reducir la importancia del mismo o incluso eliminarlo..

2 Limitar la implementación—Al limitar la solución a solo módulos que

actualmente necesitan la funcionalidad, se elimina el impacto, tanto positivo como

negativo, en otros módulos. El objetivo es dejar la mayor cantidad del sistema sin

afectar como sea posible y reducir el esfuerzo necesario en las pruebas. Para hacer

esto, se pueden usar puntos de corte como within() para especificar sólo puntos de

unión en los módulos donde se quiera hacer aplicar los aspectos. Como alternativa se

puede configurar el sistema para que sólo utilice eso módulos.

3 Generalizar la Solución—Una vez se haya probado ampliamente la solución y

estudiado su impacto, se debe modificar los puntos de corte o cambiar la configuración

que ha estado limitando el área de aplicación de la solución. Por ejemplo, en lugar de

restringir el registro de sucesos a ciertos módulos, se remueven las restricciones para

que la solución se aplique en todo el sistema. De esta manera nuevos módulos se

beneficiarán de esta solución de manera inmediata apenas ingresen al sistema, sin

necesidad de esfuerzo adicional. La única manera en que el paso tres se puede concluir

exitosamente es mediante la aplicación asertiva de los pasos 1 y 2. Tanto el diseño

como una prueba contenida de la solución son las bases para la implementación exitosa

de aspectos a una aplicación existente. 3

AspectJ y las Fases de DesarrolloCada fase de desarrollo (diseño, implementación, pruebas, manutención), registra una

serie de actividades de tal manera que la aplicación práctica en el uso de AspectJ varía

en cada una.

DiseñoAl igual que cualquier proceso de desarrollo de software un buen diseño es la piedra

angular para que el proyecto se desarrolle de manera exitosa; diseñar software usando

AspectJ no es la excepción a la regla. Al considerar el uso de AspectJ desde las etapas

iníciales del diseño se obtiene los mayores beneficios de la utilización del mismo, ya

3 (Laddad, 2003)

15

Page 16: Monografia Programacion Orientada a Aspectos

que se garantiza que los asuntos transversales son manejados correctamente e

integrados efectivamente por medio de los aspectos.

La manera típica de utilizar AspectJ en la fase de diseño incluye:

- Reconocer los asuntos transversales. Este paso es parte del mapeo necesario

de requerimientos a módulos. Una manera sencilla de identificar estos asuntos

es la utilización de frases como: “cada vez”, “en todo lugar”. Si nos encontramos

utilizando estas frases para describir parte de las funcionalidades en distintos

módulos, tenemos ante nosotros un asunto transversal. Reconocer los asuntos

transversales a tiempo, permite que estos sean delegados a aspectos que se

integran fácilmente a los módulos existentes.

- Diseñar los asuntos principales primero. Se debe aplicar técnicas estándares

para diseñar los asuntos principales. Entre mejor se realice esta labor, será más

fácil aplicar los asuntos transversales. Se recomienda la utilización de interfaces

con roles claros.

- Diseñar los asuntos transversales. Implementar los asuntos transversales

primordiales. Es una buena idea también hacer un bosquejo de los asuntos

transversales que se hayan reconocido, pero no se necesiten inmediatamente.

De tal forma que no se trabaje de manera repetida en el diseño al considerarse

las posibles mejoras al mismo.

Como se puede observar diseñar para Programación orientada a aspectos no es muy

diferente que el diseño convencional. La utilización de AspectJ nos fuerza a entender

claramente el diseño de la aplicación y a acogernos a los estándares definidos para

lograr un diseño de calidad. Una vez se logre esto, la aplicación de aspectos que se

encarguen de integrar los asuntos transversales se hará de manera efectiva y sin costos

adicionales.

ImplementaciónEn general el proceso de implementar un sistema utilizando AspectJ no es muy

diferente que cuando se utiliza un lenguaje de orientación a objetos. Hay algunas

consideraciones básicas en las cuales se debe hacer más énfasis como:

-Separar en módulos correctamente el código: idealmente cada operación debe

corresponder con una funcionalidad. La unidad granular para definir los puntos de unión

son los métodos. Es importante que cada método tenga una función clara y concisa. De

esta manera el aplicar un aspecto será pan comido.

16

Page 17: Monografia Programacion Orientada a Aspectos

-Uniformidad en la nomenclatura: Esta es una regla que se debe aplicar

independientemente si se está trabajando con AspectJ o no. Toma incluso más

relevancia cuando se utiliza AspectJ. Una de las ventajas de AspectJ es que se pueden

definir puntos de unión mediante el uso de comodines. Si somos consistentes con la

nomenclatura podremos aplicar eficientemente los puntos de unión.

Algunas otras consideraciones incluyen:

- Separar los asuntos principales de los asuntos transversales (Igual que en la

fase de diseño)

- Buscar activamente secciones de código que se presenten repetidas (scattering)

o enredadas (tangling).

- Identificar los puntos de unión. Una vez se ha determinado la existencia de un

asunto transversal, se tiene que identificar ya de una manera tangible los puntos

en código que requieren la aplicación del asunto transversal. De igual forma se

debe determinar cuál es la mejor manera de expresar el punto de corte que

contenga todos los puntos de unión identificados previamente.

- Elegir la tecnología correcta para implementar el asunto transversal. (API de

reglas, o el motor de reglas, etc). Esto dependerá de la arquitectura general del

sistema.

- Diseñar los aspectos. Se puede considerar utilizar patrones como plantillas para

diseñar los aspectos. También es necesario aplicar una nomenclatura

consistente a los aspectos en sí. Esto facilitará la aplicación e puntos de unión

dentro de los aspectos si así se requiera. Es válido también determinar si los

mismos aspectos se pueden reutilizar en otros sistemas que presenten los

asuntos transversales que se quieren resolver.

En general al igual que en diseño la implementación de los aspectos no es

estructuralmente diferente pues se basa en conceptos existentes aplicables a la

orientación a objetos. El aspecto adicional sería la creación del aspecto en sí. Se hace

mayor énfasis en mantener una nomenclatura uniforme e identificar todos los puntos de

unión mediante la definición de los puntos de corte.

Fase de PruebasAspectJ provee una serie de escenarios que ayudan a automatizar el proceso de

pruebas de la aplicación. Debido a la naturaleza no intrusiva de los aspectos se puede:

17

Page 18: Monografia Programacion Orientada a Aspectos

Crear casos de usos: Por medio del uso de aspectos privilegiados se puede acceder a

los elementos privados de una clase. Esto permite que se creen programas de prueba

sin que se modifiquen la clase original que se quiere probar. Una vez se haya

garantizado que las pruebas dan los resultados esperados, los aspectos se pueden

sacar del sistema fácilmente.

Pruebas de desempeño: Para tal fin se pueden crear aspectos que ayuden a monitorear

el desempeño de la aplicación cuando este en la versión beta.

Reporte de errores: se pueden usar aspectos que brinden información adicional acerca

del contexto de los errores. El contexto no sólo incluye el stacktrace sino toda la

información que esté disponible en el punto de unión donde se dio el error. En este

sentido los reportes de errores son superiores a la información estándar que proveen

los compiladores.

Ejemplo de AspectJHaciendo alusión al asunto transversal sobre registros de sucesos. Presentamos el

siguiente ejemplo. Es una pequeña aplicación que tiene como objetivo simular algunos

flujos existentes en un salón de clases.

RequerimientosLos requerimientos del micro sistema son:

- Permitir a los estudiantes registrar clases

- Permitir a los profesores asignar tareas

- Permitir a los profesores fracasar estudiantes

- Listar la lista de tareas asignadas a una clase

- Listar la lista de estudiantes registrados en una clase

- Permitir al estudiantes que se retire de la clase

- Asignar a un profesor con determinada clase

- Registrar los sucesos que ocurran en el sistema

Debido a que este es un ejemplo práctico enfocado en mostrar las diferencias básicas y

ventajas de utilizar AspectJ, la parte gráfica del micro sistema no será desarrollada. El

ejemplo se enfocará en crear las clases necesarias que satisfagan los requerimientos

antes señalados.

El siguiente diagrama de clases muestra el diseño inicial con el cual se pretende cumplir

con todos los requerimientos antes mencionados.

18

Page 19: Monografia Programacion Orientada a Aspectos

Como se puede observar en el diagrama la clase principal del sistema es la clase Class.

A continuación podemos ver la implementación del código en AspectJ y posteriormente

la implementación del código en C#.

Implementación Javapackage com.object.model;

import java.util.ArrayList;import java.util.*;

public class Class {

private ArrayList<Task> ActiveTasks;private ArrayList<Student> RegisteredStudents;

private String _ClassName;

private Professor _Professor;

public Class(){

ActiveTasks = new ArrayList<Task>();RegisteredStudents = new ArrayList<Student>();

}

public void SetClassName(String name){

_ClassName = name;}public String GetClassName(){

return _ClassName;}

public void AddStudent(Student newStudent){

RegisteredStudents.add(newStudent);

19

Page 20: Monografia Programacion Orientada a Aspectos

}

public void RemoveStudent(Student newStudent){

RegisteredStudents.remove(newStudent);}

public void AddTask(String name, Date dueDate){

Task newTask = new Task();newTask.SetName(name);newTask.SetDueDate(dueDate);ActiveTasks.add(newTask);

}

public void RemoveTask(Task taskToRemove){

if(ActiveTasks.contains(taskToRemove)){

ActiveTasks.remove(taskToRemove);}

}

public void ListStudents(){

for(int i = 0; i < RegisteredStudents.size(); i ++){

System.out.println("Student name: " + RegisteredStudents.get(i).GetName() + " " + RegisteredStudents.get(i).

GetLastName() );}

}

public void ListTasks(){

for(int i = 0; i < ActiveTasks.size(); i ++){

System.out.println("Task name: " + ActiveTasks.get(i).GetName() + " Due date: " + ActiveTasks.get(i).

GetDueDate().toString() );}

}

public void SetProfessor(Professor newProfessor){

_Professor = newProfessor;}

public Professor GetProfessor(){

return _Professor;}

}

20

Page 21: Monografia Programacion Orientada a Aspectos

Implementación en C#using System;using System.Collections.Generic;using System.Linq;using System.Text;

namespace ObjectModel{ public class Class { List<Student> RegisteredStudents; List<Task> ActiveTasks; Professor _Professor;

public string ClassName { get; set; }

public Class() { RegisteredStudents = new List<Student>(); ActiveTasks = new List<Task>(); }

public void AddStudent(Student newStudent) { RegisteredStudents.Add(newStudent); }

public void RemoveStudent(Student newStudent) { RegisteredStudents.Remove(newStudent); }

public void AddTask(string name, DateTime dueDate) { Task newTask = new Task(); newTask.Name = name; newTask.DueDate = dueDate; ActiveTasks.Add(newTask); }

public void RemoveTask(Task taskToRemove) { if (ActiveTasks.Contains(taskToRemove)) { ActiveTasks.Remove(taskToRemove); } } public void ListTasks() { foreach (var tempTask in ActiveTasks)

21

Page 22: Monografia Programacion Orientada a Aspectos

{ Console.WriteLine("Taks name: " + tempTask.Name + " due date " + tempTask.DueDate); } } public void ListStudents() { foreach (var tempStudent in RegisteredStudents) { Console.WriteLine("Student name: " + tempStudent.Name + " " + tempStudent.LastName); } }

}}

Las dos implementaciones son muy parecidas y en apariencia cumplen con los

requerimientos señalados. Existen algunas diferencias inherentes al syntaxis propios de

los lenguajes, pero en teoría la implementación es la misma. No obstante, si

observamos cuidadosamente nos podemos percatar que ninguna de las dos

implementaciones cumple con el requerimiento sobre registrar todos los sucesos que se

esten realizando en el sistema. Necesitamos hacer unos ajustes en ambas

implementaciones para satisfacer todos los requerimientos.

Implementacion C# con registro de sucesos en consolausing System;using System.Collections.Generic;using System.Linq;using System.Text;

namespace ObjectModel{ public class Class { List<Student> RegisteredStudents; List<Task> ActiveTasks; Professor _Professor;

public string ClassName { get; set; }

public Class() { Console.WriteLine("CTor init");

22

Page 23: Monografia Programacion Orientada a Aspectos

RegisteredStudents = new List<Student>(); ActiveTasks = new List<Task>(); Console.WriteLine("CTor end"); }

public void AddStudent(Student newStudent) { Console.WriteLine("AddStudent init"); RegisteredStudents.Add(newStudent); Console.WriteLine("AddStudent init"); }

public void RemoveStudent(Student newStudent) { Console.WriteLine("RemoveStudent init"); RegisteredStudents.Remove(newStudent); Console.WriteLine("RemoveStudent end"); }

public void AddTask(string name, DateTime dueDate) { Console.WriteLine("AddTask init"); Task newTask = new Task(); newTask.Name = name; newTask.DueDate = dueDate; ActiveTasks.Add(newTask); Console.WriteLine("AddTask end"); }

public void RemoveTask(Task taskToRemove) { Console.WriteLine("RemoveTask init"); if (ActiveTasks.Contains(taskToRemove)) { ActiveTasks.Remove(taskToRemove); } Console.WriteLine("RemoveTask end"); } public void ListTasks() { Console.WriteLine("ListTasks init"); foreach (var tempTask in ActiveTasks) { Console.WriteLine("Taks name: " + tempTask.Name + " due date " + tempTask.DueDate); } Console.WriteLine("ListTasks end"); }

public void ListStudents() { Console.WriteLine("ListStudents init"); foreach (var tempStudent in RegisteredStudents) { Console.WriteLine("Student name: "

23

Page 24: Monografia Programacion Orientada a Aspectos

+ tempStudent.Name + " " + tempStudent.LastName); } Console.WriteLine("ListStudents end"); }

}}

Como se observa en la nueva implementación, se ha tenido que agregar varías líneas

de código para poder cumplir con el requerimiento sobre registro de sucesos. Han sido

necesario agregar más de diez líneas de código para poder implementarlo. Ahora bien

esto sólo ha sido en una clase. Es decir que todas las clases de la aplicación deberán

ser modificadas con llamados similares. Se puede discutir que es un proceso mecánico,

que solo es copiar y pegar lo que lo hace fácil de implementar. No obstante este no es

el único problema que esta implementación presenta. Supongamos que se decide

cambiar de estrategia y ya no se quiera desplegar los registros de sucesos en consola,

sino que se quieran grabar en un archivo de texto o en una base de datos. Habría que

cambiar todos los llamados en las clases. Este proceso es ineficiente y distrae al

programador de la implementación de las funcionalidades principales.

Implementación usando AspectJpackage com.object.model;import org.aspectj.lang.*;public aspect LoggingAspect {

pointcut traceMethods(): execution(* *.*(..)) && !within(LoggingAspect);

before() : traceMethods() {Signature sig = thisJoinPointStaticPart.getSignature();String sigName = sig.getName();String declaringName = sig.getDeclaringTypeName();System.out.println(declaringName + " " + sigName + " init");

}after() : traceMethods(){

Signature sig = thisJoinPointStaticPart.getSignature();String sigName = sig.getName();String declaringName = sig.getDeclaringTypeName();System.out.println(declaringName + " " + sigName + " end");

}}

Por medio del uso del aspecto LogginAspect podemos incluir registros de sucesos en

todas las clases. Hemos modularizado exitosamente el asunto transversal. Ya que hay

24

Page 25: Monografia Programacion Orientada a Aspectos

un sólo lugar donde se maneja el registros de suceso, sería muy sencillo cambiar el

método consola por log4j o la librería estándar de Java para registrar sucesos

AspectJ también nos presenta una herramienta muy útil con la que se pueden ver los

puntos de unión que cumplen la condición.

Por medio del uso de esta herramienta podemos tener una idea exacta de cuantos puntos de unión se han identificado para cada uno de los puntos de corte.

25

Page 26: Monografia Programacion Orientada a Aspectos

Implementación de Aspecto en .Net C#

Para la implementación de la tecnología de programación orientada aspecto nosotros

encontramos una herramienta llamada PostSharp. Existen otras librerías que permiten

la implementación de esta tecnología en .Net. Esta herramienta nos permite reducir el

número de líneas de código en la mayoría (si no todos) de los lenguajes .Net

implementando aspecto.

PostSharp nos facilita la implementación en nuestro código encapsulando los aspectos

como atributos personalizados, haciendo nuestra vida más fácil y la implementación

más placentera.

Ejemplo de Rastreo (Tracing) de Alto Nivel por AspectoEn este ejemplo se demuestra el rastreo utilizando de Postsharp.

En este ejemplo se podrá hacer rastreo de excepciones, acceso a campos e invocación

de métodos.

También hace rastreo de los valores de los parámetros.

En el ejemplo ilustra cómo utilizarlo en tiempo de inicio de compilación.

Objetivo

Desarrollar los atributos personalizados

XTraceExceptionAttribute: escribe un mensaje cuando el método a la cual se aplica

falla con una excepción.

XTraceFieldAccessAttribute: escribe un mensaje cada vez que un campo a la cual es

aplicada es accesado, una operación get o set.

XTraceMethodBoundaryAttribute: escribe un mensaje cuando el método a la cual es

aplicada comienza o termina, ya sea exitoso o no.

XTraceMethodInvocationAttribute: escribe un mensaje cuando el mensaje a la cual

es aplicada es invocada (este método puede estar definido en otro assembly).

Nosotros queremos hacer rastreo de la forma más detallada posible, por ejemplo,

nosotros queremos escribir los valores de parámetros, valores de variables y más.

También queremos tomar ventaja de la inicialización en tiempo de compilación para

evitar formateando el texto a la hora de ejecutar.

Como los cuatro aspectos son muy similares, sómo vamos a comentar el que se utiliza

de forma más común, XTraceMethodBoundaryAttribute.

26

Page 27: Monografia Programacion Orientada a Aspectos

Implementación de XTraceMethodBoundaryAttributeComo queremos insertar código antes y después del cuerpo del método, vamos a

derivar nuestro atributo personalizado de OnMethodBoundaryAspect e implementamos

los métodos OnEntry, OnSuccess y OnException.

El esqueleto de nuestro atributo personalizado es:

[Serializable]public sealed class XTraceMethodBoundaryAttribute : OnMethodBoundaryAspect{

public override void OnEntry(MethodExecutionEventArgs context) { }

public override void OnSuccess(MethodExecutionEventArgs eventArgs) { }

public override void OnException(MethodExecutionEventArgs eventArgs) { }

}

Inicialización en Tiempo de CompilaciónEscribiendo el nombre con todos sus parámetros y los parámetros de tipo genérico no

es trivial. Requiere una potencia de cálculo que no podemos rechazar si queremos que

nuestro aspecto de trace un rendimiento de ejecución aceptable.

Hay muchas que se conocen en tiempo de compilación: el nombre del tipo y el método,

el número de parámetros genéricos y el número y tipo de parámetros. Así que

escogimos que en tiempo de compilación, se va a crear una plantilla (formatear cadena)

y en tiempo de ejecución, para formatear estas plantillas utilizando parámetros

concretos y parámetros genéricos recibidos.

Por ejemplo, si nosotros tenemos un método:

MyType<T1>::MyMethod<T2>(T2 arg1, int arg2)

la plantilla puede ser:

MyType<{0}>::MyMethod<{1}>({2}, {3})

En tiempo de ejecución, nosotros proveeremos un arreglo con los parámetros.

27

Page 28: Monografia Programacion Orientada a Aspectos

La funcionalidad de preparar plantillas y la implementación esta encapsulado en

las clases Formatter y MethodFormatStrings. Su implementación no es de

interés en nuestra discusión, así que no lo vamos a describir en nuestro ejemplo.

¿Cómo podemos realizar esto con PostSharp?

Primero, definimos las instancias de los campos que contienen las cadenas de

formateo y otras cosas que no queremos computar o calcular en tiempo de

ejecución. Después, implementamos el método CompileTimeInitialize para

configurar estos campos. Durante la post-compilación, PostSharp Laos

serializará el objeto. Eso significa que los campos que son inicializados en

tiempo de compilación para ser utilizados en tiempo de ejecución deben ser

serializables. Como este es el comportamiento predeterminado, no tenemos

que ponerle mucha atención a eso.

Finalmente aquí está el código de inicialización en tiempo de compilación:

string prefix;MethodFormatStrings formatStrings;bool isVoid;

public string Prefix{ get { return this.prefix; } set { this.prefix = value; }} public override void CompileTimeInitialize(MethodBase method){ this.prefix = Formatter.NormalizePrefix(this.prefix); this.formatStrings = Formatter.GetMethodFormatStrings(method); MethodInfo methodInfo = method as MethodInfo; if (methodInfo != null) { this.isVoid = methodInfo.ReturnType == typeof(void); } else { this.isVoid = true; }}

28

Page 29: Monografia Programacion Orientada a Aspectos

Métodos en Tiempo de EjecuciónVamos de vuelta a nuestro esqueleto de nuestra clase

XTraceMethodBoundaryAttribute. Tenemos que implementar los métodos

OnEntry, OnSuccess and OnException. Todo lo que tenemos que hacer es

formatear las plantillas con los parámetros concretos y llamar el método

Trace.TraceInformation.

public override void OnEntry(MethodExecutionEventArgs context){ Trace.TraceInformation( this.prefix + "Entering " + this.formatStrings.Format( context.Instance, context.Method, context.GetArguments())); Trace.Indent();

}

public override void OnSuccess(MethodExecutionEventArgs eventArgs){ Trace.Unindent(); Trace.TraceInformation( this.prefix + "Leaving " + this.formatStrings.Format( eventArgs.Instance, eventArgs.Method, eventArgs.GetArguments()) + (this.isVoid ? "" : Formatter.FormatString(" : {{{0}}}.", eventArgs.ReturnValue)));}

public override void OnException(MethodExecutionEventArgs eventArgs){ Trace.Unindent(); Trace.TraceWarning( this.prefix + "Leaving " + this.formatStrings.Format( eventArgs.Instance, eventArgs.Method, eventArgs.GetArguments() ) + Formatter.FormatString(" with exception {0} : {{{1}}}.", eventArgs.Exception.GetType().Name, eventArgs.Exception.Message));

}

29

Page 30: Monografia Programacion Orientada a Aspectos

Conclusión

Por medio del desarrollo de esta monografía se ha podido apreciar las ventajas que

AspectJ y PostSharp brindan en el desarrollo de un sistema. Descartando el esfuerzo

necesario para aprender sobre la sintaxis requerida para especificar los puntos de

cortes de los diferentes aspectos que se han querido introducir al sistema, el uso

correcto de garantiza un menor tiempo escribiendo código. Si bien es cierto que esta

labor sería un proceso mecánico, por medio de estos marcos de trabajo se puede

eliminar el mismo.

En cuanto al esfuerzo y tiempo necesario para diseñar la aplicación, AspectJ y

PostSharp requieren un poco más de tiempo en elaborar un diseño efectivo. No sólo es

necesario diseñar los componentes o módulos de la manera convencional, sino que

también se deben identificar los asuntos transversales de manera clara y concisa. De

igual forma se debe identificar los puntos de corte y la sentencia necesaria para

aplicarlos correctamente. En este proceso de diseño también se debe hacer énfasis en

las convenciones para nombrar las variables, clases y métodos. Ya que la uniformidad

en la nomenclatura nos facilitará la aplicación de puntos de corte por medio del uso de

comodines. La uniformidad en la nomenclatura debe ser en cualquier caso parte del

diseño convencional.

Para llegar a comprender mejor el abanico de oportunidades que AspectJ y PostSharp

nos presentan a la hora de diseñar y desarrollar un sistema sería necesario adquirir

mayor experiencia práctica con el mismo. Quizás entre las desventajas de desarrollar

con estos marcos de trabajo es que nos fuerzan a pensar en un mejor diseño, conocer

las clases con las que uno trabaja en caso de no ser clases propias y las relaciones

entre ellas. Este proceso no es inmediato y requiere una curva de aprendizaje elevada

si se pretende aprovechar todo el potencial de AspectJ y PostSharp.

30

Page 31: Monografia Programacion Orientada a Aspectos

Referencias

Gael Fraiteur. Bringing AOP to .NET, PostSharp.[En línea]http://www.postsharp.org/

An Overview of AspectJ. Kiczales, Gregor, y otros. 2001. Berlin : Springer Berlin / Heidelberg, 2001. págs. 327-354. 978-3-540-42206-8.

Eisenberg, Andrew. 20009. Aspects Everywhere: Language Extensibility for JDT through Equinox Aspects. [En línea] 23 de marzo de 20009. [Citado el: 21 de junio de 2009.] http://www.eclipsecon.org/2009/sessions?id=648.

González, Abdiel E. Cáceres. 2004. Programación Orientada a Aspectos. Mexico : Centro de Investigación y de Estudios Avanzados Mexico, 2004.

Jacobson, Ivar y Ng, Pan-Wei. 2004. Aspect-Oriented Software Development with Use Cases. s.l. : Addison Wesley Professional, 2004. 0-321-26888-1.

Laddad, Ramnivas. 2003. AspectJ in Action - Practical Aspect-Oriented Programming. New York : Manning, 2003.

Safonov, Vladimir. 2005. Aspect.NET: Aspect-Oriented Programming for Microsoft.NET in Practice. [En línea] 28 de julio de 2005. [Citado el: 17 de junio de 2009.] http://dotnet.sys-con.com/node/113337?page=0,1.

Wikimedia Foundation. 2009. Aspect Oriented Programming, Wikipedia. [En línea] 2 de junio de 2009. [Citado el: 4 de junio de 2009.] http://en.wikipedia.org/wiki/Aspect_oriented_programming.

—. 2009. Separation of Concerns. [En línea] 2 de mayo de 2009. [Citado el: 1 de junio de 2009.] http://en.wikipedia.org/wiki/Separation_of_concerns.

31