APLICACIONES DE ESTE PARADIGMA
-
Manejo de transacciones
Una transaccion en un sistema de gestion de bases de datos (SGBD), es un conjunto de ordenes que se ejecutan formando una unidad de trabajo, es decir, una forma indivisible o atomica.
La estructura de una transacción usualmente viene dada según el modelo de la transacción, estas pueden ser planas (simples) o anidadas.
El Manejo Transaccional es uno de los temas cruciales en cuanto a requerimientos para aplicaciones empresariales. Esta motivación surge debido a que en todo sistema empresarial nos interesa mantener la integridad de nuestra información, con esto en mente es que surge el tema de transacciones.
En la figura podemos observar un método de servicio que ejecuta llamadas a más de un DAO, y a su vez cada DAO modifica el estado de la base de datos al escribir y/o modificar su información.
El objetivo de una transacción es ejecutar todas las líneas de código de nuestro método y guardar finalmente la información en un repositorio, por ejemplo en nuestro caso, una base de datos. Esto se conoce como commit de nuestra transacción.
Si por alguna razón algo fallara en nuestro método de Servicio, se daría marcha atrás a los cambios realizados en la base de datos. Esto se conoce como rollback.
Lo anterior permite que nuestra información, ya sea que se una única base de datos o no, esté íntegra, y no exista posibilidad de datos corruptos por errores o fallas en la ejecución de nuestros métodos.
Spring AOP e Hibernate han implementado el manejo transaccional a partir de la Programación Orientada a Aspectos debido al acceso de datos y funciones transversales
-
Sincronización
La sincronización expuesta aquí se basa en los procesos y nos referimos a ella por el hecho de que esta otorga varias técnicas de coordinación de hilos que se ejecutan en forma simultánea y procesos para poder completar una determinada tarea con el objetivo de que estas se ejecuten en un orden establecido y que no se dé lugar a eventos inesperados.
Mencionamos a continuación en forma general los tipos de sincronización existentes: Barrier, Bloqueo/Semáforo (Lock/Semaphore), Unión de hilos (Thread join), Exclusión Mutua (Mutex), Monitores (Monitors), Sincronización no bloqueante (Non-blocking synchronization), Rendezvous, Contadores de eventos y secuenciadores (Event counters and sequencers).
Con esto nos ahorramos el hecho de colocar en cada método la palabra clave lock, el cual garantiza la ejecución de una sección crítica de código o exclusión mutua también denominada, una sección crítica de código es aquella que no permite ser ejecutada al mismo tiempo, debido a que puede darse el caso de que haya lectura sucia o que al mismo tiempo dos o más hilos de ejecución traten de modificar el valor de una variable, por lo tanto se bloquea dicha sección de código en forma exclusiva en un ambiente concurrente, no permitiendo de esta forma a que otro hilo trate de ejecutar esa sección crítica en un instante dado.
Además al evitar repetir esta palabra clave nos aseguramos de no repetir código por un lado y por otro de separar la funcionalidad básica del aspecto de sincronización.
En la definición del aspecto de sincronización expuesto más arriba, podemos decir que existen dos métodos, el primero llamado OnEntry el cual habilita la entrada a la ejecución del código de sección crítica y se utiliza la clase Monitor que provee un mecanismo para sincronizar el acceso a los objetos y el segundo método llamado OnExit, que se usa para realizar el abandono de la sección crítica de la ejecución del código, por lo tanto se invoca al método Exit de la clase Monitor.
-
Perfiles
Tomaremos como ejemplo la Extensión de UML usando Perdiles:
En la actualidad, UML (Unified Modeling Language) es uno de los lenguajes de modelado más utilizados para el diseño de sistemas. Este lenguaje permite especificar, construir, visualizar y documentar artefactos de un sistema de software de manera sencilla.
Muchas veces UML es demasiado general y no es lo suficientemente expresivo para modelar elementos específicos de un dominio particular. En estas situaciones es necesario, extender UML.
Por esta razón, UML estándar incluyó un mecanismo para extender y adaptar UML a diferentes dominios y plataformas: el “Perfil UML” (“UML Profile”)
Para realizar la extensión UML 2.0 incluyó la definición del paquete “Profile”. Éste paquete incluye los mecanismos para redefinir estereotipos, valores etiquetados y restricciones.
La propuesta de extensión del perfil, no permite modificar al metamodelo existente, sino adaptar al metamodelo existente, agregando constructores propios para un dominio particular.
Los estereotipos son especificados como metaclases, los valores etiquetados como metaatributos y los perfiles como una clase de paquete.
-
Manejo de Memoria
Ya que la principal tarea de la memoria consiste en llevar un registro de las partes de memoria que se estén utilizando y las que no , con el fin de asignar espacio en memoria a los procesos cuando éstos la necesiten y liberándola cuando terminen, así como administrar el intercambio entre la memoria principal y el disco. El uso de este paradigma de programación ahorra el uso de memoria al no guardar multiples veces las mismas funciones y código en diferentes clases, sino que al aprovechar el fundamento de su paradigma, accede a esta información de manera más eficiente a un sólo bloque de código y no necesita tener código de ejecución sino que es ejecutado bajo ciertas reglas.
-
Control de Acceso o Seguridad
Debido al uso eficiente del paradigma dentro del uso de las cuentas y perfiles, también afecta directamente el uso de los controles de acceso y la seguridad. Ya que la aplicación se mantiene generalmente igual para cada usuario, solamente difiere su acceso (o no acceso). Por lo que sería rebundante replicar código para cada sesión o la certificación o no del usuario.
Además, al haber solamente un bloque de código de datos importantes y confidenciales, habrá menos riesgo de encontrar dichos datos. Y es más sencillo controlar el acceso a esos datos si solamente están confinados a un control de acceso y no de manera múltiple.
-
Logging
De manera similar al Control de Acceso, el Logging es una forma menos generalizada, pero cumple con las mismas características.
-
Manejo de Excepciones
A través del enfoque de AOP, es posible interceptar las llamadas a los métodos y determinar cuando estos han generado una excepción para posteriormente aplicar la política de manejo más apropiada. Estas políticas puede ser parte del propio aspecto de gestión de excepciones. Como en el caso del registro de eventos, la implementación de este aspecto buscará reducir su implementación (y aplicación) a un atributo que decore el método cuyas posibles excepciones se quieren gestionar.
Un Apropiado SoporteAl crear un mecanismo de gestión y manejo de excepciones, no deberíamos partir desde cero, ya que existe un montón de excelentes productos y frameworks que nos simplificarían esta tarea. Para este caso, emplearé los Microsoft Libraries, en particular el Exception Handling Application Block; sin embargo el enfoque de AOP y de este framework que he venido presentado permite emplear cualquier otra librería.
ImplementaciónEs importante que si no han leido las primeras partes de esta serie de artículos, aprovechen este momento para hacerlo, sobre todo la parte 1. A partir de este momento mis explicaciones considerarán que el conocimiento y los detalles técnicos explicados en esa parte ya son conocidos.
El primer paso es crear el atributo (Attribute) que decorará las clases/interfaces para capturar su ejecución e inyectar el código de manejo de excepciones. Nuestro atributo se llamará ExceptionHandlingAttribute y extiende de InterceptableAttribute, la clase base en el framework de AOP que sirve para definir atributos de intercepción.
-
Patrones de Diseño
Un patrón de diseño sistemáticamente nombra, motiva y explica un diseño general que aborda un problema de diseño recurrente en sistemas orientados a objetos. Describe el problema, la solución, cuándo aplicar la solución y sus consecuencias. Muchos patrones son transversales. Los patrones pueden afectar a múltiples clases, también pueden ser invasivos y difíciles de (re) usar. AOP localiza el código para un patrón de diseño, hace que los patrones sean más ligeros, más flexibles y más fáciles de (re) utilizar.
-
Monitoreo del Rendimiento
Las aplicaciones modernas suelen ser sistemas complejos, multiproceso y distribuidos que utilizan muchos componentes de terceros. En tales sistemas, es difícil detectar (y mucho menos aislar) las causas de los problemas de rendimiento o confiabilidad, especialmente en la producción. Un buen rendimiento es un requisito importante desde el punto de vista comercial. Para cumplir con este requisito, se requiere perfilar la aplicación durante las fases de desarrollo y monitorear el rendimiento después de desplegar la aplicación. AOP permite definir pointcuts que coincidan con los muchos join points en los que se desea supervisar el rendimiento. Luego, se escriben advices que actualicen las estadísticas de rendimiento, los cuales pueden invocarse automáticamente cada vez que se entra o sale de uno de los join points.
-
Testing
Una gran cantidad de librerías de AOP ofrecen funcionalidades para mocking de datos y la ejecución de pruebas en los joinpoints establecidos. El momento de ejecución de estas pruebas depende del tipo de weaving y de las características que ofrece cada librería para estas funcionalidades.
Ejemplo de testing con pythonlib:
-
Software que emplea programación orientada a aspectos.
WebSphere Application Server (WAS)Es una plataforma de IBM que actúa como un servidor de aplicaciones diseñado para configurar, operar e integrar aplicaciones empresariales. WebSphere se distribuye en distintas ediciones donde cada edición soporta diferentes funcionalidades y usan AspectJ internamente para aislar las funcionalidades asociadas a cada edición.
JBoss Application Server (JBoss AS)Es un servidor de aplicaciones Java EE. Es un software libre y de código abierto, como está basado en java se puede usar en cualquier sistema operativo donde haya una máquina virtual de java. El núcleo de JBoss está integrado con programacion orientada a aspectos donde se usa principalmente para desplegar servicios tales como seguridad y administración de transacciones.
Oracle TopLinkEs un framework para almacenar objetos Java en una base de datos relacional (Object-Relational mapping) o convertir estos objetos en formato XML. TopLink logra altos niveles de persistencia y transparencia usando Spring AOP (Componente del framework Spring usado para aplicar AOP).
The a-kernel ProjectEl objetivo del proyecto a-kernel es determinar si la programación orientada a aspectos se puede utilizar para mejorar la modularidad del sistema operativo y, por lo tanto, reducir la complejidad y la fragilidad asociadas con la implementación del sistema.
FACETEl objetivo del proyecto FACET es investigar el desarrollo de middleware personalizable utilizando métodos de programación orientados a aspectos. Se espera que el uso de aspectos en middleware tendrá los siguientes beneficios:
- Mejor modularización de características utilizando aspectos
- Reducción del código de middleware mediante la activación selectiva de funciones
-
Aplicacion en frameworks.
Spring AOP
-
Weaving
Usa Runtime weaving durante la ejecución usando proxy dinámico JDK o proxy CGLIB
-
Estrucutra interna y aplicación
Para implementar aspectos en los objetos de destino, tendremos que crear proxies de ese objetos tipo poa. Esto se logra usando una de dos maneras:
- Proxy dinámico JDK: la forma preferida para Spring AOP. Siempre que el objeto de destino implemente incluso una interfaz, se utilizará el proxy dinámico JDK
- Proxy CGLIB: si el objeto de destino no implementa una interfaz, se puede usar el proxy CGLIB
-
JoinPoints
No puede aplicarse a clases de tipo final, a métodos estáticos o finales porque no se pueden sobrecargar y resultaría en una runtime exception
-
Simplicidad
Spring AOP es más simple porque no introduce ningún compilador o weaver adicional en nuestro proceso de compilación. Utiliza el weaver en tiempo de ejecución y, por lo tanto, se integra a la perfección con nuestro proceso de construcción habitual. Aunque parece simple, solo funciona con beans administrados por Spring.
Aplicación de AOP en microservicios con Spring
La necesidad de manejar obligaciones transversales en la arquitectura por microservicios es primordial. En el ámbito de Spring, la programación orientada aspectos nos proporciona una solución poderosa para modularizar las preocupaciones transversales e implementarlas en la lógica de negocio sin mezclarlas con el código principal.
Ventajas de usar POA en microservicios
Manejo centralizado de preocupaciones transversales:
Escalabilidad y Rendimiento:
Medidas de seguridad mejoradas:
Flexibilidad en la evolución del servicio:
Manejo optimizado de errores:
Gestión simplificada de transacciones y patrones de comunicación
-
Weaving
Usa 3 tipos diferentes de weaving:
-
Weaving en tiempo de compilación:
Toma como entrada tanto el código fuente de nuestro aspecto como de nuestra aplicación y produce una clase de archivos tejidos como salida.
-
Weaving post-compilación:
Se conoce como weaving binario, se usa hacerle weave a las clases ya existentes y archivos JAR en conjunto con nuestros aspectos.
-
Weaving en tiempo de carga:
Igual que en el weaving binario, con la diferencia que ocurre hasta que la clase sea cargada a la JVM
-
-
Estructura interna y aplicación
Las clases son compiladas directamente con los aspectos
-
JoinPoints
Los tipos de joinpoints que soporta AspectJ son:
-
Llamada a metodos
-
Ejecución de Método
-
Llamada de constructor
-
Ejecución de constructor
-
Ejecución de inicializador estático
-
Inicialización de objeto
-
Asignación de campo
-
Ejecución del hanlder
-
-
Simplicidad
Para usar AspectJ, estamos obligados a presentar el compilador de AspectJ (ajc) y volver a empaquetar todas nuestras bibliotecas (a menos que cambiemos el weaving posterior a la compilación o al tiempo de carga). Esto es más complicado, porque presenta AspectJ Java Tools (que incluye un compilador (ajc), un depurador (ajdb), un generador de documentación (ajdoc), un navegador de estructura de programa (ajbrowser)) que debe integrarse a nuestro IDE o a la herramienta de compilación.
Al definir obligaciones como el registro, validación de usuarios o seguridad en un único lugar, se garantiza un enfoque estandarizado en los microservicios. Garantizando que los cambios que puedan llegar a darse se hereden automáticamente en todos los microservicios.
La escalabilidad y el rendimiento, primordiales en los microservicios, se incrementan con POA. Los aspectos se pueden emplear estratégicamente para manejar desafíos como reintentos, tiempos de espera y rupturas de circuitos en las interacciones de red. Además, equipar los microservicios con código de supervisión del rendimiento a través de POA puede conducir a la identificación y optimización de los cuellos de botella del rendimiento.
Los aspectos de seguridad pueden aplicar de forma coherente políticas como la autenticación y la autorización en los microservicios. Además, la creación de registros de auditoría mediante el registro de operaciones específicas se vuelve más ágil, lo que garantiza que el uso del sistema se supervise y analice continuamente.
El efecto de desacoplamiento de POA significa que los microservicios pueden evolucionar sin el peso del código mezclado (code tangling). Esto conduce a la flexibilidad en la evolución del servicio. Cuando la lógica principal de un servicio no está plagada de código transversal, tareas como la refactorización o la actualización se vuelven notablemente más sencillas.
El manejo de errores se vuelve más ágil con POA. Se puede garantizar que todos los microservicios respondan a los errores en un formato coherente. Los aspectos se pueden utilizar para detectar y administrar excepciones, lo que garantiza que se evite que las excepciones no controladas bloqueen un servicio y se también que sean registradas para su análisis.
En entornos en los que los microservicios se ocupan de bases de datos u otros recursos transaccionales, POA simplifica la gestión de transacciones, garantizando la integridad y la coherencia. Además, POA facilita patrones de comunicación confiables, como el abastecimiento de eventos o la saga en interacciones asincrónicas de microservicios.