Framewors Ligeros y Lógica de Negocio
Introducción
Clásicamente hay dos formas de organizar la lógica de negocio: diseño procedimental u orientado a objetos (OO).
El diseño procedimental organiza el código en funciones y estructuras de datos simples. Las estructuras de datos, generalmente se crean, se inicializan y se pasan como parámetros a las funciones. La relación entre estas funciones y los datos que utilizan suelen asociarse en librerías según el criterio del programador.
Por el contrario, la aproximación orientada a objetos organiza el código en objetos que contienen ambos aspectos, datos y comportamiento. Dichos objetos colaboran, generalmente mediante herencia o composición para resolver la lógica de la aplicación. La relación entre los datos y las funciones que los usan está mantenida en su mayor parte por el propio lenguaje. Generalmente el diseño orientado a objetos es más fácil de entender, mantener, extender y probar.
A pesar de los beneficios del diseño OO, muchas aplicaciones J2EE modernas se han escrito utilizando el estilo procedimental. Uno de los precursores principales de dicho estilo fue la especificación EJB (anterior a 3.0).
Los principales atractivos del estilo procedimental son:
- Implementar nuevas funcionalidades es fácil. Basta añadir código a un script transaccional (Transaction Script, Fowler, P_EAA) o añadir un script transaccional nuevo.
- No hace falta diseñar la aplicación. No se necesita determinar las clases ni sus responsabilidades. La lógica de negocio se distribuye en los spcripts transaccionales (Session Beans en EJB 2.0) y los datos persistentes en simples estructuras de datos (Entity Beans en EJB 2.0).
- Es más asequible para programadores con poca experiencia. Este es el principal motivo por el que las Factorías de Software suelen decantarse principalmente por el estilo procedimental frente al OO.
El sistema funciona bien con lógicas de negocio simples pero a medida que esta se complica, los scripts transaccionales suelen contener miles de lineas de código. Se promueve la duplicación de código, los programadores tenderán a programar para si mismos debido a la dificultad de encontrar los métodos disponibles para cada modelo de datos. Se pierde el principal atractivo de la omisión del diseño. El sistema se hace demasiado dificil de entender, probar y mantener.
Vuelta a OO
En los últimos años podemos hablar de una recuperación del diseño OO fomentado por autores que o bien no compartieron en entusiasmo general de EJB o bien desilusionados por los resultados que EJB proporciona en aplicaciones con una lógica de negocio medianamente complejas.
Considerablemente anterior a la nueva especificación EJB 3.0 aparecieron algunos frameworks que recuperaban el diseño OO mediante objetos que no implementaban ninguna de las interfaces específicas de EJB. Martin Fowler, Rebbecca Parsons y Josh MacKenzie acuñaron el nombre de POJO (Plain Old Java Object) para dar un nombre atractivo al desarrollo de aplicaciones basados en objetos java regulares no vinculados a un contenedor EJB.
Fowler, en su excelente libro Patterns of Enterprise Application Architecture (2002), identifica como Modelo del Dominio (Domain Model) al conjunto de clases, normalmente pequeñas que contienen tanto estado como comportamiento y que constituyen la base de la capa de de negocio (Evans - Domain Driven Design). Los modelos sin comportamiento, similares a los entity beans de EJB 2.0, se identifican en esta linea de desarrollo como el anti-patrón Anemic Domain Model (ADM) en oposición al patrón Rich Domain Model (RDM) donde los servicios delegan gran parte de la lógica de la aplicación a los modelos del Dominio.
En modelos medianamente complejos, el estado de los modelos del dominio se hace persistente mediante un framework ORM (Object/Relational Mapping) de persistencia, como JDO, Hibernate o TopLink. La configuración de los modelos del dominio se realiza forma declarativa mediante un contenedor IoC como Spring o PicoContainer. Por último, los servicios basados en POJOs proveen capacidades similares a un contenedor EJB, como sguridad y transacciones declarativas, mediante el uso de AOP.
Esta arquitectura, conocida como arquitectura de contenedor ligero (Lightweight Container Architecture) fué analizada en detalle por Rod Johnson (autor del framework Spring) en su best-seller J2EE Design and Development (Wrox, 2002) y posteriormente contrastada seriamente con la especificación EJB en J2EE Development without EJB (Wrox, 2004).
Frameworks Ligeros. (Lightweight Containers)
La capa de presentación la proporciona un Framework MVC (Modelo – Vista – Controlador) que puede ser dedicado (Struts o Webwork) bien provisto por el propio contenedor IoC (Spring).
La capa de negocio la forman Servicios que son implementados por objetos de negocio mediante POJOS sobre los que se utilizan técnicas de Programación Orientada a Aspectos (AOP, Aspect Object Programing) para proveer la funcionalidad de contenedores clásicos EJB como, por ejemplo, transacionalidad declarativa. Estos servicios, delegan gran parte de la lógica del negocio en los modelos del dominio, que se intercambian entre todas las capas.
La capa de integración se realiza mediante persistencia transparente utlizando un framework de O/R Mapping como Hibernate.
Todas las capas se ejecutan en una única Maquina Virtual. El Contenedor IoC es es responsable de del emsamblaje de los objetos mediante inyección de las dependicias al inicio de de la aplicación.
Es evidente que al compartir todas las capas los modelos del dominio y estos contener comportamiento (en oposición a intercambiar DTOs o XML) existe un acoplación entre capas y estas son difícilmente distribuibles en máquinas virtuales separadas. Es el precio que hay que pagar por recuperar el diseño orientado a objetos.
Sin embargo la distribución transparente proporcionada por EJB es engorrosa, cara y en muchos casos inútil. Ud. no compraría un autobús en lugar de un automóvil por si alguna vez se da el caso de que tiene que llevar a veinte amigos. Del mismo modo no debería programar aplicaciones distribuidas cuando realmente no las necesita. En la mayoría de los casos es más efectivo escalar las aplicaciones mediante hardware, utilizando clusters, por ejemplo. Si realmente necesita distribuir algunos servicios esto puede hacerse mediante servicios web, no de forma generalizada para toda la aplicación.
Ventajas principales de la arquitectura de Framework ligero.
- Es simple y versátil
- Escalable horizontalmente mediante el uso de clusters en los contenedores web aunque limitada por las sesiones y el servidor de base de datos
- Reutilización de código: Los contenedores ligeros manejan POJOs que son independientes del contenedor. Es posible reutilizar los modelos del dominio en cualquier otro entorno.
- Servicios declarativos mediante contenedores ligeros con soporte de AOP. Por ejemplo, la configuración de transacciones mediante Spring es más configurable que la proporcionada por EJB CMT
- Orientación a Objetos: Puesto que no hay limitaciones (o muy pocas, como podría ser la especificación java beans) impuestas en los POJOs, la lógica de negocio de la aplicación puede resolverse utilizando técnicas de diseño OO. Esta ventaja se hace más importante según la lógica de negocio se hace más compleja.
- Es posible escribir test Unitarios de forma independiente para cada modelo del dominio ya que no es necesario desplegarlos en el contenedor. El desarrollo dirigido por test (Test Driven Development) resulta natural en este entorno. El respaldo de los test unitarios permite que el código pueda refactorizarse con seguridad según evoluciona la aplicación.
Estilo procedimental | OO, Domain Model | |
Implementación | EJB | POJOs |
Transacciones Declarativas | CMT | Spring, AOP |
Emsamblaje de la aplicación | JNDI | Inyección de Dependencias, Spring |
Conclusiones
La especificación EJB prometía simplificar el desarrollo de aplicaciones, sin embargo aunque elimina alguna complejidad, introduce serios problemas específicos de la arquitectura EJB como la distribución transparente (DTOs) o la separación del comportamiento y del estado persistente (Entity Beans). Una buena parte de los patrones de diseño que se utilizan en una aplicación EJB clásica no son más que paliativos de las desventajas introducidas por la propia especificación.
La reciente especificación EJB 3.0 no ha hecho oídos sordos al movimiento en pro de los frameworks ligeros liderados principalmente por Spring como contendor IoC e Hibernate como ORM. El hecho de que la nueva revisión de la especificación siga las preferencias de los desarrolladores y no al contrario, es un paso muy importante en la dirección correcta. La especificación anterior hizo estándar algo nuevo y se impuso como modelo a seguir sin apenas haberse probado. Miles de programadores en todo el mundo se lanzaron a programar utilizando el estándar EJB sin reparar en las consecuencias de seguir un estándar que debía ser bueno “a priori”.
Aunque hoy día un número considerable de desarrolladores basan sus
aplicaciones en frameworks ligeros, fundamentalmente Spring, a menudo se
siguen utilizando modelos anémicos donde simplemente se han sustituido
las capacidades del contendor EJB. Los Entity Beans por POJOs, los
Session Beans por servicios basados en POJOs, JNDI por Inyección de
dependencias (IoC), CMP por ORM como Hibernate, TopLink o JDO y CMT por
Proxys Transaccionales AOP. Sin embargo el código sigue siendo
principalmente procedimental. Se puede observar que el anti-patron ADM
ha sobrevivido a su precursor, EJB 2.0 CMP (actualmente sustituido por
JPA) mientras que el verdadero corazón de la capa de negocio de esta
arquitectura, Rich Domain Model, no ha llegado tan lejos como los
propios frameworks que la soportan.
Acrónimos
- EJB: Enterprise Java Beans
- AOP: Aspect Oriented Programming
- DTO: Data Transfer Object
- JNDI: Java Naming and Directory Interace
- CMT: Container Managed Transactions
- CMP: Container Managed Persistence
- IoC: Inversión of Control (también conocido como Dependency Inyection)
- POJO: Plain Old Java Object
- ORM: Object Relational Mapping
- JDO: Java Data Objects
- JPA: Java Persistence API
- ADM: Anemic Domain Model
- RDM: Rich Domain Model
Bibliografía
- Patterns of Enterprise Application Architecture - Martin Fowler, Addisson Wesley 2002
- Expert One-on-One J2EE Design and Development
Rod Johnson – Wiley Publishing Inc, 2002
ISBN: 978-0-7645-4385-2 - Expert One-on-One J2EE Development without EJB
Rod Johnson, Juergen Hoeller - Wiley Publishing Inc, 2004
ISBN: 978-0-7645-5831-3 - POJOs in Action – Chris Richardson, Manning 2006
- Improving your code with a Rich Domain Model – Chris Richardson, Spring One Conference 2006