Post on 19-Aug-2020
Trabajo Profesional
Tutora: Adriana Echeverría
2009
Pablo Linares (80654)
Adrián Paredes (80130)
Diciembre de 2009
SISTRANS Sistema de Transporte de Larga Distancia
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 2
Tabla de contenido
1. Introducción .............................................................................................................. 8
2. Arquitectura ............................................................................................................ 10 2.1. Introducción ..................................................................................................... 10
2.2. Arquitectura de 4 capas .................................................................................... 10 2.3. Componentes .................................................................................................... 11
2.4. Capa de Dominio .............................................................................................. 13 2.4.1. Framework de Dominio ............................................................................. 13
2.4.2. Generic Subdomains .................................................................................. 15 2.4.3. Modelo ...................................................................................................... 17
2.5. Capa de Persistencia ......................................................................................... 19 2.6. Capa de Servicio .............................................................................................. 21
2.7. Soporte para Aplicaciones Clientes ................................................................... 21 2.8. Entidades DDD, Entidades EJB y DTOs........................................................... 23
2.9. Capas de Presentación (Aplicaciones Cliente) .................................................. 27 2.9.1. sistrans-extractor........................................................................................ 27
2.9.2. sistrans-procesos-reparaciones ................................................................... 28 2.9.3. sistrans-aerolineas ...................................................................................... 30
3. Análisis ................................................................................................................... 31 3.1. Lenguaje Ubicuo .............................................................................................. 31
3.2. Módulos ........................................................................................................... 33 3.2.1. Módulo de Unidades (MU) ........................................................................ 33
3.2.1.1. Domain Vision Statement ................................................................... 33 3.2.1.2. Especificación ..................................................................................... 33
3.2.2. Módulo de Rutas (MR) .............................................................................. 36 3.2.2.1. Domain Vision Statement ................................................................... 36
3.2.2.2. Especificación ..................................................................................... 36 3.2.2.3. Waypoints ........................................................................................... 36
3.2.2.4. Tramos................................................................................................ 37 3.2.2.5 Agregaciones ....................................................................................... 37
3.2.3. Módulo de Personal (MP) .......................................................................... 38 3.2.3.1. Domain Vision Statement ................................................................... 38
3.2.3.2. Especificación ..................................................................................... 38 3.2.4. Módulo de Clientes (MC) .......................................................................... 40
3.2.4.1. Domain Vision Statement ................................................................... 40 3.2.4.2. Especificación ..................................................................................... 40
3.2.4.3. Programa de recompensas ................................................................... 41 3.2.5. Módulo de Reparaciones (MREP).............................................................. 42
3.2.5.1. Domain Vision Statement ................................................................... 42 3.2.5.2. Especificación ..................................................................................... 42
3.2.5.3. Entidades ............................................................................................ 44 3.2.5.4. Revisiones Periódicas ......................................................................... 45
3.2.6. Módulo de Viajes (MV) ............................................................................. 46 3.2.6.1. Domain Vision Statement ....................................................................... 46
3.2.6.2. Especificación ........................................................................................ 46 3.2.6.3. Escalas ................................................................................................ 49
3.2.6.4. Tarifas ................................................................................................ 50 3.2.6.5. Cálculo del valor de un Viaje .............................................................. 50
3.2.6.6. Costos ................................................................................................. 50
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 3
3.2.6.7. Cálculo del costo por consumo de un Viaje ......................................... 50
3.2.6.8. Cálculo del costo por servicios de un Viaje ......................................... 52 3.2.6.9. Otros costos ........................................................................................ 52
3.2.6.10. Cálculo de las ganancias de un Viaje ................................................. 53 3.2.6.11. Sugerencia de tripulantes .................................................................. 53
3.2.7. Módulo de Pasajes (MPAS) ....................................................................... 53 3.2.7.1. Domain Vision Statement ................................................................... 53
3.2.7.2. Especificación ..................................................................................... 53 3.2.7.3. Ciclo de Vida de un Pasaje .................................................................. 56
3.2.7.4. Creación de un Pasaje ......................................................................... 56 3.2.7.5. Confirmación de una Reserva ............................................................. 58
3.2.7.6. Cancelación de un Pasaje .................................................................... 58 3.2.7.7. Aspectos Económicos ......................................................................... 59
3.2.8. Módulo de Ejecutivos (ME) ....................................................................... 59 3.2.8.1. Domain Vision Statement ................................................................... 59
3.2.8.2. Especificación ..................................................................................... 59 3.2.9. Módulo de Trámites (MT) ......................................................................... 60
4. Diseño..................................................................................................................... 60 4.1. Convenciones y Estándares .............................................................................. 60
4.1.2. Abreviaturas de los módulos del sistema .................................................... 60 4.1.3. Nomenclatura básica de codificación ......................................................... 61
4.1.4. Nomenclatura del modelo .......................................................................... 62 4.1.5. Riesgos ...................................................................................................... 64
4.1.5.1. Probabilidad de Ocurrencia ................................................................. 64 4.1.5.2. Severidad ............................................................................................ 64
4.1.5.3. Exposición al riesgo ............................................................................ 65 4.1.6. Estimaciones ............................................................................................. 65
4.2. EJB3 y Domain-Driven Design: Arquitecturas Incompatibles ........................... 65 4.3. Pruebas Unitarias ............................................................................................. 69
4.4. Distribución...................................................................................................... 70 4.4.1. sistrans.jar ................................................................................................. 70
4.4.2. sistrans-ejb.jar ........................................................................................... 70 4.4.3. sistrans-dto.jar ........................................................................................... 71
4.4.4. sistrans-ejb-client.jar .................................................................................. 71 4.4.5. sistrans-dto-personal.jar ............................................................................. 71
4.4.6. sistrans-ejb-personal.jar ............................................................................. 71 4.4.7. sistrans-dto-reparaciones.jar....................................................................... 71
4.4.8. sistrans-ejb-reparaciones.jar ....................................................................... 72 4.5. Mecanismo de Eager Loader ............................................................................ 72
4.6. Mecanismo de Programación de Tareas ............................................................ 78 4.6.1. Tecnología ................................................................................................. 78
4.6.2. Breve Introducción a los Timers de EJB 3.0............................................... 79 4.6.3. Implementación en la capa de Servicio ...................................................... 79 4.6.4. Ejemplo ..................................................................................................... 80
4.7. Comunicación con Sistema Externo de Capacitación ........................................ 82 4.7.1. sistrans-ejb-personal.jar ............................................................................. 82
4.7.2. Aplicación Extractor de Ejemplo ............................................................... 82 5. Calidad.................................................................................................................... 84
5.1. Datos de Prueba................................................................................................ 84 5.1.1. Parseo ........................................................................................................ 84
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 4
5.1.2. Clonación .................................................................................................. 84
5.1.3. Fuerza bruta ............................................................................................... 85 5.1.4. Realización de la carga .............................................................................. 85
5.2. Pruebas de Aceptación de Usuario (UAT) ........................................................ 86 5.3. Contenido ..................................................................................................... 86
Prueba N°1 (US1)............................................................................................ 87 Prueba N°2 (US10) .......................................................................................... 89
Prueba N°3 (US15) .......................................................................................... 90 Prueba N°4 (US21) .......................................................................................... 93
Prueba N°5 (US20) .......................................................................................... 94 Prueba N°6 (US7)............................................................................................ 96
Prueba N°7 (US18) .......................................................................................... 98 Prueba N°8 (US6)............................................................................................ 99
Prueba N°9 (US11) ........................................................................................ 101 Prueba N°10 (US16) ...................................................................................... 102
Prueba N°11 (US17) ...................................................................................... 102 Prueba N°12 (US8) ........................................................................................ 102
Prueba N°13 (US22) ...................................................................................... 102 Prueba N°14 (US2) ........................................................................................ 103
Prueba N°15 (US4) ........................................................................................ 103 Prueba N°16 (US5) ........................................................................................ 104
Prueba N°17 (US3) ........................................................................................ 106 Prueba N°18 (US23) ...................................................................................... 106
Prueba N°19 (US12) ...................................................................................... 108 Prueba N°20 (US14) ...................................................................................... 109
Prueba N°21 (US19) ...................................................................................... 110 6. Tutoriales .............................................................................................................. 111
6.1. Tecnología y Herramientas ............................................................................. 111 6.2. Deployment y ejecución de sistrans-ejb .......................................................... 112
6.3. Deployment y ejecución de la DEMO: sistrans-aerolineas .............................. 113 6.4. Instalación de Maven2 .................................................................................... 114
Windows 2000/XP ............................................................................................ 115 Unix-based Operating Systems (Linux, Solaris and Mac OS X)......................... 116
6.5. Qué copiar en la carpeta ―lib‖ del JBoss ......................................................... 116 6.6. Instalación de JBPM 3.3.1 .............................................................................. 117
7. Administración del Proyecto ................................................................................. 119 7.1. Product Backlog ............................................................................................. 119
7.2. Desarrollo de los Sprints ................................................................................. 125 7.2.1. Sprint 1 .................................................................................................... 125
7.2.1.1. Sprint Backlog .................................................................................. 125 7.2.1.2. Burndown Chart................................................................................ 127
7.2.1.3. Riesgos ............................................................................................. 127 7.2.1.4. Impedimentos ................................................................................... 130 7.2.1.5. Sprint Review y metas ...................................................................... 130
7.2.2. Sprint 2 .................................................................................................... 131 7.2.2.1. Sprint Backlog .................................................................................. 131
7.2.2.2. Burndown Chart................................................................................ 134 7.2.2.3. Riesgos ............................................................................................. 134
7.2.2.4. Impedimentos ................................................................................... 139 7.2.2.5. Sprint Review y metas ...................................................................... 139
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 5
7.2.3. Sprint 3 .................................................................................................... 139
7.2.3.1. Sprint Backlog .................................................................................. 139 7.2.3.2. Burndown Chart................................................................................ 142
7.2.3.3. Riesgos ............................................................................................. 142 7.2.3.4. Impedimentos ................................................................................... 146
7.2.3.5. Sprint Review y metas ...................................................................... 146 7.2.4. Sprint 4 .................................................................................................... 146
7.2.4.1. Sprint Backlog .................................................................................. 146 7.2.4.2. Burndown Chart................................................................................ 149
7.2.4.3. Riesgos ............................................................................................. 149 7.2.4.4. Impedimentos ................................................................................... 155
7.2.4.5. Sprint Review y metas ...................................................................... 155 7.2.5. Sprint 5 .................................................................................................... 156
7.2.5.1. Sprint Backlog .................................................................................. 156 7.2.5.2. Burndown Chart................................................................................ 159
7.2.5.3. Riesgos ............................................................................................. 159 7.2.5.4. Impedimentos ................................................................................... 165
7.2.5.5. Sprint Review y metas ...................................................................... 165 7.2.6. Sprint 6 .................................................................................................... 165
7.2.6.1. Sprint Backlog .................................................................................. 165 7.2.6.2. Burndown Chart................................................................................ 168
7.2.6.3. Riesgos ............................................................................................. 168 7.2.6.4. Impedimentos ................................................................................... 172
7.2.6.5. Sprint Review y metas ...................................................................... 172 7.3. Product Burndown Chart ................................................................................ 172
7.3.1. Gráfico .................................................................................................... 172 7.3.2. Cálculo del gráfico................................................................................... 173
7.4. Otros indicadores ........................................................................................... 174 7.4.1. Velocidad ................................................................................................ 174
8. Bibliografía ........................................................................................................... 176 9. Anexos .................................................................................................................. 177
9.1. Domain-Driven Design................................................................................... 177 9.1.1. Introducción ............................................................................................ 177
9.1.1.1. Aplicaciones Enterprise .................................................................... 177 9.1.1.2. Arquitectura de 4-tiers ...................................................................... 178
9.1.1.3. El Dominio es lo Único Importante ................................................... 180 9.1.1.4. El dominio no depende de la aplicación ............................................ 180
9.1.1.5. Tiers V.S. Layers .............................................................................. 181 9.1.1.6. Domain-Driven Design ..................................................................... 182
9.1.1.7. La importancia de un dominio portable ............................................. 184 9.1.2. Poniendo el Modelo de Dominio a trabajar .............................................. 184
9.1.2.1. Masticando el Conocimiento ............................................................. 185 9.1.2.2. Comunicación y el Uso del Lenguaje ................................................ 187 9.1.2.3. Uniendo el Modelo y la Implementación ........................................... 190
9.1.3. Los Componentes Fundamentales de un Modelo Guiado por el Dominio . 192 9.1.3.1. Aislando el Dominio ......................................................................... 193
9.1.3.2. Layered Architecture ........................................................................ 193 9.1.3.3. Anti-Patrón: Smart UI ....................................................................... 194
9.1.3.4. Un Modelo Expresado en Software ................................................... 195 9.1.3.5. Associations ...................................................................................... 195
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 6
9.1.3.6. Entities.............................................................................................. 197
9.1.3.7. Value Objects ................................................................................... 198 9.1.3.8. Services ............................................................................................ 199
9.1.3.9. Modules ............................................................................................ 200 9.1.3.10. Paradigmas de Modelado ................................................................ 201
9.1.3.11. El Ciclo de Vida de un Objeto de Dominio...................................... 202 9.1.3.12 Aggregates ....................................................................................... 202
9.1.3.13. Factories ......................................................................................... 204 9.1.3.14. Repositories .................................................................................... 205
9.1.4. Refactorizando Hacia una Visión Más Profunda ...................................... 206 9.1.4.1. Progreso ............................................................................................ 206
9.1.4.2. Haciendo Explícitos los Conceptos Implícitos ................................... 207 9.1.4.3. Diseño Flexible ................................................................................. 209
9.1.4.4. Intention-Revealing Interfaces .......................................................... 210 9.1.4.5. Side-Effect-Free Functions................................................................ 211
9.1.4.6. Assertions ......................................................................................... 211 9.1.4.7. Conceptual Contours ......................................................................... 212
9.1.4.8. Standalone Classes ............................................................................ 212 9.1.4.9. Closure of Operations ....................................................................... 213
9.1.4.10. Diseños Declarativos....................................................................... 213 9.1.4.11. Domain-Specific Language ............................................................. 214
9.1.5. Links de Interés ....................................................................................... 215 9.2. Scrum ............................................................................................................. 215
9.2.1. Roles ....................................................................................................... 216 9.2.2. Ciclo de Vida de Desarrollo ..................................................................... 216
9.2.3. Artefactos ................................................................................................ 217 9.2.4. Reuniones ................................................................................................ 218
9.2.5. Conclusiones ........................................................................................... 220 9.2.6. Fuentes .................................................................................................... 221
9.3. Introducción a EJB 3.0 ................................................................................... 221 9.3.1. ¿Qué es un EJB? ...................................................................................... 221
9.3.2. Tipos de EJBs .......................................................................................... 223 9.3.3. Entities y la Java Persistence API ............................................................ 224
9.3.4. ¿Qué es un contenedor de EJBs? .............................................................. 224 9.3.5. ¿Qué servicios proveen los EJBs? ............................................................ 225
9.3.6. HelloUser Example.................................................................................. 226 9.3.7. Código del Lado del Servidor .................................................................. 227
9.3.8. Código del Lado del Cliente .................................................................... 227 9.3.9. Inyección de Dependencia ....................................................................... 227
9.3.10. Ejemplo de la aplicación ActionBazaar .................................................. 229 9.3.11. PlaceBinBean: un stateless bean ............................................................ 230
9.3.12. PlaceOrderBean: un stateful bean........................................................... 231 9.3.13. OrderBillingMDB: Un Message-Driven Bean ........................................ 234 9.3.14. Persistiendo las Entidades Bid y Order a través de JPA .......................... 235
9.3.15. Conclusión............................................................................................. 238 9.4. Información consultada .................................................................................. 239
9.4.1. Tecnología ............................................................................................... 239 9.4.2. Negocio ................................................................................................... 241
9.4.2.1. General ............................................................................................. 241 9.4.2.2. Empleados ........................................................................................ 241
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 7
9.4.2.3. Licencias........................................................................................... 242
9.4.2.4. Clientes ............................................................................................. 242 9.4.2.5. Viajes ............................................................................................... 243
9.4.2.6. Unidades ........................................................................................... 245
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 8
1. Introducción
SISTRANS nació del deseo de realizar una implementación de Domain-Driven Design,
siguiendo la filosofía planteada por Eric Evans y aplicando muchos de sus patrones y
conceptos. Necesitábamos para esto un dominio complejo, un dominio que valiera la
pena el desafío de orientar el Trabajo Profesional a un desarrollo fuertemente orientado
al negocio. Comenzamos a investigar la bibliografía relacionada y así surgió que los
sistemas que mayor lógica de negocio poseen son las aplicaciones Enterprise. En este
tipo de software es donde más se busca aislar los aspectos técnicos de la complicación
intrínseca del dominio. Esto nos condujo a la conclusión de que no sólo haríamos una
implementación de Domain-Driven Design, también construiríamos una aplicación
Enterprise.
SISTRANS es un producto básico customizable, un core de negocio capaz de adaptarse
a las distintas empresas de transporte de larga distancia. Si hablamos de una arquitectura
Enterprise típica, lo que nosotros proveemos es una capa de acceso al negocio, una capa
de dominio y las capas de infraestructura necesarias. Sobre este core se pueden montar
variadas presentaciones. Las aplicaciones que se construyan sobre el sistema no estarán
limitadas a una empresa de transporte en particular (como aerolíneas, barcos, micros o
trenes) y por supuesto tampoco a una vista (pudiéndose construir aplicaciones web, de
escritorio, para dispositivos móviles, etc.). El producto es genérico, por lo cual no sólo
sirve para construir aplicaciones de transporte de personas, sino que también brinda la
posibilidad de construir aplicaciones para transporte de carga o paquetes.
El Trabajo Profesional tiene una fuerte orientación a la Arquitectura. Creemos que las
buenas arquitecturas son las que sirven como plataforma de los buenos sistemas.
SISTRANS sigue muchos de los principios y patrones de Domain-Driven Design y del
libro de Patrones Enterprise de Martin Fowler1.
También hemos puesto importante énfasis en la administración del proyecto y en la
elección de las tecnologías y herramientas. Elegimos Scrum como metodología2 de
desarrollo3, porque es una de las metodologías ágiles que más conocemos y los
principios de Domain-Driven Design son más afines a una metodología ágil que a una
orientada al plan, como puede ser RUP. Para la tecnología, optamos por Java EE +
EJB3, la cual creemos que es actualmente la plataforma de desarrollo más madura y
robusta para la construcción de aplicaciones Enterprise. Como herramienta para la
administración del proyecto usamos Assembla4, que nos proporcionó un espacio para
escribir la documentación de forma colaborativa en formato de wiki y un repositorio
SVN para alojar el código fuente y los distintos artefactos del proyecto. Otra
herramienta que nos fue útil para la administración del proyecto, pero más orientada al
desarrollo, fue Maven2, con la que pudimos gestionar los proyectos Eclipse, las
complicadas dependencias de los mismos, empaquetar, desplegar y algunas otras cosas
más.
1 Ver Bibliografía. 2 Aunque hablando estrictamente Scrum no es una metodología de desarrollo, sino un conjunto de
principios y buenas prácticas, usaremos la palabra metodología para simplificar la redacción. Lo mismo
aplica a RUP. 3 Usamos Scrum, pero con algunas leves modificaciones para adaptarlo a la cantidad de personas del
equipo de trabajo y al tiempo disponible. 4 http://www.assembla.com/
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 9
El presente documento abarca toda la documentación de SISTRANS y del proyecto.
Está dividido en ocho secciones:
Arquitectura: donde se describe la arquitectura, se explican las decisiones
tomadas en las distintas capas y los conceptos fundamentales en los que se basa
el desarrollo del producto.
Análisis: donde se especifica funcionalmente cada módulo, mezclando por
momentos con cuestiones específicas de implementación; en lo que respecta a
Domain-Driven Design, esta sección compone la especificación del Modelo de
Dominio y la definición del Lenguaje Ubicuo.
Diseño: donde se tratan temas puntuales de implementación, como Mecanismo
de Eager Loader, Mecanismo de Programación de Tareas, cuestiones sobre
incompatibilidades entre filosofía y tecnología, etc.; también se establecen los
lineamientos generales para el desarrollo del proyecto.
Calidad: donde se incluyen las Pruebas de Aceptación de Usuario (UAT) y
algunas indicaciones de cómo ejecutarlas.
Tutoriales: donde se detallan todas las herramientas y tecnologías usadas y se
incluyen explicaciones paso a paso de temas puntuales sobre cómo armar los
proyectos, cómo desplegarlos, cómo ejecutarlos o cómo instalar el software y las
herramientas necesarias.
Administración del Proyecto: donde se adjunta toda la documentación referida
a la administración del proyecto: Product Backlog, desarrollo de cada uno de los
sprints: burndown chart, riesgos, impedimentos, sprint reviews, y demás
artefactos de Scrum.
Bibliografía: donde se enumera la bibliografía que seguimos para el desarrollo
del Trabajo.
Anexos: donde incluimos anexos para varios de los temas teórico-prácticos que
estuvimos estudiando para la realización del Trabajo. El primer anexo
comprende un resumen de casi todo el libro de Domain-Driven Design. El
segundo trata sobre Scrum, y es un breve apartado que explica de forma concreta
los principios básicos de la metodología. El tercer anexo se enfoca directamente
en la tecnología, dando una breve introducción a la plataforma de Java EE,
EJB3, sobre la que construimos el producto. Por último, adjuntamos parte de la
información que fuimos recolectando sobre los distintos dominios de transporte:
barcos, aviones, micros, trenes, etc.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 10
2. Arquitectura
2.1. Introducción
SISTRANS es un producto básico customizable, un core de negocio capaz de adaptarse
a las distintas empresas de transporte de larga distancia. Desde el punto de vista del
cliente, SISTRANS provee un conjunto de servicios para acceder a un Modelo de
Dominio portable, construido con las buenas prácticas de Domain-Driven Design.
SISTRANS está preparado para funcionar en un ambiente distribuido, soportar el
acceso concurrente de usuarios y proveer una capa de infraestructura que resulta
transparente al consumidor del sistema. Sobre estos servicios, se pueden montar
variadas presentaciones. Las aplicaciones que se construyan sobre el sistema no estarán
limitadas a una empresa de transporte en particular, ni a una plataforma específica.
Al proveer una capa robusta de servicios, SISTRANS brinda la posibilidad de
construir aplicaciones en base a dos dimensiones no excluyentes:
Presentación para distintas aplicaciones: aplicaciones para administración de
vuelos, micros, trenes, carga de paquetes, pasajeros, etc.
Presentación para distintas plataformas: aplicaciones web, de escritorio,
móviles, etc.
2.2. Arquitectura de 4 capas
La arquitectura que SISTRANS implementa es muy similar a la arquitectura propuesta
por Martin Fowler en su libro Patterns of Enterprise Application Architecture5:
Figura 2.1: Arquitectura de SISTRANS
5 Ver Bibliografía.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 11
En su libro, Fowler propone una arquitectura típica de tres capas: Persistencia /
Dominio / Presentación. A estas tres capas, nosotros hemos agregado una capa más,
ubicada entre la capa de Presentación y la de Dominio, a la que llamamos Acceso al
Negocio o Service Layer.
Martin Fowler presenta esta capa de Servicio como un patrón de Organización de
Dominio llamado Service Layer6. La implementación de este patrón es lo que permite
a SISTRANS la posibilidad de que el cliente pueda desarrollar distintas capas de
Presentación, montadas sobre una única capa de Acceso al Negocio:
Figura 2.2: Distintas capas de Presentación para única ServiceLayer
SISTRANS provee una capa de Dominio, una capa de Persistencia y una capa de
Acceso al Negocio, dejando que el cliente/consumidor del sistema pueda implementar
su propia capa de Presentación.
2.3. Componentes
En la siguiente figura podemos observar una vez más la Arquitectura de 4 capas de
SISTRANS, esta vez con mayor detalle:
6 http://martinfowler.com/eaaCatalog/serviceLayer.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 12
Figura 2.3: Componentes de SISTRANS ubicados por capas
Como podemos ver en la Figura 3, SISTRANS abarca la capa de Persistencia, la de
Dominio y la de Servicio. Otro detalle muy importante, que se puede apreciar mejor en
la Figura 1, es que la capa de Dominio no tiene ninguna dependencia con otra capa.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 13
De hecho, son las capas de Persistencia y de Servicio las que conocen a la capa de
Dominio y no al revés. Esto es así, ya que el dominio es portable, genérico y
reutilizable, independientemente de la tecnología, plataforma y/o arquitectura que
estemos usando.
En las siguientes secciones analizaremos con más detalle cada una de las capas,
comenzando con la más importante: la de Dominio, detallando el funcionamiento y el
propósito de cada una de ellas, las decisiones que se tuvieron que tomar para su
implementación y los componentes que allí viven.
2.4. Capa de Dominio
La capa de Dominio es la más importante de todo el sistema. Es tan importante que
Eric Evans en Domain-Driven Design asegura que el Dominio es la única capa
importante de una aplicación de negocios.
En la Figura 3, puede verse que existen dos grandes componentes en la capa de
Dominio de SISTRANS. Un componente que hemos llamado Framework y otro que
hemos llamado Modelo.
Figura 2.4: Capa de Dominio de SISTRANS
Esencialmente, el Modelo de Dominio vive en el componente Modelo. El Modelo
tiene una dependencia directa con el Framework de Dominio. Esto significa que si
deseamos llevarnos el Modelo para ejecutarlo en otra aplicación, tendremos que
llevarnos también el Framework, o sea: toda la capa de Dominio.
2.4.1. Framework de Dominio
Como se muestra en la Figura 4, el Framework de Dominio no tiene dependencia con
ningún otro componente. Este framework es un módulo genérico que establece un
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 14
conjunto de clases, muchas de ellas abstractas, e interfaces que sirven de marco para la
implementación de un Modelo de Dominio puro utilizando DDD.
El paquete más genérico está compuesto por clases abstractas e interfaces que
especifican Patrones de Dominio extraídos del libro de DDD y del libro de Martin
Fowler antes mencionado. En este paquete viven las siguientes clases/interfaces:
Entity: Clase que implementa métodos genéricos para la manipulación de
Entidades del mundo DDD. Los Objetos de Dominio del Modelo que sean
Entidades deberán extender de esta clase para poder heredar su comportamiento.
Entity tiene implementados los métodos: sameIdentityAs, equals y hashCode.
Además, se encarga de manejar el atributo identificador con el cual se establece
una identidad única a cada Entidad. De esta forma, el manejo de la identidad es
transparente para los Objetos de Dominio que pertenezcan al Modelo. (El
acceso al atributo identificador es protegido y no se puede tener acceso
fuera del framework.)
ValueObject: Clase que implementa métodos genéricos para la manipulación de
Entidades del mundo DDD. Los Objetos de Dominio del Modelo que sean
Objetos de Valor deberán extender de esta clase para poder heredar su
comportamiento. ValueObject tiene implementados los métodos: sameValueAs,
equals y hashCode. Esta clase no cuenta con un atributo identificador, ya que
conceptualmente un Objeto de Valor no tiene identidad. (Notar la diferencia
semántica del nombre entre el método sameIdentityAs de las Entidades y
sameValueAs de los Objetos de Valor, de los cuales los equals hacen uso; el
primero compara únicamente los id, el segundo compara todos los atributos
del objeto.)
Service: Interfaz que representa un Servicio genérico del Modelo. Todos los
objetos del Modelo, según DDD, deben extender o implementar alguno de los
tres tipos ya mencionados: Entidad, Objeto de Valor o Servicio. Los Servicios
básicamente son clases con métodos pero sin atributos, que por definición no
conservan estado.
IdentityField: Esta clase está basada en un patrón de Martin Fowler llamado
de la misma forma7. Es un patrón de mapeo objeto-relacional, que sirve en este
caso para asignarle una identidad única a cada Entidad del Dominio. Un
IdentityField es único y universal. Entity usa el patrón IdentityField para
conservar su identidad. IdentityField es un Objeto de Valor.
Repository: Interfaz que especifica los métodos que debe implementar un
Repositorio. Repository es un patrón de DDD y sirve para contar con una
representación lógica de una colección de Entidades de Dominio y poder
manipularla. Los métodos que especifican la interfaz son independientes de la
implementación. Un Repositorio puede ser una colección en memoria, una tabla
en una base de datos, registros en un archivo de texto, o lo que sea. Las
implementaciones que SISTRANS provee de Repository se encuentran en la
capa de Persistencia y se discutirán más adelante.
7 http://martinfowler.com/eaaCatalog/identityField.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 15
NamedQuery: Es una clase que está basada en el patrón QueryObject de
Martin Fowler8. No es una implementación del todo correcta del patrón, sino
que está más preparada para encapsular el mecanismo de NamedQueries con el
que cuenta JPA. Por supuesto no necesita JPA para ejecutarse. Básicamente esta
clase sirve para guardar el nombre de la NamedQuery que se necesita invocar y
un Mapa con los parámetros que servirán de filtro para la consulta. Los
NamedQueries son recibidos por parámetro en los métodos de búsqueda de los
Repositorios. Un NamedQuery sirve para filtrar Entidades en un Repositorio.
NamedQueryExecutor: Interfaz que ejecuta y devuelve objetos genéricos
armados on-the-fly. Se recomienda usar esta interfaz solamente cuando se quiera
obtener el resultado de alguna función aplicada a la persistencia, o algún mix de
resultados de distintas Entidades. Para los casos en los que claramente una
consulta devolverá uno o un conjunto de datos del mismo tipo de Entidad, se
recomienda usar la interfaz genérica Repository especificando la Entidad sobre
la cual se quiere trabajar. Casos de uso típicos de esta interfaz son las
NamedQueries que ejecuten funciones count, max, min, o que estén agrupando
por uno o dos atributos; también se puede usar para ejecutar una query que
devuelva tres únicos atributos, por ejemplo, y cada uno de esos tres pertenezcan
a tres Entidades distintas.
2.4.2. Generic Subdomains
Eric Evans, en DDD, explica que algunas partes del modelo no son esencialmente
relevantes al dominio y no agregan absolutamente ningún valor al conocimiento del
negocio. Por el contrario, estos conceptos extraños "ensucian" el core del dominio
(Core Domain), logrando que los conceptos realmente importantes del modelo sean
difíciles de discernir y comprender.
El Core Domain es la esencia de un Modelo de Dominio, el verdadero valor de
negocio. En el diseño de cualquier capa de dominio extensa existen muchos otros
componentes que no forman parte de este Core Domain básico y fundamental. Los
Generic Subdomains son componentes del Modelo que son fundamentales para el
correcto funcionamiento del Core Domain, pero que no aportan conocimiento del
negocio. Los Generic Subdomains no son componentes específicos del dominio en que
se está trabajando.
En SISTRANS tenemos varios Generic Subdomains, que se encuentran aislados, cada
uno en sus respectivos paquetes, con el fin de no contaminar el framework de Dominio
ni el Modelo, a saber:
Money: Este paquete se encarga de manipular dinero. Money es un Objeto de
Valor y es el objeto fundamental de este subdominio. Money encapsula el
importe y la moneda de una cifra de dinero. Además, en este subdominio
podemos encontrar funcionalidades como: cambios de moneda, operaciones con
distintos importes, cotizaciones, etc. Para SISTRANS sólo se implementarán las
operaciones necesarias.
8 http://martinfowler.com/eaaCatalog/queryObject.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 16
Variables: Este paquete se encarga de manipular variables genéricas definidas
por el programador de la aplicación cliente (o capa de Presentación). SISTRANS
brinda soporte para la persistencia de estas variables y para la manipulación de
sus valores sin necesidad de casteos o mecanismos externos de introspección. El
programador cliente podrá definir tipos de variables con un nombre y un tipo
de clase java, para después almacenar en otro objeto variables de este tipo. Una
de las Entidades del Modelo que hacen uso de este Generic Subdomain es
Unidad.
Measures: Este paquete se encarga de manipular magnitudes, expresadas por un
valor y su correspondiente unidad de medida. Provee soporte para los tipos de
unidades de medida más utilizados en el dominio, tales como longitud, área,
volumen, tiempo, velocidad, peso (masa), potencia, energía, consumo y
frecuencia. Además, en este subdominio se pueden encontrar utilidades
relacionadas, tales como la conversión entre unidades.
Waypoints: Este paquete se encarga de manipular los puntos de interés9 del
dominio. El Waypoint es una Entidad que posee coordenadas geográficas
(latitud, longitud, elevación) y un nombre para describir un punto en el planeta.
Rules: Este paquete provee una interfaz simplificada para el uso del motor de
reglas Drools. Lógicamente genera dependencia con las librerías de Drools. Esto
no es del todo malo, ya que si no se necesita, se puede remover, y además JBoss
Drools es considerado un conjunto de bibliotecas de dominio, igual que JBoss
jBPM y Apache Commons.
Sortables: Este paquete se encarga de validar y proveer de un orden a los
objetos de dominio que lo requieren, tales como Tramo, Escala,
TarifaDeSegmentoDeViaje, TramoDeItinerario, ItinerarioAlternativo, etc.
Provee dos interfaces fundamentales: Sortable, para objetos que deben ser
ordenados mediante un atributo llamado orden, y Segment, que también es un
Sortable, pero que agrega funcionalidad para recorrer los extremos y validar
que, en un conjunto, los extremos sean coincidentes. Esto se usa mucho para
validar que los Tramos de una Ruta sean válidos, o los Tramos de un Itinerario.
Eagerloader: Este paquete provee una manera de leer colecciones de objetos de
dominio de forma selectiva y dinámica. Más adelante dedicaremos una sección
entera a la explicación del Mecanismo de EagerLoader.
Specifications: Provee una implementación simple del patrón Specification de
Domain-Driven Design. La implementación es bastante similar a la provista en
el libro, salvo por una o dos modificaciones. Comúnmente puede servir utilizar
este patrón para desacoplar código del modelo del código de un motor de reglas
como jBPM. En Domain-Driven Design aconsejan usar este patrón cuando las
reglas de negocio son medianamente complejas. Cuando la complejidad de las
reglas es superior, puede resultar necesario utilizar un motor de reglas.
SISTRANS no utiliza la funcionalidad completa de los Specifications provista
por el framework. Nada más usa el AbstractSpecification para desacoplar el
9 Juego de coordenadas para ubicar puntos de referencia tridimensionales utilizados en la navegación. Determinación
de un lugar mediante sus coordenadas geográficas y un nombre.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 17
módulo de reglas del framework de las clases del modelo, como mencionamos
unas oraciones más atrás.
2.4.3. Modelo
Llegamos al corazón de la capa de Dominio y de SISTRANS en general. El Modelo de
Dominio.
El Modelo de SISTRANS está dividido en nueve módulos:
Módulo de Unidades (MU)
Módulo de Rutas (MR)
Módulo de Personal (MP)
Módulo de Clientes (MC)
Módulo de Reparaciones (MREP)
Módulo de Viajes (MV)
Módulo de Pasajes (MPAS)
Módulo de Ejecutivos (ME)
Módulo de Trámites (MT)
A continuación, la Figura 5 muestra cada uno de estos módulos y las dependencias con
las que se interrelacionan:
Figura 2.5: Módulos del Modelo de Dominio de SISTRANS
Si se observa con atención el diagrama de componentes de arriba, podemos ver que hay
módulos que no dependen de otros. Estos módulos son:
Módulo de Unidades (MU)
Módulo de Personal (MP)
Módulo de Rutas (MR)
Unidades
(MU)Personal
(MP)
Reparaciones
(MR)
Rutas
(MR)
Pasajes
(MPAS)
Trámites
(MT)
Viajes
(MV)
Clientes
(MC)
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 18
Módulo de Trámites (MT)
El Módulo Reparaciones (MREP) hace uso del Módulo Unidades (MU) y del Módulo
Personal (MP).
El Módulo Viajes (MV) hace uso del Módulo Unidades (MU), del Módulo Personal
(MP) y del Módulo Rutas (MR).
El Módulo Pasajes (MPAS) hace uso del Módulo Viajes (MV).
El Módulo Clientes (MC) hace uso del Módulo Pasajes (MPAS) y del Módulo Tramites
(MT).
Siguiendo uno de los criterios más prácticos de DDD, se buscó que las dependencias
entre paquetes fueran mínimas. Evans aconseja eliminar todas las relaciones no
esenciales, con el fin de minimizar la complejidad del Modelo.
Así como hay módulos que no dependen de otros, también existen módulos de los
cuales no depende ninguno. El Módulo de Reparaciones (MR) es uno de ellos. También
el Módulo Clientes (MC). Además, hay otro módulo que no hemos incluido en la figura
anterior, que es el Módulo Ejecutivos (ME). El ME es otro de estos módulos del cual
nadie depende, pero se trata de un componente muy particular, ya que, al generar
informes, estadísticas y analizar de forma inteligente la información maestra y
transaccional, depende de todos los otros componentes:
Figura 2.6: Dependencias del Módulo Ejecutivos (ME)
Ejecutivos
(ME)
Unidades
(MU)
Personal
(MP)
Reparaciones
(MR)Rutas
(MR)
Pasajes
(MPAS)
Trámites
(MT)
Viajes
(MV)
Clientes
(MC)
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 19
Cada uno de estos módulos forman el Core Domain de SISTRANS.
2.5. Capa de Persistencia
La capa de Persistencia es el conjunto de paquetes que provee la infraestructura de la
aplicación. A diferencia de la capa anterior, esta capa sí está atada a la tecnología, ya
que aquí se encuentran las implementaciones de los Repositorios y la lógica para
acceder a los soportes externos de datos.
SISTRANS provee dos diferentes implementaciones de Repository:
DummyRepository: Es una implementación que funciona con un
DummyMapper, que mapea objetos y arrays JSON a Objetos Java del Modelo.
Este Repositorio sirve para hacer funcionar SISTRANS sin necesidad de una
Base de Datos o un Servidor de Aplicaciones. El DummyRepository es ideal para
los Unit Test.
JpaRepositoryBean: Es una implementación que funciona con JPA, la
especificación de Persistencia de EJB 3.0. JpaRepositoryBean es un Session
Bean de EJB 3.0, que inyecta un EntityManager para manipular Entity Beans.
Para hacer funcionar correctamente este Repositorio es necesario desplegarlo en
un Servidor de Aplicaciones que implemente la especificación EJB 3.0 y que el
Servidor tenga configurado un ORM (DataMapper) y una conexión a una base
de datos relacional.
Figura 2.7: Capa de Persistencia de SISTRANS
La interfaz de Repository es un generic. Lo que significa que la misma interfaz sirve
para reconstituir y almacenar cualquier Entidad del Dominio.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 20
Figura 2.8: Interfaz Repository
Además, la capa de Persistencia provee una implementación
de NamedQueryExecutor llamada JpaNamedQueryExecutorBean.
JpaRepositoryBean hace uso de esta implementación heredando de ella para poder
reutilizar gran parte de la lógica de las consultas realizadas a través de
NamedQueries de JPA.
Figura 2.9: Diagrama de clases de la capa de Persistencia
La capa de Persistencia cuenta con un archivo de propiedades llamado
persistencia.properties en el cual se puede especificar, entre otras cosas, si se quiere que
la infraestructura sea dummy o no.
Debido a que la capa de Dominio no tiene dependencia con esta capa ni con ninguna
relacionada con la tecnología, no se usaron las anotaciones de EJB 3.0 para realizar el
mapeo Objeto-Relacional de las Entidades y Objetos de Valor del modelo. El mapeo de
las clases del Modelo se encuentra en el archivo: orm.xml10
.
10 http://java.sun.com/xml/ns/persistence/orm_1_0.xsd
<<interface>>
Repository<T>
+find(id:IdentityField,clazz:Class<T>): T
+findAll(clazz:Class<T>): List<T>
+findAll(clazz:Class<T>,first:Integer,max:Integer): List<T>
+findSingleResult(namedQuery:NamedQuery,
clazz:Class<T>): T
+findResults(namedQuery:NamedQuery,clazz:Class<T>): List<T>
+findResults(namedQuery:NamedQuery,clazz:Class<T>,
first:Integer,max:Integer): List<T>
+count(clazz:Class<T>): Long
+store(t:T): void
+refresh(t:T,clazz:Class<T>): T
+remove(t:T)
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 21
2.6. Capa de Servicio
La capa de Servicio (Acceso al Negocio o Service Layer) provee las interfaces que las
diferentes capas de Presentación o aplicaciones cliente pueden invocar. Estas interfaces
están implementadas con EJBs 3.0, por lo tanto, los servicios podrán ser invocados de
forma remota (desde una aplicación desktop, un servidor web o lo que sea). También
podrían ser inyectados de forma local si la capa de Presentación se encuentra
desplegada en el mismo servidor de aplicaciones en que se encuentran desplegados los
EJBs de SISTRANS.
Figura 2.10: Capa de Servicio de SISTRANS
La estructura de paquetes que podemos encontrar en la capa de servicio es muy parecida
a la estructura de paquetes del dominio. En la capa de servicio tendremos un paquete
por cada Módulo al que necesitemos tener acceso. Ya que la lógica de negocio no se
ejecuta directamente, sino a través de estas ServiceLayers, tendremos distintos Session
Beans que servirán para ejecutar de forma remota mecanismos internos del core domain
encapsulados en interfaces que revelan de forma declarativa sus intenciones11
.
La lógica de una ServiceLayer es puramente técnica. La capa provee Servicios que
consumen los Servicios, Entidades y Objetos de Valor del modelo, y accede a la
persistencia a través de la interfaz Repository del framework de DDD. Notar que, si bien
esta capa posee una fuerte dependencia tecnológica con la plataforma EJB 3.0, no
depende directamente de la capa de persistencia ni de las tecnologías que allí se estén
usando. Podemos ver anotaciones de Session Beans, pero no vamos a encontrar ni una
sola anotación de JPA, ni mucho menos una dependencia con Hibernate.
Típicamente, las ServiceLayers se encargan de validar los parámetros y de llamar a uno
o dos servicios del dominio. Las interfaces están fuertemente orientadas a servicios
siguiendo algunas de las filosofías más básicas de SOA.
2.7. Soporte para Aplicaciones Clientes
Junto con los componentes del sistema, SISTRANS provee algunos módulos para
desarrollar distintas aplicaciones cliente. Estos módulos son paquetes de clases e
interfaces para poder establecer la comunicación remota entre cliente y servidor.
Entre los paquetes cliente que SISTRANS provee por defecto podemos encontrar dos
distintos tipos de distribuciones:
Paquetes que exporta la capa de dominio (los DTOs)
11 Ver Patrón Intention-Revealing Interfaces de Domain-Driven Design.
Servicio
ServiceLayer 1 ServiceLayer 2 ServiceLayer 3
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 22
Paquetes que exporta la capa de servicio (las interfaces de las ServiceLayers)
Luego, dentro de cada uno de los grupos podemos encontrar más o menos módulos
dependiendo del paquete que se esté exportando, a saber:
Paquetes cliente para una capa de presentación completa (incluye todos los
módulos del modelo)
Paquetes cliente para una aplicación cliente que acceda sólo a la información de
Personal (incluye sólo el MP)
Paquetes cliente para una aplicación externa, por ejemplo un paquete de
workflows, que consuma el módulo de reparaciones (incluye el MREP y sus
dependencias: MU y MP)
Recordemos la Figura 2, donde se muestra las diferentes aplicaciones cliente que
pueden acceder a distintas porciones de la capa de servicio. Esto, en EJB 3, se logra
precisamente con estas distintas distribuciones de paquetes, en las que en algunas están
incluidas todos los módulos y en otras no.
La capa de Dominio exporta el framework de DDD completo más los Entity Beans del
modelo, para que los mismos sean usados como DTOs en las distintas capas de
Presentación para pasar datos hacia y desde el core de SISTRANS. El truco está en que
el paquete del modelo no está completo. No se incluyen los Session Beans ni las
interfaces de los mismos. Lo que significa que las aplicaciones clientes nunca podrán
acceder directamente a la lógica de negocio. La lógica de negocio de una Entidad o
un Objeto de Valor sólo puede ser invocada desde la capa de Servicio o de la
misma capa de Dominio.
Los paquetes cliente que la capa de dominio exporta por defecto son:
sistrans-dto (los paquetes del framework + todos los DTOs)
sistrans-dto-personal (los paquetes del framework + los DTOs del MP)
sistrans-dto-reparaciones (los paquetes del framework + los DTOs de los
módulos: MP, MU y MREP)
La capa de servicio exporta las interfaces de los EJBs (las ServiceLayers) que pueden
inyectarse o invocarse remotamente12
. Notar que al no proveer los Beans de las
implementaciones, toda la lógica de la capa de servicio se ejecutará del lado del
servidor, del lado de SISTRANS.
Los paquetes cliente que la capa de servicio exporta por defecto son:
sistrans-ejb-client (todas las interfaces de las ServiceLayers)
sistrans-ejb-personal (sólo las interfaces de las ServiceLayers que pertenecen al
MP)
12 Según las Convenciones y Estándares de SISTRANS, los nombres de estas interfaces terminan con las
palabras: ServiceLayer; por ejemplo: UnidadServiceLayer o ClienteServiceLayer.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 23
sistrans-ejb-reparaciones (sólo las interfaces de las ServiceLayers que
pertenecen al MP, MU y MREP)
2.8. Entidades DDD, Entidades EJB y DTOs
Es interesante profundizar un poco más el tema de que los paquetes cliente que exporta
la capa de dominio contienen los Entity Beans del Modelo, o sea: sólo la parte de datos
de los Objetos de Dominio. Históricamente, la forma que una capa de Presentación
tiene de traer los datos del negocio para mandarlos a la vista (o viceversa) en una
aplicación de negocio es a través de Data Transfer Objects13
. Los DTOs no son más que
objetos sin lógica, que sirven como contenedores para transportar atributos hacia abajo
y hacia arriba entre capas. Usualmente se necesita un mapeo entre estos objetos DTO y
los objetos de Dominio. A menudo el mapeo se encuentra en la misma capa de
Presentación, pero muchas veces también puede ubicarse en la capa de Servicio. Este
mapeo es tedioso y propenso a errores.
Afortunadamente, a partir de EJB 3.0, los mismos Entity Beans que sirven en el Modelo
para representar los datos de un Objeto de Dominio y para persistir en la capa de
Persistencia, pueden ser usados como DTOs (esto es así, ya que a partir de la versión 3,
se usan simples POJOs para la persistencia).
En SISTRANS, los Beans de Negocio cumplen 3 diferentes roles, dependiendo de la
capa en la que se encuentren:
Objetos de Dominio (Entidades u Objetos de Valor) si se encuentran en la
capa de Dominio o de Servicio.
Entity Beans (o Entidades EJB) si se encuentran en la capa de Persistencia
(dentro de un Repository, las Entidades EJB se mantienen sincronizadas con el
mapper de persistencia, gracias al EntityManager que provee JPA y la
implementación de Hibernate que SISTRANS usa).
DTOs si se encuentran en la capa de Presentación o aplicación cliente.
Conceptualmente se podría afirmar que un objeto Unidad, por ejemplo, no es el mismo
si se está manipulando en una capa o en otra. En la práctica, los tres distintos tipos de
objetos usan la misma definición de clase. Pero si miramos en detalle, desde el punto de
vista de Domain-Driven Design, esta afirmación sigue valiendo, ya que una Entidad,
que es lo que comúnmente se trasporta (por lo menos en parte) de una capa a otra y lo
único que tiene identidad, va variando su ID dependiendo de la capa en la que se esté
usando, lo que significa que el objeto va cambiando de identidad, lo que significa que el
objeto nunca es el mismo.
Veamos un ejemplo simple:
Supongamos que un programador cliente quiere recuperar un Empleado (de cualquier
tipo, no importa) desde una aplicación cliente a través de su número de legajo. Para
hacerlo deberá invocar alguno de estos servicios provistos por la
EmpleadoServiceLayer:
13 http://martinfowler.com/eaaCatalog/dataTransferObject.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 24
public Empleado recuperarPorNumeroLegajo(Empleado empleado);
public Empleado recuperarPorNumeroLegajo(Integer numeroLegajo);
public Empleado recuperarPorNumeroLegajo(Empleado empleado,
EagerLoader eagerAttributes);
public Empleado recuperarPorNumeroLegajo(Integer numeroLegajo,
EagerLoader eagerAttributes);
Ignoremos por ahora los dos últimos métodos; se explicará el Mecanismo de
EagerLoader en otra sección. Y más allá de que la segunda operación sea la más
práctica para utilizar (cuando son pocos parámetros los que tenemos que transportar), a
los fines didácticos de lo que estamos explicando, vamos a elegir el primer método:
public Empleado recuperarPorNumeroLegajo(Empleado empleado);
En alguna parte del código, el programador cliente escribirá:
Empleado empleado = new Empleado();
El programador cliente sabe que está instanciando un DTO llamado empleado y no
sabe mucho más. Internamente, por ser Empleado una Entidad DDD, se llamará al
constructor de Entity que genera automáticamente un ID para el objeto:
public Entity() {
id = IdentityField.createIdentityField();
}
A la clase Entity poco le importa que se está ejecutando del lado del cliente y que en ese
momento no es una Entidad DDD, sino un DTO. Ella genera una identidad para el
objeto porque sabe que no puede existir en ningún momento una Entidad sin un ID
válido.
Cuando el programador invoca a la ServiceLayer son varias las cosas que suceden:
empleado.setNumeroLegajo(1234);
empleado = empleadoServiceLayer.recuperarPorNumeroLegajo(empleado);
Por empezar, se serializa el DTO empleado y viaja a través de la red para ser recibido
por el servidor de aplicaciones que está escuchando en el puerto indicado. El servidor de
aplicaciones obtiene la respectiva implementación de EmpleadoServiceLayer, abre una
transacción de negocio y ejecuta el método. En el cuerpo del método:
Validará que los parámetros recibidos sean correctos (en este caso empleado y
empleado.numeroLegajo)
Armará la NamedQuery necesaria para satisfacer la consulta
Le pedirá a la interfaz Repository que ejecute la NamedQuery y le devuelva el
objeto buscado
Así, indirectamente el servidor de aplicaciones invocará al código específico de la
implementación de Repository, que, para el caso del ejemplo imaginemos que es
JpaRepositoryBean. Esto involucra dos conceptos muy importantes:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 25
El servidor de aplicaciones ha pasado a ejecutar código de la capa de
persistencia
El objeto empleado ha dejado de desempeñar el rol de DTO y ahora pasa a
cumplir la funcionalidad de una Entidad EJB
El JpaRepositoryBean, que encapsula el EntityManager de JPA usará el EntityBean
empleado para sincronizar con la base de datos de forma transparente y recuperar la
verdadera Entidad del Empleado.
Al satisfacer la consulta empleado es otro tipo de objeto. Es una Entidad EJB
sincronizada con la base. Ahora, el ID ficticio que la capa de presentación le había
asignado al invocar al constructor ha desaparecido, se ha pisado, se ha
reemplazado por el verdadero ID que se encuentra persistido en la base, la
verdadera Entidad. Seguimos teniendo una Entidad EJB, pero ahora con su
identidad verdadera.
Cuando el método de Repository deje de ejecutarse y el EntityManager de JPA se
escape del alcance, pasaremos a estar nuevamente en la capa de servicio, y lo que
tendremos ahora, en nuestro poder, será la Entidad DDD completa, con la misma
identidad con la que la habíamos persistido en su momento. El Entity Bean pasa a ser
una Entidad DDD en el momento que escapa de la capa de persistencia, en el
momento en que se hace la separación con el Repository, en el momento en que se
hace lo que en JPA comúnmente se llama detach.
En la capa de servicio tenemos una Entidad DDD y no un DTO porque en
cualquier momento podemos invocar un método que pertenezca a
EmpleadoService, la parte procedural y transaccional de la Entidad.
Cuando el servicio termine de invocarse, el servidor de aplicaciones hace un commit de
la transacción de negocio que tenía abierta (o un rollback si algo salió mal). Entonces, la
Entidad DDD empleado se serializará y viajará por la red hasta la aplicación cliente que
la solicitó. Lo que el programador cliente recibe en el return del
recuperarPorNumeroLegajo es un DTO clon de la verdadera Entidad DDD. La
verdadera Entidad DDD nunca escapa de la capa de servicio. El DTO empleado
tiene una identidad sustituta, una copia de la verdadera Entidad DDD. Ya no es
más la Entidad completa, porque el programador cliente no podrá ejecutar ningún
método de la Entidad Empleado que no esté incluido en el DTO.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 26
Figura 2.11: Viaje de una Entidad a través de toda la arquitectura de SISTRANS
Este mismo escenario puede variar levemente si variamos la tecnología y/o la
arquitectura de la aplicación cliente. Por ejemplo, si la aplicación cliente estuviera
corriendo en el mismo servidor de aplicaciones que SISTRANS, en lugar de invocar la
ServiceLayer de forma remota (a través de un mecanismo de JNDI), podría hacerlo a
través de inyección de dependencia, de forma local, en cuyo caso el DTO no se
serializaría ni viajaría por la red. Pero, para los fines conceptuales es exactamente lo
mismo. Lo que viaja entre la capa de servicio y la aplicación cliente es el DTO.
Conclusión: La implementación de un objeto de dominio nunca viaja de una capa a
otra, en cambio los datos de negocio sí viajan, y recorren de punta a punta la
aplicación.
Aplicación Cliente
Capa de Servicio
Capa de Dominio
Capa de Persistencia
SISTRANS
empleado: Empleado (DTO)
empleado: Empleado (DTO)
EmpleadoServiceLayer.recuperarPorNumeroInterno()
empleado: Empleado (DTO)
empleado: Empleado (Entidad EJB)
Repository.findSingleResult()
JpaRepositoryBean.findSingleResult() mediante inyección de dependencia
entityManager.executeNamedQuery()
empleado: Empleado (Entidad EJB
con Identidad Verdadera)
empleado: Empleado (Entidad DDD)
detach()
empleado: Empleado (Entidad DDD)
mediante inyección de dependencia
empleado: Empleado (DTO
con la misma identidad
que la verdadera
Entidad DDD)
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 27
2.9. Capas de Presentación (Aplicaciones Cliente)
Las capas de Presentación que SISTRANS provee son simplemente DEMOs o
aplicaciones de ejemplo que muestran algunos posibles usos del sistema. Estos
proyectos no forman parte del producto. Cada empresa de transporte deberá programar
su propia capa de presentación en función a sus necesidades.
Las aplicaciones de ejemplo provistas por SISTRANS son:
sistrans-extractor.jar (para ejecutar en consola)
sistrans-procesos-reparaciones.jar (para desplegar en un contenedor de EJBs
como JBoss)
sistrans-aerolineas.war (para desplegar en un contenedor de Servlets como
Tomcat)
2.9.1. sistrans-extractor
El extractor consume únicamente el MP (Módulo Personal). Por ende tiene
dependencias con los paquetes:
sistrans-dto-personal.jar
sistrans-ejb-personal.jar
El extractor es una simple aplicación Java de consola, que consume datos de un sistema
externo de capacitación de empleados simulado y los vuelca en los empleados de
SISTRANS. Más adelante, en la sección de Diseño se explica en detalle cómo funciona
la comunicación con un Sistema Externo de Capacitación. Por ahora, alcanza con
entender que se trata de un código de ejemplo que muestra la forma en que se
recuperarían los empleados, adjuntando únicamente los paquetes involucrados en el MP
(Módulo Personal) y cómo se agregaría la información de Licencias y de Ítems de
Capacitación que se extrae de un sistema externo.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 28
Figura 2.12: Arquitectura de la aplicación cliente de sistrans-extractor
2.9.2. sistrans-procesos-reparaciones
El MREP (Módulo de Reparaciones) es un módulo fuertemente orientado a procesos.
Rigurosamente hablando este proyecto no es una capa de presentación. Si bien podemos
ejecutarlo desde una capa de presentación aislada de las demás, lo que esta aplicación
agrega es nueva lógica de negocio, que funciona de forma aislada al resto del producto
de SISTRANS.
En la sección de Análisis pudimos ver que el Módulo de Reparaciones está compuesto
por una Entidad Problema y un objeto de valor Entrada. Estas clases pueden
encontrarse en el dominio de SISTRANS y son exportadas en uno de los paquetes que
sistrans-procesos-reparaciones consume (sistrans-dto-reparaciones.jar). Luego, la
parte funcional del módulo se encuentra modelada por el paradigma de orientación a
procesos. En lugar de utilizar la orientación a objetos, como en el resto de los módulos,
vimos que la orientación a procesos podía expresar mejor la lógica de negocio para
reparaciones. Para esto se utilizó el motor de workflows de JBoss jBPM. Los workflows
se programan en un proyecto separado: sistrans-procesos-reparaciones, se
empaquetan y se despliegan en un servidor de aplicaciones separado de los jars de
SISTRANS.
Los procesos consumen el MREP (Módulo de Reparaciones). Si observamos las
dependencias entre los módulos de SISTRANS diagramada en esta misma sección en la
parte de Capa de Dominio, vemos que el MREP tiene dependencia con el MU (Módulo
Unidades) (ya que las reparaciones, revisiones, etc., se realizan sobre las Unidades) y
con el MP (Módulo Personal) (ya que las reparaciones, revisiones, etc. son realizadas
por los Técnicos empleados de este módulo). Por ende, los paquetes con los que los
workflows tienen dependencias son:
sistrans-dto-reparaciones.jar
sistrans-ejb-reparaciones.jar
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 29
En la capa de servicio de SISTRANS, se proveen servicios para iniciar los workflows,
iniciar problemas y demás, que eventualmente se disparan desde una capa de aplicación
y desde un Timer Service que SISTRANS provee para realizar revisiones periódicas.
Los workflows pueden ser desplegados en el mismo servidor de aplicaciones en que se
despliega sistrans-ejb, o pueden también desplegarse en otro. Las acciones de los
workflows se comunicarán con los servicios provistos por la capa de servicio de
reparaciones de forma remota, como si formaran parte de una capa de presentación. Por
eso tampoco podemos decir que sistrans-procesos-reparaciones es parte de la capa de
dominio de SISTRANS. En lo que a la arquitectura respecta, este proyecto es una
aplicación cliente como sistrans-extractor o sistrans-aerolineas.
La capa de servicio de reparaciones provee funcionalidad para iniciar procesos, guardar,
modificar y borrar problemas. La manipulación de los objetos de dominio del módulo se
hace exactamente igual que con cualquier otro módulo, a través de las Service Layers y
usando las Entidades EJBs como DTOs.
Los workflows son iniciados por SISTRANS, pero inmediatamente el control de los
mismos pasa a las manos del motor de workflows, quien asignará las tareas humanas a
los responsables (que son Empleados Técnicos del MP). El flujo de estados, la
persistencia y el control de los workflows está a cargo de jBPM. Los Empleados podrán
consultar sus tareas disponibles, escribir datos y comentarios, marcar como realizadas
las tareas, todo desde una capa de presentación. Una empresa interesada en explotar este
módulo, desarrollará una aplicación propia, bien customizada para sus necesidades, para
que los empleados puedan manipular de forma sencilla las tareas. Para lo que
SISTRANS respecta, los workflows pueden ser probados con la consola web que
provee jBPM (que también es una capa de presentación).
Figura 2.13: Diagrama de Colaboración no lineal a nivel de componentes para sistrans-procesos-reparaciones
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 30
2.9.3. sistrans-aerolineas
Sistrans-aerolineas es una aplicación web construida con JSF, RichFaces y Facelets.
Está preparada para desplegarse en un contenedor de Servlets, como Tomcat. Funciona
como DEMO de las principales funcionalidades que SISTRANS puede proveer para
una empresa de aerolineas.
La aplicación de aerolineas consume prácticamente todos los módulos. Por ende tiene
como dependencias los paquetes:
sistrans-dto.jar
sistrans-ejb-client.jar
La arquitectura de esta DEMO es la típica de una aplicación web construida con JSF.
Existe un conjunto de Controllers, asociados a páginas XHTML escritas casi por
completo con tags de JSF, RichFaces y Facelets. Estos tags, de forma transparente, se
convierten en HTML y/o JavaScript y muchos de ellos (casi todos los tags de
RichFaces) brindan funcionalidades AJAX para comunicarse con el servidor web sin
tener que refrescar la página. Los Controllers acceden a los servicios publicados en
sistrans-ejb-client, trayendo las implementaciones de las interfaces por JNDI, como las
demás aplicaciones cliente. Por supuesto, también hacen uso de los DTOs provistos por
sistrans-dto para transportar a través de la capa de servicio remota.
Esta aplicación expone la funcionalidad de forma muy simple, sin acceso de usuarios,
sin control de perfiles, sin diseño web sofisticado. La idea es que el código de esta
DEMO sirva de ejemplo para una empresa que necesite programar una aplicación web
comercial apuntando a distintos objetivos. Por ejemplo: en sistrans-aerolineas se puede
dar de alta Unidades o Itinerarios o Viajes, a la vez que se pueden comprar o reservar
Pasajes, hacer check-in de Pasajeros, o dar de alta Empleados, armar Tripulaciones y
demás. Claramente vemos que en esta DEMO todas las incumbencias están mezcladas,
sin distinguir tareas de administración, de tareas para clientes o tareas de compra/venta.
En una aplicación real, en general, todas estas incumbencias se programarán en
contextos separados, o hasta en distintas aplicaciones.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 31
3. Análisis
3.1. Lenguaje Ubicuo
B Bitácora: diario de navegación en el cual se hacen constar los sucesos relevantes que
sucedan en un Viaje.
C Categoría: Clase de la Ubicación. Por ejemplo: Cama, Semi-cama, Clase Turista,
Primera Clase, Club Cóndor.
Cliente: Toda Persona que compra un Pasaje o consulta por un Viaje.
E Equipaje: Carga o bulto que un pasajero lleva consigo en la Unidad durante un Viaje.
Es necesario que sea registrado antes de que el pasajero aborde la Unidad. Tipos de
Equipaje: Valija, Maletín, Bolso, Bolso de mano, Caja, Cofre u Otro.
Escala: Parada intermedia de un Viaje, donde algunos pasajeros pueden descender o
ascender a la Unidad. Origen o Destino intermedio de un Viaje.
Ejecutivo: Persona interesada en sacar provecho del Negocio.
Empleado: Toda aquella Persona que trabaje para la Empresa.
Empleado Tripulante: Todo aquella Persona que trabaje para la Empresa y que viaje a
bordo de un Viaje cumpliendo un rol.
H Historial (de Proceso): Para los procesos de Reparaciones y Problemas, es una lista de
Entradas en la que se puede seguir todo el recorrido que siguió un Problema a lo largo
de todo su ciclo de vida, con los comentarios opcionales de cada uno de los actores que
participaron en las tareas.
I Inspector de Calidad: Toda aquella Persona que trabaje para la Empresa y que esté
encargada de probar las reparaciones efectuadas por los Técnicos Especialistas.
Itinerario: Descripción de un conjunto de Tramos que forman todo el camino recorrido
o a recorrer en un Viaje.
P Pasaje: Boleto; representa la compra de un Viaje por un Cliente.
Pasajero: Persona, paquete o contenedor a transportar.
Personal: Todo empleado que trabaje para la Empresa.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 32
Problema: Anomalía detectada en la Unidad, que podría necesitar una Reparación.
R Recompensa: Premio que se otorga a un Cliente por su fidelidad para con la empresa, a
cambio de cierta cantidad de Puntos o una combinación de Puntos y dinero.
Reparación: Proceso para solucionar un Problema en una Unidad.
Revisión: Proceso para inspeccionar si una Unidad posee algún Problema y
solucionarlo.
Rol: Rol que puede desempeñar un Tripulante en un Viaje en un Tramo determinado. El
mismo Tripulante puede desempeñar más de un Rol en un mismo Viaje.
Ruta: Caminos que podrán ser transitados por las Unidades durante los Viajes.
S Segmento: Espacio entre dos Escalas de un Viaje. Entre dos Escalas puede haber varios
Tramos, pero sólo existe un Segmento entre ellas. Se utiliza para calcular Tarifas.
T Tarifa: Importe que se cobra por un servicio de transporte. Depende del origen, el
destino, la Categoría y el tipo de Pasajero.
Técnico: Toda aquella Persona que trabaje para la Empresa y que esté encargada de
inspeccionar las Unidades en busca de Problemas y realizar las Reparaciones necesarias
en las Unidades.
Técnico Supervisor: Técnico encargado de supervisar el ciclo de vida de un Problema.
Será responsable de N procesos de problemas y se encargará de asignar técnicos
especialistas para la reparación, supervisar sus tareas y asignar inspectores de calidad
para las pruebas.
Técnico Especialista: Técnico encarga de la reparación de un Problema. Será
responsable de N procesos de reparaciones.
Terminal: Puntos de partida o llegada de Pasajeros. Tipos de Terminal: Aeropuerto,
Terminal de micros, Terminal de carga, Puerto marítimo. La Terminal se encuentra en
una Localización.
Trámite: Proceso burocrático que un Cliente debe realizar para viajar de un sitio a otro.
Tramo: Fragmentos en los que puede dividirse una Ruta. Los Tramos formarán parte
de los itinerarios.
Tripulante: Empleado Tripulante que cumple uno o varios Roles en un Viaje. Un
Tripulante estará compuesto por un Empleado Tripulante, más un conjunto de Roles que
desempeña.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 33
U Ubicación: Posición donde puede ubicarse un Pasajero. Tipos de Ubicación: Butaca,
Asiento, Superficie, Volumen. Ubicación es parte de Unidad. Una Ubicación pertenece
a una determinada Categoría.
UbicacionEstado: Valor transaccional cuyo ciclo de vida corresponde al de un Viaje.
Cada Ubicación Estado apunta a una Ubicación de una determinada Unidad, e indica su
disponibilidad (DISPONIBLE u OCUPADO) y su ubicación física para que una vista
pueda dibujar el mapa de Ubicaciones del Viaje.
Unidad: Vehículo, transporte. Tipos de Unidad: MICRO, TREN, BARCO, AVION,
CAMION, AUTO, VAGON, LOCOMOTORA.
Unidad de Viaje: Valor transaccional cuyo ciclo de vida corresponde al de un Viaje.
Cada Unidad de Viaje sirve para asociar una Unidad con su Ubicación
Estado correspondiente a un Viaje.
V Viaje: Transporte de Pasajeros desde un Origen a un Destino por medio de una o
más Unidades.
W Waypoint: Juego de coordenadas para ubicar puntos de referencia tridimensionales
utilizados en la navegación. Determinación de un lugar mediante sus coordenadas
geográficas y un nombre.
3.2. Módulos
3.2.1. Módulo de Unidades (MU)
3.2.1.1. Domain Vision Statement
Control total de las Unidades de Transporte que forman parte de la empresa. Se llevará
cuenta de las:
Unidades que forman parte de la Flota de viajes regulares
Unidades que sirven para alquilar a terceros
Unidades que sirven de soporte al negocio
3.2.1.2. Especificación
La información que cada unidad deberá incluir será:
Nombre: String
Descripción: String
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 34
Número de Interno: Integer
Matrícula: String
Marca: String
Modelo: String
Nacionalidad: String
Ubicaciones: List<Ubicacion>
Año de Fabricación: Date
Año de Incorporación a la Flota: Date
Valor Monetario: Money
Dispone de GPS: Boolean
Distancia Recorrida: Magnitude
Velocidad Máxima: Magnitude
Velocidad de Crucero: Magnitude
Calefacción: Boolean
Aire Acondicionado: Boolean
Cantidad de Televisores: Integer
Disponible para Alquiler: Boolean
Disponible para Uso Interno: Boolean
Habilitada: Boolean (se utiliza para indicar si la Unidad puede realizar viajes o
está en reparación)
Cantidad de Motores: Integer
Variables: Set<Variables>
Consumo de combustible: Magnitude
Capacidad de combustible: Magnitude
Carga máxima: Magnitude
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 35
Figura 3.1: Diagrama de Clases del Módulo Unidades (MU)
<<Entity>>
Unidad
-nombre: String
-descripcion: String
-numeroDeInterno: Integer
-matricula: String
-marca: String
-modelo: String
-nacionalidad: String
-anioFabricacion: Year
-anioIncorporacion: Year
-valorMonetario: Money
-tieneGPS: Boolean
-distanciaRecorrida: Magnitude
-velocidadMaxima: Magnitude
-velocidadDeCrucero: Magnitude
-calefaccion: Boolean
-aireAcondicionado: Boolean
-cantTelevisores: Integer
-disponibleParaAlquiler: Boolean
-disponibleParaUsoInterno: Boolean
-cantMotores: Integer
<<Entity>>
UnidadTerrestre
-cantRuedas: Integer
-chasis: String
-motor: String
-carroceria: String
-caja: String
-cajaAtomatica: Boolean
-velocidades: Integer
-suspension: String
<<Entity>>
UnidadMaritima
-eslora: Magnitude
-manga: Magnitude
-potencia: Magnitude
-cantAutos: Integer
<<Entity>>
Camion
-distanciaEntreEjes: Magnitude
-largoTotal: Magnitude
-anchoTotal: Magnitude
-voladizoDelantero: Magnitude
-voladizoTrasero: Magnitude
-radioDeGiro: Magnitude
<<Entity>>
Vagon
<<Entity>>
Locomotora
-tipoLocomotora: String
-potencia: Magnitude
-cargaMax: Magnitude
-diametroRuedas: Magnitude
-velocidadDeAdherencia: Magnitude
<<Entity>>
UnidadFerroviaria
-peso: Magnitude
<<Entity>>
UnidadAerea
-longitud: Magnitude
-envergadura: Magnitude
-alcanceDeVuelo: Magnitude
-techoDeServicio: Magnitude
-techoAbsoluto: Magnitude
<<Entity>>
Auto
<<ValueObject>>
Ubicacion
-tipoUbicacion: TipoUbicacion
<<ValueObject>>
Categoria
-nombre: String
<<ValueObject>>
Variable <<Entity>>
VariableType
*
1
11
*
1
1
*
<<Entity>>
Micro
<<Entity>>
Barco
<<Entity>>
Avion
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 36
3.2.2. Módulo de Rutas (MR)
3.2.2.1. Domain Vision Statement
Control total de las Rutas por las cuales se desplazarán las Unidades en los Viajes.
3.2.2.2. Especificación
La información que cada ruta incluye es:
Nombre: String
Dificultad: Dificultad (ALTA, MEDIA, BAJA)
Jurisdicción: Jurisdicción
Observaciones: String (Consideraciones de tránsito: observaciones tales como
precauciones al transitar cierto tramo, presencia de puntos de interés, etc.)
Tramos: List<Tramos>
Para entender mejor cómo está construido el concepto de Ruta en SISTRANS, primero
tenemos que ver otros dos conceptos muy importantes: Waypoints y Tramos. El
primero no es un concepto exclusivo de las rutas, ya que en sí pertenece a un
subdominio genérico que usa el framework de Domain-Driven Design. El segundo, es
un concepto exclusivo del módulo Rutas.
3.2.2.3. Waypoints
Como acabamos de explicar, los Waypoints se encuentran en un subdominio genérico
del framework de DDD. Un waypoint es un juego de coordenadas para ubicar
puntos de referencia tridimensionales utilizados en navegación. Sirve para
determinar unívocamente un lugar mediante sus coordenadas geográficas y un
nombre.
Un waypoint incluye:
Nombre: String
Descripción: String
Latitud: Angle (Los ángulos son Objetos de Valor que contienen la
información de la coordenada: grados, minutos, segundos y hemisferio: norte,
sur, este, oeste.)
Elevación: Magnitude
Los waypoints están presentes en todo el modelo de dominio de SISTRANS.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 37
3.2.2.4. Tramos
Los Tramos son los fragmentos ordenados en los que puede dividirse una Ruta. Básicamente se tratan de segmentos bidimensionales que incluyen un waypoint en cada
extremo y un conjunto de Tramos ordenados constituye una Ruta. Tanto las Rutas
como los Waypoints son Entidades.
Un Tramo incluye:
Nombre: String
Descripción: String
Comienzo: Waypoint
Fin: Waypoint
Longitud: Magnitude
Orden: Integer (orden relativo a la ruta)
Ruta (una referencia cruzada a la Ruta para poder satisfacer la consulta de a qué
Ruta pertenece el Tramo con mayor facilidad)
Figura 3.2: Diagrama de Clases del Módulo Rutas (MR)
Los Tramos se usan también para formar los Itinerarios del MV (Módulo de Viajes).
Un Itinerario básicamente es un conjunto de Tramos14
.
3.2.2.5 Agregaciones
Es importante aclarar que Ruta y Tramo no forman parte de una agregación DDD, dado
que ambas son Entidades y Tramo puede utilizarse independientemente de Ruta. En
cambio, entre Waypoint y Angle sí tenemos una agregación, ya que no tiene sentido
modificar un objeto Angle si no es a través de su Waypoint.
Tramo puede existir tranquilamente sin Ruta. De hecho, si el módulo MR fuera una
agregación, aunque parezca contra-intuitivo, Tramo sería la entidad raíz. En un
dominio como el de los micros, por ejemplo, las Rutas serían las carreteras de asfalto y
los Tramos podrían comenzar y terminar en diferentes cruces con distintas Rutas, o
diferentes paraderos comunes. En un dominio como el de la aeronáutica comercial, el
concepto de Ruta tal vez no tendría sentido por sí solo, ya que en el aire, Rutas y
14 Ver más adelante Diagrama de Clases del Módulo Viajes (MV)
<<Entity>>
Waypoint
-name
-elevation
<<Entity>>
Tramo
-nombre
-descripcion
-longitud
-orden
<<ValueObject>>
Angle
-degrees
-minutes
-seconds
-hemisphere
<<Entity>>
Ruta
-nombre
-jurisdicción
-longitud
-orden
*
comienzo
1
*
fin
1
11 *
1
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 38
Tramos suelen ser sinónimos. En ese caso, lo conveniente es no usar la Entidad Ruta
y acceder directamente a los Tramos.
En el módulo de Viajes (MV) podemos ver que las Entidades realmente importantes son
los Tramos. Los Itinerarios tienen una lista de Tramos. Por otra parte, las Escalas de un
Viaje están determinadas por Terminales, que las Terminales a su vez están
determinadas unívocamente por Waypoints. Las Tarifas también se determinan por
Terminales. Conclusión: La Entidad Ruta sirve más como una referencia que como un
dato útil; la implementación de un negocio puede prescindir tranquilamente de ella.
3.2.3. Módulo de Personal (MP)
3.2.3.1. Domain Vision Statement
Control total del Personal de la empresa.
3.2.3.2. Especificación
El Empleado guardará la siguiente información genérica:
Nombre: String
Segundo Nombre: String
Apellido: String
DNI: Integer
Domicilio: String
Ciudad: String
Código Postal: String
País: String
Teléfono móvil: String
Teléfono de la casa: String
Teléfono del trabajo: String
Teléfono del fax: String
Otro teléfono: String
Fecha de nacimiento: Integer
Fecha de incorporación como empleado a la empresa: Date
Observaciones
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 39
Además, los Empleados contarán con la siguiente información:
Número de Legajo: Integer
Licencias: En caso de transporte terrestre, por ejemplo, número de licencia de
conducir y reglas de la licencia: por qué áreas está habilitado para conducir, qué
tipo de vehículos. En el caso de una aerolínea podría ser la licencia de piloto, de
operador de radiocomunicaciones, etc.
Legajo de Capacitación: Set<Item de Capacitación> (Exámenes rendidos,
cursos tomados, cursos dictados, calificaciones obtenidas.)
Roles habilitados: Set<Rol>. Indica los roles que el Empleado puede asumir en
algún Viaje.
Un Empleado puede ser:
Empleado Tripulante: Todo aquel empleado que trabaje para la Empresa y que
viaje a bordo de un Viaje cumpliendo un Rol. En otras palabras, se trata de los
Empleados que pueden formar parte de la Tripulación de un Viaje.
Técnico: Son los encargados de inspeccionar las unidades en busca de
problemas y de reparar los Problemas que las mismas puedan tener. Entre los
Técnicos se encuentran:
o Técnicos Supervisores: son los encargados de verificar la existencia de
un Problema en una Unidad y de elegir y asignar a los Técnicos
Especialistas necesarios para realizar la reparación del mismo.
o Técnicos Especialistas: tienen conocimientos en un área mecánica
específica de las Unidades y son los encargados de realizar reparaciones
en las mismas.
o Inspectores de Calidad: son los encargados de probar las Unidades tras
la reparación de un Problema y verificar que la reparación se haya hecho
correctamente.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 40
Figura 3.3: Diagrama de Clases del Módulo Personal (MP)
El objeto de valor Tripulante no pertenece a este módulo, pero fue incluido en el
diagrama de clases para mostrar una visión más general de las relaciones. Tripulante es
relativo al módulo Viajes, es transaccional, y contiene la lista de roles que el
Empleado Tripulante (Entidad) desempeña durante ese Viaje.
3.2.4. Módulo de Clientes (MC)
3.2.4.1. Domain Vision Statement
Control total de los Clientes que posee la empresa. Se llevará cuenta de los clientes que:
Realizaron algún viaje con la empresa.
Son personas conocidas de clientes que realizaron viajes con la empresa.
3.2.4.2. Especificación
La información que cada cliente deberá incluir será:
Nombre: String
Segundo Nombre: String
Apellido: String
DNI: Integer
Pasaporte: Integer
<<Entity>>
Persona
Empleado
-numeroLegajo
<<ValueObject>>
Licencia
-numeroLicencia
-tipoLicencia
-tipoUnidad
<<ValueObject>>
ItemDeCapacitacion
-fecha
-nombre
-descripcion
-lugar
-calificacion
<<Entity>>
Rol
-nombre
-descripcionFunciones
-descripcionResponsabilidades
*
-licencias
1
*
-legajoCapacitacion
1
*
-rolesHabilitados
1
EmpleadoTripulante
-horasDeViaje
<<ValueObject>>
Tripulante
*
1
1
*
Tecnico
InspectorDeCalidadTecnicoSupervisor TecnicoEspecialista
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 41
Dirección: String (Domicilio del cliente)
Compañía: String (Empresa a la que pertenece el cliente, en el caso que
corresponda)
Ciudad: String (Ciudad de domicilio del cliente)
Código Postal: String
País: String
Zona horaria: String (Huso horario del lugar de domicilio del cliente)
E-Mail: String
Teléfonos: List<String>
Fecha de nacimiento: Integer
Fecha de incorporación como cliente de la empresa: Integer
Pregunta secreta: String (Para recuperar su contraseña de usuario en caso de
perderla)
Respuesta secreta: String (Para recuperar su contraseña de usuario en caso de
perderla)
Clase de cliente: String (Para poder especificar si es un cliente preferencial
(VIP))
Fecha de baja automática: Integer (Se puede especificar una fecha de baja para
los clientes ocasionales)
Moneda preferida: Currency (Moneda con la que se maneja el cliente)
Idioma preferido: String (Idioma con el que se principalmente se comunica el
cliente)
Observaciones: String (Comentarios extra que se quieran guardar en el sistema)
Contactos: List<Contacto> (Listado de personas que el cliente conoce, para que
se le puedan enviar publicidad y/o ofertas de viajes para visitarlas).
3.2.4.3. Programa de recompensas
El sistema permite que cada Cliente acumule puntos (también conocidos como ―millas‖
en las aerolíneas) para ser canjeados luego por recompensas, como es costumbre en
ciertas empresas de transporte para premiar la fidelidad de sus clientes.
Existe en el sistema un catálogo con las distintas recompensas disponibles para los
clientes, con un conjunto de Valores por los cuales se puede obtener dicha recompensa.
Estos valores pueden ser combinaciones de puntos y/o dinero. Por ejemplo:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 42
Recompensa: Viaje dentro de Argentina, categoría Económica, en temporada
baja.
Valor: la recompensa puede ser obtenida canjeando uno de los siguientes:
o 20000 puntos.
o 10000 puntos + ARS 200.
o 5000 puntos + ARS 500.
Nota: en esta versión del sistema no se soporta el vencimiento de los puntos adquiridos
por un Cliente.
3.2.5. Módulo de Reparaciones (MREP)
3.2.5.1. Domain Vision Statement
Control total de los procesos de Reparación de las Unidades, guardando la información
requerida por cada proceso y las acciones y tareas que componen el flujo de trabajo.
3.2.5.2. Especificación
El módulo de Reparaciones administra el ciclo de vida de los Problemas que puedan
ocurrirle a una Unidad. Los Problemas son anomalías detectadas en la Unidad, que
podrán necesitar (o no) una Reparación. Cuando se da de alta un Problema,
dependiendo de la gravedad o severidad del mismo, la Unidad podrá seguir siendo
utilizada para nuevos Viajes o no. Un Técnico Supervisor se encargará de revisar el
problema e inhabilitar la Unidad si es necesario. Luego, emitirá un Pedido de
Reparación, asignando una lista de Técnicos Especialistas que se encargarán de la
Reparación. Cuando los técnicos especialistas terminen con su labor, el técnico
supervisor volverá a inspeccionar la Unidad para verificar que ésta esté lista para enviar
a Calidad. Cuando el Problema esté listo para ser probado, asignará un Inspector de
Calidad, quien hará las pruebas necesarias para verificar que el Problema no se sigue
manifestando. Una vez que la Unidad salga de Calidad y el inspector afirme que el
Problema fue resuelto, el técnico supervisor podrá cerrar el problema.
A continuación, podemos ver el flujo de trabajo recién explicado, en lenguaje BPM:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 43
Figura 3.4: Workflow de Problemas
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 44
El proceso de Reparaciones es llevado a cabo por un Técnico Especialista. El técnico
revisa el problema y determina si realmente necesita reparación, si él está capacitado
para repararlo y tiene las herramientas necesarias, y si necesita materiales. En caso de
necesitar materiales está autorizado a emitir un Pedido de Materiales y esperará a que
los materiales lleguen para comenzar con la reparación.
Figura 3.5: Workflow de Reparaciones
En caso de que el técnico determine que no puede reparar el Problema o el Problema no
necesita reparación, dejará un comentario en la tarea de Revisión para que el técnico
supervisor lo lea y determine si debe asignar a un nuevo técnico o no.
Como se puede ver, este módulo está fuertemente orientado a Procesos, por eso se usará
una herramienta de modelado de BPM (Business Process Management) para que el
proceso sea fácil de modificar y se pueda encapsular el flujo de trabajo.
3.2.5.3. Entidades
La Entidad Problema existe en el modelo. Un Problema se creará en la ejecución del
primer nodo del proceso de problemas y se cerrará en la ejecución del último nodo del
mismo proceso.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 45
Los Problemas contienen los siguientes datos:
Código
Descripción
Fecha de creación
Unidad en la que se manifiesta el Problema
Prioridad
Severidad
Tiempo estimado de Reparación
Técnico Supervisor responsable del Problema
Lista de Técnicos Especialistas responsables de la Reparación
Persona que reportó el Problema (Iniciador)
Número de Pedido de Reparación asociado
Historial del Problema: Proceso del que salió, Tarea que se ejecutó,
Responsable, Comentario del Responsable
El iniciador del Problema puede ser:
Un Técnico que acaba de efectuar una revisión de rutina
Un Técnico que estaba reparando otro Problema
Un Empleado Tripulante que detectó el Problema en su último Viaje
3.2.5.4. Revisiones Periódicas
Hay además un tercer workflow que se ejecutará de forma periódica si el TimerService
fue configurado correctamente en SISTRANS.
Para eso, SISTRANS cuenta con una Service Layer en la capa de servicio que funciona
con el Mecanismo de Programación de Tareas explicado en la sección de Diseño, en el
cual se puede configurar la periodicidad con la que se lanza el proceso. En el mismo
archivo de propiedades, servicio.properties, se puede especificar también el número de
legajo del Técnico Supervisor encargado de llevar a cabo la Revisión.
El proceso de Revisión es simple. Comienza con un Técnico Supervisor que revisará
la unidad asignada y determinará si la misma tiene problemas o no. Si se encontraron
Problemas, asignará a una lista de Técnicos Supervisores para que se encarguen de la
administración del Problema, invocando al workflow de Problemas.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 46
Figura 3.6: Workflow de Revisiones
Una vez que los Técnicos Supervisores concluyeron con sus respectivos procesos de
Problemas, el Técnico Supervisor asignado al proceso de Revisiones, cerrará la
revisión y dará fin al workflow.
3.2.6. Módulo de Viajes (MV)
3.2.6.1. Domain Vision Statement
Control total de los Viajes realizados y por realizarse.
3.2.6.2. Especificación
La información que cada Viaje deberá incluir será:
Tripulación: List<Tripulante>
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 47
Unidades de Viaje: List<UnidadDeViaje>
Ubicaciones: List<Ubicacion>
Origen: Terminal
Destino: Terminal
Rutas Principales: Itinerario
Rutas Alternativas: ItinerarioAlternativo
Servicios brindados a bordo del Viaje: List<Servicio>
Servicios brindados previos al abordaje (frecuentemente en la Terminal): List<Servicio>
Escalas: List<Escala>
Tarifas: List<TarifaDeSegmentoDeViaje>
Estado: puede ser:
o Programado: el Viaje fue ingresado en el sistema y se realizará en los
tiempos especificados.
o Demorado: el Viaje no se realizará en el tiempo especificado. Se debe
modificar para realizarlo.
o En ruta: el Viaje se está realizando.
o Realizado: el Viaje ha finalizado con éxito.
o Cancelado: no se realizará el Viaje.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 48
Figura 3.7: Diagrama de Clases del Módulo Viajes (MV)
En el caso de una empresa ferroviaria, el viaje debe incluir también la información de
locomotora y vagones que componen la formación, con sus respectivos números de
identificación. Tanto la locomotora como cada vagón se deberán cargar en el
Módulo Unidades como Unidades independientes, si se necesita tal grado de
control.
<<Entity>>
Viaje
-nombre
-descripcion
-estado
-motivoCancelacion
-costosVarios
<<ValueObject>>
Tripulante
<<Entity>>
Empleado
<<Entity>>
Rol
-nombre
-descripcionFunciones
-descripcionResponsabilidades
<<Entity>>
Tramo
-nombre
-descripcion
-longitud
-orden
*
1
1
**
*
<<Entity>>
Terminal
-nombre
-tipoTerminal
-zonaHoraria
-pais
-provincia
-ciudad
-sector
<<Entity>>
Itinerario
-nombre
-descripcion
1
*
<<ValueObject>>
Servicio
-nombre
-descripcion
-costoPorPasajero
1
*
<<Entity>>
Ruta
-nombre
-jurisdicción
-dificultad
-observaciones
<<Entity>>
Unidad
*
-aBordo
*
*
-previoAlAbordaje
*
<<Entity>>
Waypoint
-name
-latitude
-longitude
-elevation
1
1
<<Entity>>
UbicacionEstado
-disponibilidad
-ubicacionFisica
<<ValueObject>>
Categoria
-nombre
1
-comienzo
1
*
-fin
1
1
*
<<ValueObject>>
ItinerarioAlternativo
-orden
*
1
<<ValueObject>>
UnidadDeViaje
-costoUnitarioCombustible
-unidadDeCombustible
1
*
<<ValueObject>>
Ubicacion
-tipoUbicacion
*
1
1
* 1
1
*
1
*
1
<<ValueObject>>
Escala
-orden
-horaSalida
-horaLlegada
1
*
*
1
<<ValueObject>>
ItemDeBitacora
-fecha
-asunto
-desarrollo
1
*
<<ValueObject>>
TramoDeItinerario
-orden
*
1
-habilitado
*
*
<<Entity>>
TarifaDeSegmento
-nombre
-validaDesde
-validaHasta
<<ValueObject>>
TarifaDeSegmentoDeViaje
-orden
<<ValueObject>>
Tarifa
-tipoPasajero
-importe
-impuestos
-extras
1
*
*
1
1
*
1-origen
1
1
1
1
-destino
1
1
*
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 49
El sistema permitirá la realización de un Viaje utilizando varios vehículos (ya sea en
forma paralela, en el caso de contingentes que no quepan en un solo vehículo, o en
serie, haciendo trasbordo en puntos intermedios de la ruta).
El sistema brindará la posibilidad de establecer políticas que determinen la realización
de un viaje. En caso de no cumplirse estas condiciones, el viaje podrá no realizarse.
También se podrán configurar reglas o restricciones a cada Unidad, Tripulación y/o
Personal. Usando la información de las Unidades, de los Conductores y considerando
las reglas especificadas, el sistema podrá sugerir tripulaciones y asignarlas a distintos
viajes, proponiendo calendarios tentativos.
Al comenzar un Viaje, los Conductores podrán consultar los Itinerarios disponibles y/o
sugeridos por el sistema y, dependiendo de ciertas condiciones actuales (disponibilidad
del camino, pronóstico meteorológico, etc.) configurarán el Itinerario principal y los
alternativos adecuadamente. A los Itinerarios alternativos se les podrá asignar una
prioridad y así se podrán ordenar por orden de preferencia.
Las autoridades competentes tendrán la posibilidad de consultar por un Viaje específico,
donde el Itinerario principal y los alternativos elegidos por cada Conductor se mostrarán
en detalle en forma de reporte, con posibilidad de archivar, imprimir, enviar por email,
etc.
Una persona (no es necesario que sea un Cliente registrado) tendrá la posibilidad de
acceder por Internet con el uso de una contraseña especial emitida con el Pasaje. Una
vez ingresada la clave, podrá consultar la siguiente información:
Número de Viaje.
Horario de partida / Horario de llegada.
Estado.
Geo-ubicación actual (si la Unidad cuenta con GPS).
Rutas Principales.
Rutas Alternativas.
Estado del envío (exclusivo para traslado de paquetes).
3.2.6.3. Escalas
Se pueden especificar distintas paradas intermedias durante un viaje, para que algunos
pasajeros puedan bajar antes de llegar al destino, subir luego de la salida, o ambos.
Cada una de las escalas de un viaje está unida virtualmente por un segmento de viaje.
Esto significa que entre dos escalas de un viaje pueden existir varios Tramos físicos por
los que una Unidad transita para poder llevar a cabo el Viaje, pero existe sólo un
Segmento o ―espacio entre ambas‖.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 50
De esta manera, el precio del Viaje para el usuario no depende de cómo la empresa
realiza el viaje, sino del origen y el destino. Esto es muy útil a la hora de utilizar algún
Itinerario alternativo ante alguna eventualidad.
3.2.6.4. Tarifas
Existe un listado ordenado de tarifas entre cada una de las Escalas del Viaje. Cada tarifa
incluye los importes de los pasajes de al menos cada tipo de Categoría (Ej.: Primera,
Económica, etc.) que posea la Unidad del Viaje, para cada tipo de Pasajero que realice
el viaje (Adulto mayor, Adulto, Menor, Menor que viaja solo o Infante). Para calcular el
valor de un Pasaje, basta con sumar los importes de los Segmentos desde el origen hasta
el destino elegido, para una Categoría y un tipo de Pasajero dados.
3.2.6.5. Cálculo del valor de un Viaje
Para calcular el precio que debe pagar un pasajero se considera lo siguiente:
Escalas de origen y destino en las cuales el pasajero embarcará y desembarcará.
Categoría.
Tipo de pasajero.
Por ejemplo, si un Viaje se realiza de A hasta B, sin escalas intermedias, el valor será el
indicado por la Tarifa de Segmento del Viaje perteneciente.
Si, en cambio, un Viaje se realiza de A hasta C, con una escala en B, y el Cliente desea
ir de A hasta C, el valor será el indicado por la suma de las Tarifas de Segmento del
Viaje de A hasta B y de B hasta C.
3.2.6.6. Costos
Junto con la información relacionada a las Unidades que se utilizarán en el viaje, se
guardan también datos que hacen referencia a los costos directos que implican la
realización del mismo. Estos costos se dividen en tres grupos:
Costos por consumo de combustible.
Costos por servicios.
Otros costos (personal, mantenimiento, etc.).
3.2.6.7. Cálculo del costo por consumo de un Viaje
Para el costo por el consumo de combustible en un Viaje se considera el valor del
combustible al momento de realizarse el viaje, para que de esta manera quede guardado
en el sistema el costo real al momento de la inversión. Si la empresa compra
combustible al por mayor, se puede usar el valor por unidad de combustible que se haya
pagado en ese momento. Las unidades de medida disponibles para el precio del
combustible son:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 51
Moneda / Kilogramo de combustible
Moneda / Tonelada de combustible
Moneda / Litro de combustible
Moneda / Galón de combustible
Para la Moneda se puede usar cualquiera de las establecidas en el estándar ISO 421715
.
También se considera la longitud del Itinerario a seguir o seguido por la Unidad, y el
consumo de la misma. En el caso de que el Viaje sea realizado por más de una Unidad,
se obtiene el valor del consumo de cada una para el cálculo del costo. (Actualmente se
considera que las unidades viajan en paralelo). El precio de la unidad de combustible
anteriormente descrito debe expresarse de acuerdo a cómo se exprese el consumo de
una Unidad, en alguna de estas unidades de medida:
Unidad de consumo Precio unitario de combustible
Kilómetros / Litro Moneda / Litro
Millas / Galón Moneda / Galón
Litros / Hora Moneda / Litro
Galones / Hora Moneda / Galón
Kilogramos / Hora Moneda / Kilogramo
Toneladas / Hora Moneda / Tonelada
En el caso en que la unidad de consumo sea expresada en función de una medida de
capacidad, el costo se calcula como:
Cd
C comb
total
C q
Donde:
Cc : Costo por consumo.
dtotal : Distancia total del itinerario del Viaje.
q : Consumo de combustible de la Unidad del Viaje.
Ccomb : Costo por unidad de combustible (expresado en Moneda / Litro ó
Moneda / Galón, según corresponda).
En el caso en que la unidad de consumo sea expresada en función de una medida de
peso, el costo se calcula como:
15 http://es.wikipedia.org/wiki/ISO_4217
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 52
CqtC
vd
t
combviajeC
crucero
total
viaje
Donde:
tviaje : Tiempo de viaje.
dtotal : Distancia total del itinerario del Viaje.
vcrucero : Velocidad crucero de la Unidad del Viaje.
Cc : Costo por consumo.
q : Consumo de combustible de la Unidad del Viaje.
Ccomb : Costo por unidad de combustible (expresado en Moneda / Kilogramo ó
Moneda / Tonelada, según corresponda).
3.2.6.8. Cálculo del costo por servicios de un Viaje
Para el cálculo del costo por servicios se consideran los servicios previos al abordaje y
los que se proveen a bordo durante el viaje. Para todos ellos, siempre se utiliza el costo
por pasajero indicado en el Servicio y la cantidad de pasajeros que realizaron el viaje.
De esta manera, se puede calcular el costo por servicios con la siguiente fórmula:
nCCC pasajerosbordoaspreviossS ..
Donde:
Cs : Costo por servicios.
Cs. – previos : Costo por servicios previos al abordaje.
Cs. – a-bordo : Costo por servicios a bordo.
npasajeros : Cantidad de pasajeros en el viaje.
3.2.6.9. Otros costos
En el caso de los costos incurridos en el Viaje y que escapan del alcance del sistema, se
guarda un dato de costos varios junto con el Viaje. Ejemplos de estos costos pueden ser
los relacionados al sueldo de la tripulación, revisiones de rutina, insumos, etc.
considerados para cada viaje en particular.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 53
3.2.6.10. Cálculo de las ganancias de un Viaje
Para calcular las ganancias obtenidas por la realización de un viaje se toma la suma de
los ingresos por ventas de pasajes para el viaje y se restan todos los costos asociados al
mismo (combustible, servicios y personal).
3.2.6.11. Sugerencia de tripulantes
El sistema provee la funcionalidad de sugerir una tripulación posible para asignar a un
Viaje a realizarse. Para ello se deben indicar los roles necesarios, el origen y fecha del
nuevo Viaje, y una fecha mínima desde la cual los empleados sugeridos deben haber
llegado a la terminal donde se originará el nuevo Viaje.
Para encontrar los Empleados tripulantes que pueden formar parte de la tripulación, el
sistema busca entre los Empleados que hayan llegado (o llegarán en un futuro) al origen
del nuevo viaje, dentro de las horas indicadas, los que sean capaces de cumplir alguno
de los roles especificados (según sus ―roles habilitados‖).
Para la sugerencia se considera el último viaje asignado al Empleado tripulante, que no
haya sido cancelado. De esta manera, se asegura que luego de este viaje planificado o
realizado el Empleado no tiene otra asignación, con lo cual es libre de ser elegido para
cualquier otro Viaje.
En este proyecto no se considera para la sugerencia algún período de descanso para el
Empleado. De hecho, un operador del sistema no debe aceptar la sugerencia tal como
fuera indicada, sino que debería evaluar la cantidad de horas de trabajo luego del último
período de descanso para decidir si incluir o no al Empleado.
3.2.7. Módulo de Pasajes (MPAS)
3.2.7.1. Domain Vision Statement
Control total de la información referida a los pasajes vendidos y soporte procedural al
proceso de venta y reservación de ubicaciones para un Viaje.
3.2.7.2. Especificación
El sistema administrará la información referida a los Pasajes vendidos. Los Pasajes
contendrán los siguientes datos:
Datos del Cliente
Nombre y Apellido (podrían o no ser iguales a los del Cliente. De esta manera,
un Cliente puede reservar o comprar pasajes para otras personas); idealmente
serán el nombre y el apellido del Pasajero
Datos del Viaje
Datos de la Unidad del viaje
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 54
Ubicación: UbicacionEstado
Sube en: Escala
Baja en: Escala
Estado: [ RESERVADO | VENDIDO | CANCELADO ]
Importe neto del Viaje (calculado utilizando la Tarifa del viaje)
Descuentos e Impuestos Aplicados (sacados del Sistema de Facturación)
Forma de Pago
Punto de Venta donde se emitió el boleto
Urgencia de Entrega (exclusivo para traslado de paquetes)
Peso (exclusivo para traslado de paquetes)
Seña (si el Pasaje fue RESERVADO con una seña): Money
Tipo de Pasajero: tipo de pasajero al cual pertenece el pasaje. Puede ser adulto,
adulto mayor, menor, infante, menor que viaja solo u otro tipo. Dependiendo del
tipo de pasajero se calcula la tarifa correspondiente.
Atención especial: Boolean (indica si el pasajero requiere alguna atención o
espacio especial, debido a alguna discapacidad).
Fecha de Expiración: Date (día en que vence la reserva si el Pasaje no es
confirmado)
Fecha de emisión: Date
Equipajes: List<Equipaje> (una colección de equipajes que transportará el
pasajero y de los que eventualmente deberá hacer check-in al abordar)
Fecha de Cancelación: Fecha en la que fue cancelado el Pasaje (si el pasaje está
en estado CANCELADO)
Motivo de Cancelación: Motivo por el que fue cancelado el Pasaje (si el pasaje
está en estado CANCELADO)
Código: código aleatorio de 6 caracteres auto-generado; puede ser usado como
el Record Locator que utilizan algunas empresas para realizar el check-in de
pasajeros
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 55
Figura 3.8: Diagrama de Clases del Módulo Pasajes (MPAS)
PasajeServiceLayer
+reservar(pasaje:Pasaje)
+reservar(pasajes:List<Pasaje>)
+comprar(pasaje:Pasaje)
+comprar(pasajes:List<Pasaje>)
+confirmar(pasaje:Pasaje)
+confirmar(pasajes:List<Pasaje>)
+cancelar(pasaje:Pasaje,motivoCancelacion:String)
<<Entity>>
Pasaje
-nombre: String
-apellido: String
-tipoPasajero: TipoPasajero
-estado: EstadoPasaje
-importeNeto: Money
-descuento: Money
-senia: Money
-formaPago: String
-puntoVenta: String
-atencionEspecial: Boolean
-urgencia: TipoUrgencia
-peso: Magnitude
-fechaExpiracion: Date
-fecha: Date
<<Entity>>
Viaje
<<Entity>>
Cliente
1
*
1
*
<<Entity>>
UbicacionEstado1
1
<<ValueObject>>
Escala
-horaLlegada: Date
-horaSalida: Date
<<Entity>>
Terminal1
*
subeEn 1
*
bajaEn 1
*
<<ValueObject>>
UnidadDeViaje*
1
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 56
3.2.7.3. Ciclo de Vida de un Pasaje
Figura 3.9: Diagrama de Estados de un Pasaje
Un Pasaje representa la compra de un Viaje realizada por un Cliente. El Pasaje puede
ser comprado o reservado previamente. Para que un Cliente reserve un Pasaje se
deberán cumplir ciertas condiciones o reglas especificadas por la empresa de
transporte. Por ejemplo, una empresa puede poner como limitación que un pasaje no
pueda reservarse si faltan menos de 72 horas para realizarse el viaje. Otra regla podría
ser que no se le reservan pasajes a un cliente que ejecutó más de N cancelaciones. Las
reglas variarán dependiendo de la empresa y podrán especificarse en un lenguaje de
negocio claro, en un archivo de texto aparte. El Módulo Pasaje hará uso de un intérprete
de reglas de negocio y, mediante el Patrón Specification, aprobará o desaprobará
las reservas.
Los Pasajes en estado RESERVADO tienen una fecha de Expiración. SISTRANS
cuenta con un proceso que se ejecuta una vez por día y revisa las fechas de
expiración de todos los pasajes RESERVADOS. Cuando una reservación está por
vencer, el sistema emite un alerta para que se le comunique al Cliente la proximidad de
cancelación. Cuando el Pasaje ya está vencido automáticamente se elimina del sistema.
Los Pasajes pueden cancelarse, efectuando o no la devolución de un porcentaje
configurable del importe. En el caso de que el Pasaje esté en estado RESERVADO, es
muy posible que la seña depositada no se reintegre. Un Pasaje puede ser cancelado por
el Cliente, por expiración de la Reserva o por cualquier otro motivo. Cuando el Pasaje
es cancelado, pasa al estado CANCELADO, donde se le podrá asignar una fecha
de cancelación y un motivo.
3.2.7.4. Creación de un Pasaje
Como todas las Entidades de SISTRANS, un Pasaje se crea a través de su
correspondiente ServiceLayer, en este caso PasajeServiceLayer. La capa de
presentación deberá completar los datos de la entidad Pasaje y enviarlos al sistema a
través de los servicios reservar o comprar.
RESERVADO
reservar()
VENDIDO
comprar()
confirmar()
CANCELADO
cancelar()
cancelar()
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 57
Los procesos de compra y reserva de un Pasaje son similares. Por eso, se han unificado
en un único diagrama de secuencia.
A través del Módulo Viajes (MV), un Cliente podrá consultar por distintos Viajes.
ViajeServiceLayer cuenta con varios servicios de búsqueda de Viajes. El Cliente
elegirá un Viaje, una Escala en la que abordar, una Escala en la que desembarcar y una
ubicación.
1: <<create>>
presentacion pasajeServiceLayer pasajeService pasajeSpecification
4: reservar / comprar()
repository
5: isSatisfiedBy()
14: ubicacionEstado
viajeService
15: valorViaje()
16: importe
17: store()
19: ok
20: ok
18: ok
pasaje : Pasaje
2: seteo de atributos
7: setEstado(RESERVADO / VENDIDO)
9: ocuparUbicacion()
3: reservar / comprar()
10: refresh()
11: ubicacionEstado
12: store()
13: ubicacionEstado
6: true
8: agregarPuntosAClienteAsociado()
Figura 3.10: Diagrama de Secuencia de la reservación o compra de Pasaje
En el diagrama de secuencia, los objetos coloreados con celeste pertenecen a la capa de
presentación, los coloreados con rojo a la capa de servicio y los coloreados con amarillo
a la capa de dominio. En el diagrama vemos cómo PasajeService consulta a
PasajeSpecification si la reserva o compra puede realizarse, se ocupan las ubicaciones
del viaje (esto se hace en otra transacción y en un método sincronizado de
ViajeService, que asegura que no se pueda estar ocupando la misma
UbicacionEstado a la vez desde algún otro lado en el mismo momento) y luego se
imprimen los datos en el Pasaje y se persisten.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 58
3.2.7.5. Confirmación de una Reserva
presentacion pasajeServiceLayer pasajeService
1: confirmar()
2: confirmar()
repository
8: ok
3: setEstado(VENDIDO)
5: store()
6: ok
7: ok
repository
4: agregarPuntosAClienteAsociado()
Figura 3.11: Diagrama de Secuencia de la confirmación de un Pasaje
Si el Pasaje está RESERVADO y el Cliente decide confirmar la reserva, entonces
pasará al estado VENDIDO.
3.2.7.6. Cancelación de un Pasaje
presentacion pasajeServiceLayer pasajeService
1: cancelar()
2: cancelar()
repository
3: getUbicacion.desocupar()
7: store()
9: pasaje
10: pasaje
8: pasaje
pasaje
4: setMotivoCancelacion()
5: setFechaCancelacion()
6: setEstado(CANCELADO)
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 59
Figura 3.12: Diagrama de Secuencia de la cancelación de un Pasaje
Es importante aclarar que el servicio de cancelación puede ser invocado por la
capa de Presentación o por la misma capa de dominio que cambiará
automáticamente el estado del Pasaje cuando se supere la fecha de expiración de la
reservación.
3.2.7.7. Aspectos Económicos
En los diagramas de secuencia anteriores fueron excluidos los aspectos económicos por
motivos de simplificación.
El Pasaje guarda tres atributos del tipo Money:
Importe Neto
Descuento
Seña (si el Pasaje fue previamente RESERVADO)
Al momento de crear un Pasaje, PasajeServiceLayer deberá interactuar con
ViajeService enviándole todos los datos del Pasaje que desea comprar o reservar
(cliente, unidad, ubicación, subeEn, bajaEn). En ViajeService existe el método
valorViaje() que se encarga de calcular el importeNeto del Pasaje a emitir.
3.2.8. Módulo de Ejecutivos (ME)
3.2.8.1. Domain Vision Statement
Generar reportes estadísticos y estimativos a partir de los datos presentes en el sistema.
3.2.8.2. Especificación
El módulo consta de seis reportes:
Cantidad de viajes realizados.
Cantidad de pasajes vendidos.
Viajes cancelados.
Ganancias obtenidas.
Inversiones estimadas para viajes.
Cantidad de unidades utilizadas.
El reporte de cantidad de viajes realizados permite contabilizar la cantidad de viajes que
fueron realizados satisfactoriamente y quedaron registados en el sistema con este estado.
Existen varias maneras de obtener los viajes realizados:
Por Unidad: viajes realizados por determinada Unidad.
Entre fechas: viajes realizados entre dos fechas.
Por origen: viajes realizados originados en una escala especificada.
Por destino: viajes realizados finalizados en una escala especificada.
Por origen y destino: viajes realizados originados y finalizados en las escalas
especificadas.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 60
Por escala perteneciente al Viaje realizado: viajes realizados que tengan como
escala la indicada.
El reporte de cantidad de pasajes vendidos se comporta de manera similar al descripto
anteriormente. Permite contabilizar la cantidad de pasajes que fueron vendidos y
quedaron registados en el sistema con este estado, sin importar si el individuo realizó o
no el viaje. Existen varias maneras de obtener los pasajes vendidos:
Por Unidad: pasajes vendidos para ser utilizados en viajes realizados o a realizar
en determinada Unidad.
Entre fechas: pasajes vendidos entre dos fechas.
Por origen: pasajes vendidos para viajes que se originan en una escala
especificada.
Por destino: pasajes vendidos para viajes que finalizan en una escala
especificada.
Por origen y destino: pasajes vendidos para viajes que se originan y finalizan en
las escalas especificadas.
Por escala: pasajes vendidos para viajes que tengan como escala la indicada.
El reporte de viajes cancelados permite obtener los nombres y fechas de los Viajes
cancelados entre las fechas indicadas, incluyendo tambien el motivo de la cancelacion.
El reporte de ganancias obtenidas permite obtener un resumen del dinero ganado por la
venta de pasajes, menos los costos incurridos por la realización de los viajes. El cálculo
de los costos se explica en detalle en el apartado 3.2.6.6.
El reporte de inversiones permite estimar la inversión necesaria para poder sustentar los
costos asociados con la realización de viajes, basándose en información pasada.
Adicionalmente, existen objetos de apoyo a los reportes, que son necesarios para la
presentación de los resultados:
Histograma.
Intervalo.
3.2.9. Módulo de Trámites (MT)
El Módulo de Trámites (MT) no fue implementado por falta de tiempo y por
considerarse un módulo que aporta escaso valor al negocio y al desarrollo del trabajo.
4. Diseño
4.1. Convenciones y Estándares
4.1.2. Abreviaturas de los módulos del sistema
Para nombrar a los diferentes módulos del sistema se podrán utilizar las siguientes
abreviaturas (en orden por sigla):
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 61
Abreviatura Módulo
MC Módulo de Clientes
ME Módulo de Ejecutivos
MP Módulo de Personal
MPAS Módulo de Pasajes
MR Módulo de Rutas
MREP Módulo de Reparaciones
MT Módulo de Trámites
MU Módulo de Unidades
MV Módulo de Viajes
4.1.3. Nomenclatura básica de codificación
Identificador Reglas de Nomenclatura Ejemplo
Clases Los nombres de las clases deben ser palabras completas, en
mayúsculas y minúsculas, con la primera letra de cada palabra en mayúscula. Los nombres de clases deben ser simples y descriptivos, utilizando palabras completas y acrónimos o abreviaturas (a no ser que la abreviatura sea ampliamente conocida, como URL o HTML).
class Raster;
class ImageSprite;
Interfaces Los nombres de las interfaces deberían seguir las mismas reglas indicadas para las clases.
interface RasterDelegate;
interface Storing;
Métodos Los métodos deberían ser verbos, en mayúsculas y minúsculas, con la primera letra en minúscula, y la
primera letra de cada una de las palabras internas en mayúscula.
run();
runFast();
getBackground();
Variables Todos los nombres de variables de instancia o de clase deben estar constituidos por palabras con la primera letra de la primera palabra en minúscula y la primera letra de las palabras internas en mayúscula. Los nombres de variables deben ser cortos y significativos. La elección de un nombre de variable debe ser mnemotécnica, es decir,
pensado para que un lector casual comprenda su uso al verla. Se deben evitar las variables de una sola letra, excepto en variables temporales de corto uso. Nombres comunes para este tipo de variables son:
int i;
float myWidth;
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 62
Identificador Reglas de Nomenclatura Ejemplo
i, j, k, m y n para enteros. c, d, y e para caracteres.
Constantes Los nombres de variables declaradas como constantes de clase y constantes ANSI, deberían escribirse siempre en mayúsculas, con las palabras internas separadas por el signo de
subrayado ("_"). Las constantes ANSI se deben evitar en lo posible, para facilitar la depuración del código.
int MIN_WIDTH = 4;
int MAX_WIDTH = 999;
int GET_THE_CPU = 1;
4.1.4. Nomenclatura del modelo
Los nombres de clases y métodos que corresponden a Patrones de Diseño o
pertenecen al framework de Dominio o Persistencia se escribirán en idioma
inglés.
Los nombres de clases y métodos que corresponden al modelo (ubicado en la
capa de dominio) se escribirán en idioma español.
Los nombres de clases y métodos pertenecientes a Generics Subdomains del
framework de dominio (por ejemplo Money) se escribirán en idioma inglés.
Todos los comentarios en el código se escribirán en idioma español y sin
acentos.
Todas las clases del modelo deberán implementar o extender uno (y sólo uno) de
los tipos Entity, Value Object o Service, dependiendo del tipo de clase, según las
buenas prácticas de DDD.
Todos los objetos del modelo podrán componerse de dos clases y una interfaz.
Una de las clases será un EJB del tipo Entity, donde no se escribirá lógica de
negocio; el Entity EJB solamente guardará los atributos que se quieran persistir
y sus correspondientes setters y getters. La otra clase será un EJB Session Bean,
que contendrá la lógica de negocio y hará uso de los datos de la Entidad EJB. La
interfaz expondrá los servicios que podrán ser invocados remotamente desde el
Session Bean y será, por supuesto, la interfaz que implemente la lógica de
negocio. (No es necesario que existan las tres clases para cada objeto de
dominio. Se crearán de acuerdo a los requerimientos del modelo.)
Una Entidad DDD estará compuesta por su Entidad EJB correspondiente y su
Session Bean que implemente la lógica de negocio. Las Entidades se llamarán
como se llame la Entidad en el dominio (por ejemplo: Unidad) y extenderán de
la clase Entity del framework de DDD, la interfaz de la lógica de negocio se
llamará como el nombre de la Entidad + el nombre Service (por ejemplo:
UnidadService) y las clases Session Beans tendrán el mismo nombre que la
interfaz + la palabra Bean (por ejemplo: UnidadServiceBean).
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 63
Un Objeto de Valor de DDD estará compuesto por su Entidad EJB
correspondiente y su Session Bean que implemente la lógica de negocio. La
convención será la misma que para las Entidades, salvo que la Entidad EJB
extenderá de la clase ValueObject del framework de DDD.
Bajo ningún concepto se permite separar en distintos paquetes los datos de
un objeto de dominio de su lógica de negocio (por ejemplo: Unidad y
UnidadServiceBean no pueden encontrarse en distintos paquetes). Si existen
dos clases para representar un objeto del modelo en el código, las dos deben
estar contenidas en el mismo paquete y siguiendo la convención de los
puntos anteriores.
No es necesario que las interfaces de los Session Beans que pertenecen a un
objeto de dominio extiendan de la interfaz Service del framework de DDD. Por
ejemplo: UnidadService no debe heredar de Service. La interfaz Service fue
creada para objetos de lógica pura, que no son parte de ninguna Entidad u
Objeto de Valor de DDD.
Las clases públicas de la capa de servicio (Service Layer) deberán llamarse de la
forma Nombre de la clase + ServiceLayer. La mayoría de las ServiceLayers
serán Session Beans, por lo tanto, se compondrán por una interfaz y una
implementación llamada del mismo modo con el agregado de la palabra Bean.
(Por ejemplo: interfaz: UnidadServiceLayer; implementación:
UnidadServiceLayerBean.
Si hay atributos, constructores, setters o getters que no son parte del modelo,
pero son requeridos por las herramientas de introspección usadas o el motor de
persistencia, se agregarán en la clase al final de todos los otros métodos que sí
pertenecen al negocio, y además se crearán con la visibilidad más reducida
posible. (Por ejemplo: aunque el framework de DDD no provee un atributo ―id‖
para los Objetos de Valor, y tampoco es correcto que lo provea, el motor de
persistencia puede requerir un atributo ―id‖ para persistir el objeto y sus setters y
getters correspondientes. En ese caso se creará un ―id‖ privado auto-generado y
setters y getters protegidos.)
No se deben usar anotaciones que pertenezcan a la aplicación, en ninguna
clase de la capa de dominio. Si deben incluirse parámetros de configuración o
mapeo ORM para el motor de persistencia, se especificarán mediante el uso de
archivos de configuración externos como XML o properties. Fuera de la capa
de dominio, podrán utilizarse las anotaciones, que resultan más cómodas
para el desarrollo.
La capa de dominio debe construirse para ser completamente independiente de
la aplicación que la utiliza. No debe existir ninguna dependencia de la capa de
dominio hacia cualquier otra capa. La capa de dominio podrá ejecutarse fuera
de la aplicación, ya que será la representación del modelo y la fuente de
mayor valor para el negocio.
Siempre que se pueda (para consultas más o menos simples) se utilizará como
convención para los nombres de los NamedQueries la siguiente plantilla:
EntidadByAtributoAtributoAtributo. Por ejemplo: UnidadesByModeloMarca,
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 64
UnidadesByModelo, VariableTypeByName. El Primer Entity es el nombre de la
clase que será devuelta por el NamedQuery. El nombre de la Entity será en
singular si se sabe que sólo se obtendrá un resultado y en plural si se
obtendrá una lista.
Para las constantes de nombres de NamedQueries, se utilizará la plantilla
MODULO_ENTIDAD_BY_ATRIBUTO_ATRIBUTO_ATRIBUTO, donde
MODULO es la abreviatura del módulo al cual corresponde la consulta. Por
ejemplo: MV_TERMINAL_BY_NOMBRE, perteneciendo la consulta al
Módulo de Viajes.
Los números de orden en entidades ―ordenables‖ comienzan en ―0‖. Por
ejemplo, la primera Escala de un Viaje debe tener el número de orden ―0‖.
En las pruebas unitarias del sistema, se debe nombrar a las clases con el mismo
nombre de la clase que están probando, con el agregado al final de la palabra
Test. Por ejemplo, RutaTest prueba a la clase Ruta.
Se usará como codificación de los archivos del código fuente el estándar ISO-
8859-1.
4.1.5. Riesgos
4.1.5.1. Probabilidad de Ocurrencia
1. Baja: (< 15%)
- Poco probable.
2. Media: (>15% y <85%)
- Posible / Muy Posible.
3. Alta: (>85%)
- Casi seguro
4.1.5.2. Severidad
1. Baja:
- Impacto menor en costo y en calendario.
- Sin cambio de beneficios.
2. Media
- Impacto importante en costo y calendario.
- Impacto menor en beneficios.
3. Alta
- Impacto importante en costo y beneficios.
- Impacto mayor en beneficios.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 65
4.1.5.3. Exposición al riesgo
Fórmula para el cálculo de la exposición al riesgo:
Exposición al Riesgo = Probabilidad de Ocurrencia x Severidad
4.1.6. Estimaciones
Para las estimaciones se toma en cuenta el concepto de story points aportado por la
metodología Scrum. Éste indica que se debe considerar por cada user story cuánto se
tardaría en desarrollarlo, si una persona estuviese trabajando full-time sobre el mismo.
Las unidades equivalentes a los story points indicados en nuestro proyecto son los días,
consideradas 8 horas/hombre por día.
Al momento de estimar, la unidad mínima de estimación debe ser de 0,5 story points.
Esto se debe a que no se conoce con demasiada certeza el tiempo que puede llevar
alguna tarea, o bien se podría caer en un micro-management. En el sprint backlog, en el
caso de que el tiempo necesario para terminar alguna tarea sea muy pequeño y el valor
de 0,5 sea demasiado alto para expresarlo, se puede marcar como tiempo necesario 0,
pero dejar indicado en el Estado de la tarea que todavía se está realizando.
4.2. EJB3 y Domain-Driven Design: Arquitecturas Incompatibles
Si bien Eric Evans en su libro Domain-Driven Design (filosofía que hemos adoptado
para el desarrollo de SISTRANS) no impone una arquitectura definida, a través de
conceptos y patrones enuncia lineamientos de diseño en los cuales se puede vislumbrar
una separación de capas fundamental.
El objetivo principal de DDD es aislar el dominio del resto de la aplicación. Eso
queda bien claro desde el primer capítulo. Lo primero que Evans nos dice es que el
dominio es la única capa indispensable para DDD. Tranquilamente podríamos
construir una arquitectura de solamente dos capas:
[Capa de Dominio o Lógica de Negocio] + [Capa de Aplicación].
Para satisfacer requerimientos no funcionales de distribución y/o manejo de
concurrencia, SISTRANS ha adoptado la siguiente separación de capas:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 66
Figura 4.1: Arquitectura de SISTRANS
Debido a que SISTRANS se plantea como una aplicación enterprise, que debe
soportar concurrencia, transacciones de negocio y encima estar preparada para
funcionar en un ambiente distribuido, nos pareció apropiado utilizar la tecnología más
robusta que actualmente se conoce para aplicaciones enterprise escalables: EJB 3.0.
EJB 3.0 no sólo es un framework, también es un conjunto de bibliotecas que imponen
una arquitectura, ya que, para aprovechar todo su potencial, debe correr en un servidor
de aplicaciones que implemente la especificación correspondiente de SUN. Por lo
tanto, EJB 3.0 es una plataforma, a menudo conocida como Plataforma Java EE
(aunque, correctamente hablando, Java EE es una plataforma que soporta muchas más
especificaciones que EJB).
A continuación, podemos ver cómo es la arquitectura de una aplicación enterprise
estándar construida con EJB 3.0:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 67
Figura 4.2: Arquitectura de una aplicación típica construida con EJB3
Esta arquitectura no es compatible con una arquitectura pura de DDD, ni con la
arquitectura que propone SISTRANS. La incompatibilidad fundamental está en que en
EJB 3.0 no existe una capa de dominio aislada donde vive el Modelo de forma
independiente a la infraestructura y/o aplicación. Lo que EJB 3 llama Modelo es esa
capa de Persistencia que vemos sobre la capa de Base de Datos. En esta capa viven los
Entity Beans, que no son más que Objetos de Dominio con atributos, setters y getters,
pero sin lógica de negocio. Toda la lógica de negocio se ubica en la capa de Lógica
de Negocio, donde viven los Session Beans. De esta forma, el conocimiento del
Dominio se encuentra disgregado en dos capas separadas y, en el caso de la capa de
Persistencia, mezclada con aspectos de infraestructura y, por ende, de tecnología.
En DDD, Evans rechaza este tipo de arquitecturas hasta el extremo de aducir que
atentan contra la programación orientada a objetos, ya que, al separar los datos de
los algoritmos que manipulan dichos datos, se vuelve a un diseño estructurado.
Diseccionando de esta forma el Modelo, no sólo perdemos la forma de aislar el
Conocimiento del Negocio, también perdemos la encapsulación que la POO propone al
guardar atributos y métodos en una sola estructura lógica.
Pero por otra parte, una de las recomendaciones de DDD es que, cuando se tiene que
utilizar un framework, no se debe luchar contra la filosofía esencial del mismo, porque
el resultado puede quedar tan complicado que se corre riesgo de perder la
mantenibilidad y escalabilidad que un Modelo de Dominio es capaz de brindar. Por
eso, Evans recomienda que, si nos vemos obligados a utilizar alguna de estas
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 68
tecnologías que separan la lógica de negocio de los datos en distintas clases, por lo
menos no ubiquemos esas clases en distintas capas.
No es trivial la razón por la que existen Session Beans y Entity Beans. En los Session
Beans se debe escribir la lógica transaccional de negocio y en los Entity Beans deben
vivir los datos que pueden persistirse. No podemos ir en contra de esa filosofía. La
lógica de negocio se debe escribir en los Session Beans porque es ésta la forma que
tiene el servidor de aplicaciones de controlar el acceso concurrente de usuarios y
manipular las transacciones declarativas de negocio para el acceso a los datos. En los
Entity Beans vive el mapeo objeto-relacional necesario para que el DataMapper persista
los atributos en las tablas de la base de datos. Pero los Entity Beans no son thread-
safe. El servidor de aplicaciones no controlará el ciclo de vida de los Entity Beans
ni el acceso concurrente a sus datos. Por eso: todos los Entity Beans deben ser
accedidos a través de Session Beans.
Para solucionar esta dicotomía entre ambos modelos, hemos establecido una convención
sencilla. En nuestro modelo vivirán Entity Beans y Session Beans. Cada Entidad de
DDD que necesite ser persistida, estará compuesta por un Entity Bean que
contenga los atributos y un Session Bean que implemente la lógica de negocio para
manipular dichos atributos. Cada Objeto de Valor de DDD que necesite ser
persistido, estará compuesto por un Entity Bean que contenga los atributos y un
Session Bean que implemente la lógica de negocio para manipular dichos
atributos. Además, en la capa de Dominio vivirán Servicios, el tercero de los tipos de
Objetos de Dominio que DDD propone. Los Servicios estarán implementados como
Session Beans.
Entity = EntityBean + SessionBean + Interface
ValueObject = EntityBean + SessionBean + Interface
Service = SessionBean + Interface
A partir de EJB 3.0, tanto el mapeo ORM como la configuración de los Session Beans
pueden hacerse mediante anotaciones imbuidas en el código. Las anotaciones
representan un incremento muy grande en la velocidad de desarrollo de una aplicación
enterprise. No se puede negar que escribir el mapeo ORM, por ejemplo, en el mismo
archivo donde se encuentra la clase que será el Entity Bean es realmente cómodo; sin
contar además que contamos con un mecanismo de compilación de anotaciones para
solucionar problemas de sintaxis previos a la ejecución. Comparado con los XMLs, las
anotaciones son una gran ventaja; escribir descriptores XML es demasiado verboso y
propenso a errores.
Sin embargo, las anotaciones encajan perfecto en una arquitectura EJB 3.0, pero no en
una arquitectura DDD. La razón: al agregar anotaciones en una clase, automáticamente
agregamos una dependencia de tecnología. Si los Entity Beans viven en la capa de
Persistencia, eso no es problema. Pero si los Entity Beans viven en la capa de Dominio,
como será en el caso de SISTRANS, las anotaciones no son una buena opción. La capa
de Dominio no puede tener absolutamente ninguna dependencia con el framework
de persistencia o la plataforma EJB3. Es por esto que hemos decidido utilizar los
descriptores XML (orm.xml y ejb-jar.xml) para que los POJOs que pasarán a ser
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 69
Entity Beans o Session Beans no posean ninguna dependencia de tecnología. No
olvidemos que el objetivo principal de DDD es aislar por completo el dominio:
podríamos armar un paquete y usarlo en cualquier aplicación (no necesariamente
una aplicación Java EE o EJB 3.0). Éste es el concepto de Dominio Portable.
Conclusión:
Todos los objetos del modelo podrán componerse de dos clases y una interfaz.
Una de las clases será un EJB del tipo Entity, donde no se escribirá lógica de
negocio; el Entity EJB solamente guardará los atributos que se quieran persistir
y sus correspondientes setters y getters. La otra clase será un EJB Session Bean,
que contendrá la lógica de negocio y hará uso de los datos del EJB Entity. La
interfaz expondrá los servicios que podrán ser invocados remotamente desde el
Session Bean y será, por supuesto, la interfaz que implemente la lógica de
negocio. (No es necesario que existan las tres clases para cada objeto de
dominio. Se crearán de acuerdo a los requerimientos del modelo.)
Bajo ningún concepto se permite separar en distintos paquetes los datos de
un objeto de dominio de su lógica de negocio. Si existen dos clases para
representar un objeto del modelo en el código, las dos deben estar
contenidas en el mismo paquete y siguiente la convención de los puntos
anteriores.
No se deben usar anotaciones que pertenezcan a la aplicación, en ninguna clase
de la capa de dominio. Si deben incluirse parámetros de configuración o mapeo
ORM para el motor de persistencia, se especificarán mediante el uso de archivos
de configuración externos como XML o properties. Fuera de la capa de dominio,
podrán utilizarse las anotaciones, que resultan más cómodas para el desarrollo.
La capa de dominio debe construirse para ser completamente independiente de
la aplicación que la utiliza. No debe existir ninguna dependencia de la capa
de dominio hacia cualquier otra capa. La capa de dominio podrá ejecutarse
fuera de la aplicación, ya que será la representación del modelo y la fuente de
mayor valor para el negocio.
4.3. Pruebas Unitarias
SISTRANS se construye bajo un marco de desarrollo ágil, por eso ponemos especial
énfasis en mantener un producto con calidad cercana a producción en todo momento.
Las Pruebas Unitarias, para la detección temprana de errores, y la Revisión de a
Pares, para identificar errores y reducir el re-trabajo, son las dos herramientas
fundamentales que usamos para mantener la calidad en todo momento.
Dado que la Arquitectura de SISTRANS se encuentra fuertemente separada en capas,
durante el desarrollo, se podrán crear pruebas unitarias automatizadas para cada capa
por separado, probando así cada una de forma individual.
A continuación, se muestra un esquema en el que vemos cómo, mediante componentes
de Unit Test, podemos pararnos sobre la capa inmediatamente superior, reemplazándola,
para probar cada capa por separado:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 70
Figura 4.3: Pruebas Unitarias dentro de la Arquitectura de SISTRANS
4.4. Distribución
4.4.1. sistrans.jar
Contiene la capa de dominio:
Framework de dominio
Generic subdomains
Modelo de dominio
Se deberá copiar en el directorio de librerías del servidor de aplicaciones.
4.4.2. sistrans-ejb.jar
Contiene la aplicación entera de SISTRANS, lista para ser desplegada en un Servidor de
Aplicaciones:
Capa de Persistencia (con el mapeo ORM de las Entidades y las
implementaciones de Repository)
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 71
Capa de Servicio (con las ServiceLayers)
Se deberá desplegar en el servidor de aplicaciones.
4.4.3. sistrans-dto.jar
Este jar contiene:
Framework de dominio
Generic subdomains
Entidades EJBs del modelo para ser usadas como DTOs
Se deberá incluir en el classpath de una capa de Presentación o Aplicación Cliente.
4.4.4. sistrans-ejb-client.jar
Este jar contiene:
Las interfaces de los EJBs de la capa de Servicio para ser invocados
remotamente
Se deberá incluir en el classpath de una capa de Presentación o Aplicación Cliente.
4.4.5. sistrans-dto-personal.jar
Este jar contiene:
Framework de dominio
Generic subdomains
Entidades EJB del Módulo de Personal (MP) para ser usadas como DTOs
Se deberá incluir en el classpath de un extractor de datos de calificación de Personal.
4.4.6. sistrans-ejb-personal.jar
Este jar contiene:
Las interfaces de los EJBs de la capa de Servicio de Personal para ser invocados
remotamente.
Se deberá incluir en el classpath de un extractor de datos de calificación de Personal.
4.4.7. sistrans-dto-reparaciones.jar
Este jar contiene:
Framework de dominio
Generic subdomains
Entidades EJB del Módulo de Reparaciones (MREP), Unidades (MU) y
Personal (MP) para ser usadas como DTOs
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 72
Se deberá incluir en el classpath de una aplicación cliente que administre las
reparaciones de unidades.
4.4.8. sistrans-ejb-reparaciones.jar
Este jar contiene:
Las interfaces de los EJBs de la capa de Servicio de Reparaciones para ser
invocados remotamente.
Se deberá incluir en el classpath de una aplicación cliente que administre las
reparaciones de unidades.
4.5. Mecanismo de Eager Loader
El framework de dominio de SISTRANS, provee un mecanismo para leer colecciones
de objetos de dominio de forma selectiva y dinámica.
Supongamos que el modelo posee una Entidad llamada EntidadUno y que esta Entidad
tiene dos colecciones (relación de 1 a muchos). Una de estas colecciones es otra Entidad
(EntidadDos) y la otra es un Objeto de Valor (ValueObjectUno).
Figura 4.4. EntidadUno posee dos colecciones: EntidadDos y ValueObjectUno
En los mapeos ORM (object relational mapping), las relaciones entre objetos se pueden
especificar como EAGER o LAZY. Cuando una relación está mapeada como EAGER
(supongamos que la relación 1 a muchos entre EntidadUno y EntidadDos está mapeada
de esta forma), al recuperar un objeto del tipo EntidadUno de la capa de persistencia a
través de un Mapper, lo hacemos trayendo además una colección completa de objetos
EntidadDos asociados.
Como la cantidad de objetos EntidadDos puede ser muy grande, estas consultas a la
base y mantener una cantidad considerable de objetos en memoria podría resultar muy
costoso. En casos en los que al cliente solicitante sólo le interesen los atributos propios
de EntidadUno y no le interese consultar la colección de EntidadDos, debería ser
innecesario pagar este costo.
<<Entity>>
EntidadUno
<<Entity>>
EntidadDos
<<ValueObject>>
ValueObjectUno
1
*
1
*
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 73
Por eso, es común que las implementaciones de Mappers de persistencia implementen el
patrón LazyLoad16
de Martin Fowler. Este patrón lo que hace es retrasar la carga de la
colección dependiente hasta el momento en que sea efectivamente requerida. Si la
relación entre EntidadUno y EntidadDos estuviera mapeada como LAZY, el cliente no
pagaría el costo de la carga masiva si no es necesario.
En JPA el mecanismo de LazyLoad es implementado a través del mapper definido por
configuración (en el caso de SISTRANS, este mapper es Hibernate). La interfaz
EntityManager es la encargada de crear, recuperar, actualizar y borrar (CRUD) objetos
en la capa de Persistencia de una aplicación EJB3. A través de esta interfaz es que un
programador de la capa de Persistencia puede comunicarse con el Mapper para traer o
depositar los objetos de dominio en la base de datos.
Figura 4.5. A través del EntityManager se pueden traer o depositar objetos de dominio en la base de datos
La interfaz EntityManager manipula Entidades EJBs (POJOs), que pueden ser
Entidades u Objetos de Valor del dominio. Los Entities EJB responden a un ciclo de
vida que inevitablemente se encuentra atado a las operaciones de esta interfaz. Los
objetos nacen con un constructor provisto por el lenguaje de programación (new), se
persisten (persist), se recuperan (find), se separan (detached) del EntityManager o se
fusionan (merge), y por último, se remueven (remove).
Figura 4.6. Ciclo de Vida de una Entidad EJB con respecto a la interfaz EntityManager
En JPA se habla de Entidades Manejadas (Managed Entities) cuando el objeto se
encuentra sincronizado con la base de datos. Cuando la Entidad se encuentra en este
estado, sabemos que el EntityManager tiene una conexión abierta con la base de datos
16 http://martinfowler.com/eaaCatalog/lazyLoad.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 74
(nos encontramos trabajando en una misma UnitOfWork17
). Esta sincronización se
cerrará cuando la transacción sea terminada o cuando el objeto se separe (detached) de
la capa de Persistencia, en otras palabras: cuando el objeto se escape del alcance de la
instancia del EntityManager.
Cuando una Entidad posee una colección de Entidades asociadas y la relación se
encuentra configurada como Lazy, el patrón funcionará correctamente mientras el objeto
se mantenga sincronizado con la base. Volviendo al ejemplo del principio, esto
significa: podremos recuperar la EntidadUno y, si queremos, recuperar la EntidadDos o
el ValueObjectUno utilizando la carga perezosa, cargando la Entidad al momento de
invocar a los getters respectivos de las colecciones. JPA hace que la recuperación tardía
sea transparente para el cliente. Pero esto sólo funcionará cuando estemos en el estado
de Entidad Manejada, una vez separado el objeto, cuando intentemos traer alguna
colección asociada (que no hayamos cargado previamente) obtendremos una excepción
del tipo LazyLoadException.
Esto presenta un desafío para la arquitectura de SISTRANS, ya que las capas se
encuentran muy separadas y el EntityManager sólo vive en la capa de Persistencia,
encapsulado por un Repositorio (en este caso, el JpaRepositoryBean). Cuando la capa
de servicio intente recuperar EntidadUno (y las relaciones con EntidadDos y
ValueObjectUno se encuentren en LAZY), y luego quiera acceder a alguna de las dos
colecciones a través de su getter, inevitablemente obtendrá una LazyLoadException.
Por este motivo es que el framework de dominio implementa un Generic Subdomain
llamado EagerLoader, que permite al cliente recuperar Entidades especificando las
colecciones que se quieren cargar de antemano.
Figura 4.7. Diagrama de clases del subdominio genérico EagerLoader
17 http://martinfowler.com/eaaCatalog/unitOfWork.html
<<ValueObject>>
EagerLoader
+getAttributes(): List<Attribute>
+setAttributes(attributes:List<?>)
+load(object:Object)
<<ValueObject>>
EagerLoaderImpl
+setAttributes(jsonArray:String)
+load(object:Object)
<<ValueObject>>
Attribute
-name: String
+Attribute()
+Attribute(name:String)
+getName(): String
+setName(name:String)
+load(object:Object)
*
1
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 75
La interfaz Repository especifica un parámetro adicional en sus métodos de búsqueda
para el manejo del EagerLoader. Veamos las siguientes operaciones:
public T find(IdentityField id, Class<T> clazz, EagerLoader
eagerAttributes);
public List<T> findAll(Class<T> clazz, EagerLoader eagerAttributes);
public List<T> findAll(Class<T> clazz, Integer first, Integer max,
EagerLoader eagerAttributes);
public T findSingleResult(NamedQuery namedQuery, Class<T> clazz,
EagerLoader eagerAttributes);
public List<T> findResults(NamedQuery namedQuery, Class<T> clazz,
EagerLoader eagerAttributes);
public List<T> findResults(NamedQuery namedQuery, Class<T> clazz,
Integer first, Integer max, EagerLoader eagerAttributes);
Lo que tienen en común estos métodos es el último parámetro EagerLoader, objeto raíz
del subdominio genérico EagerLoader.
El EagerLoader recibirá una lista de atributos, cada atributo a la vez puede otra lista de
atributos y así hasta la profundidad que se desee alcanzar. De esta forma podremos
recuperar objetos dentro de otros objetos, dentro de una misma agregación.
Volviendo al ejemplo del comienzo, supongamos que deseamos recuperar una
EntidadUno y que necesitamos que las colecciones EntidadDos y ValueObjectUno se
carguen completas. Para lograr esto, haríamos algo así:
List<Attribute> attributes = new ArrayList<Attribute>();
attributes.add(new Attribute("entidadesUno"));
attributes.add(new Attribute("valueObjectsUno"));
EagerLoader eagerLoader = EagerLoaderFactory.create();
eagerLoader.setAttributes(attributes);
EntidadUno entidadUno = repository.find(id, EntidadUno.class,
eagerLoader);
Pero ahora imaginemos que el modelo es un poco más complicado. Imaginemos que
EntidadDos y ValueObjectUno también tienen colecciones asociadas.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 76
Figura 4.8. Ejemplo un poco más complejo: las colecciones ahora a su vez tienen otras colecciones
Imaginemos que queremos recuperar de vuelta una EntidadUno, pero esta vez queremos
que se carguen absolutamente todas las colecciones, incluyendo las asociadas a
EntidadDos y a ValueObjectUno. Si cargáramos los atributos en el EagerLoader de la
misma forma en la que lo hicimos en el ejemplo anterior, el código sería éste:
List<Attribute> lista1 = new ArrayList<Attribute>();
lista1.add(new Attribute("valueObjectDos"));
lista1.add(new Attribute("valueObjectTres"));
List<Attribute> lista2 = new ArrayList<Attribute>();
lista2.add(new Attribute("valueObjectCuatro"));
lista2.add(new Attribute("valueObjectCinco"));
Attribute att1 = new Attribute("entidadDos");
att1.setAttributes(lista1);
Attribute att2 = new Attribute("valueObjectUno");
att2.setAttributes(lista2);
List<Attribute> lista3 = new ArrayList<Attribute>();
lista3.add(att1);
lista3.add(att2);
EagerLoader eagerLoader = EagerLoaderFactory.create();
eagerLoader.setAttributes(lista3);
EntidadUno entidadUno = repository.find(id, EntidadUno.class,
eagerLoader);
Como se puede apreciar, la configuración del EagerLoader se ha complicado
notablemente. Si el modelo fuera más complicado aún, esto se tornaría un infierno.
Por eso existe otra forma de configurar los atributos en el EagerLoader y es a través de
un String en formato JSON. Si observamos el diagrama de clases de la Figura 4,
<<Entity>>
EntidadUno
<<Entity>>
EntidadDos
<<ValueObject>>
ValueObjectUno
1
*
1
*
<<ValueObject>>
ValueObjectDos
<<ValueObject>>
ValueObjectTres
<<ValueObject>>
ValueObjectCuatro
<<ValueObject>>
ValueObjectCinco
1
*
1*
1
*
1
*
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 77
podemos ver que el EagerLoaderImpl cuenta con un setAttributes que recibe un
jsonArray en forma de String. En el ejemplo anterior, el JSON que se debería enviar al
EagerLoader sería:
[ { "entidadDos" : [ "valueObjectDos", "valueObjectTres" ] },
{ "valueObjectUno" : [ "valueObjectCuatro", "valueObjectCinco" ] } ]
Este JSON está definido como una lista cuyos elementos pueden ser Strings o Maps. Si
el elemento es un String, se trata del nombre del atributo que se quiere recuperar. Si el
atributo es un Map, la clave es el nombre del atributo que se quiere recuperar y el valor
es la sub-lista de atributos que se cargarán para ese atributo; esta lista es de vuelta un
array, pero si se trata de un solo elemento también se puede escribir como un String.
Así, podemos anidar elementos de una forma muchísimo más práctica y sencilla.
Una vez que cargamos el String en formato JSON, que podría leerse de un archivo
properties de configuración o hardcodearse directamente en el código, para recuperar
EntidadUno hacemos lo siguiente:
EagerLoader eagerLoader = EagerLoaderFactory.create(jsonArray);
EntidadUno entidadUno = repository.find(id, EntidadUno.class,
eagerLoader);
Por supuesto que no siempre estamos obligados a cargar todas las colecciones. Por
ejemplo, podríamos querer cargar solamente las colecciones de primer nivel:
[ "entidadDos", "valueObjectUno" ]
O quizás cargar una colección sola de cada objeto:
[ { "entidadDos" : "valueObjectDos" } ]
O cargar lo mismo que antes más el ValueObjectUno:
[ { "entidadDos" : "valueObjectDos" }, "valueObjectUno" ]
De esta forma, variar las combinaciones de carga es mucho más sencillo y más fácil de
entender. He aquí dos ejemplos para la carga de un Viaje en SISTRANS.
Ejemplo 1:
[ { "itinerariosAlternativos" : [
{ "itinerario": [ {"tramos" : "ruta" } ] } ] },
{ "tripulacion" : "roles" },
{ "unidadesDeViaje" :
[ { "unidad": [ "ubicaciones", "variables" ] },
"ubicacionesEstado" ] },
"serviciosABordo",
"serviciosPreviosAlAbordaje",
"bitacora" ]
Ejemplo 2:
[ "unidadesDeViaje", "itinerariosAlternativos" ]
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 78
4.6. Mecanismo de Programación de Tareas
La capa de Servicio de SISTRANS provee una forma de ejecutar tareas repetitivas con
un intervalo de tiempo constante o que se ejecuten en una fecha determinada. Estas
tareas pueden ser útiles, por ejemplo, para disparar un conjunto de reglas de negocio
para que se ejecuten mensualmente, o para verificar la fecha de expiración de las
reservaciones de Pasajes y avisar cuándo algún vencimiento esté cerca, o cancelar la
reservación pasada la fecha.
El mecanismo de Programación de Tareas de la capa de Servicio es puramente técnico,
y se encuentra construido sobre la especificación del servicio de Timers de EJB 3.0.
4.6.1. Tecnología
Al principio se analizaron tres posibilidades para la implementación de este mecanismo:
Utilizar una biblioteca no estándar para programación de tareas, como Quartz o
Flux.
Utilizar la especificación de Timers estándar de EJB 3.0 (y en particular la
implementación de JBoss AS).
Diseñar un framework propio.
Habiendo tantas opciones de código abierto en el mercado, ya probadas y algunas muy
completas, la tercera opción fue descartada casi en seguida. Entre la primera y la
segunda opción, optamos por la segunda por los siguientes motivos:
Los Timers son parte de la especificación EJB 3, parte del estándar que ya
venimos utilizando en el resto del sistema.
No necesitamos agregar nuevas bibliotecas a nuestro proyecto. Aprovechando
que la capa de servicio es desplegada en un contenedor de EJBs (en nuestro caso
JBoss), simplemente utilizamos la funcionalidad que éste provee.
El TimerService es inyectado mediante el uso del ejb-jar.xml dentro de un
Session Bean, de la misma forma que inyectamos otros EJBs y el EntityManager
de JPA en los Repositorios. De esta forma, el contenedor maneja las instancias
del servicio y su ciclo de vida.
Las Tareas se ejecutan dentro de una transacción de negocio declarativa,
administrada por el mismo servidor de aplicaciones. Al igual que con cualquier
Session Bean, no tenemos necesidad de complicar el código agregando soporte
para JTA (como sí tendríamos que haber hecho si usábamos alguna biblioteca
externa).
Los Timers sobreviven al ciclo de vida de su EJB. Los Timers son persistidos
por el contenedor y cuando éste vuelve a levantarse son reactivados
automáticamente.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 79
4.6.2. Breve Introducción a los Timers de EJB 3.0
Todo Session Bean puede poseer un método (y no más de uno) especificado como
método de Timeout. El método de timeout puede ser declarado mediante una anotación
@Timeout sobre la definición del método, o mediante el tag timeout-method en el ejb-
jar.xml. Siguiendo el criterio de diseño elegido para SISTRANS, hemos utilizado la
segunda opción.
El método Timeout se ejecutará cada vez que expire el intervalo de sueño del Timer.
Veamos un ejemplo sencillo:
@Stateless
public class TimerEjemploBean implements TimerEjemplo {
@Resource
private TimerService timerService;
public void crearTimer() {
...
timerService.createTimer(
tiempoInicial,
frecuenciaEnMilisegundos,
datos);
...
}
@Timeout
public void metodoDeTimeOut(Timer timer) {
Datos datos = (Datos) timer.getInfo();
...
}
}
Como se puede ver en el código anterior, TimerEjemploBean no es más un Session
Bean común y corriente (stateless). Por lo tanto, podremos inyectar el TimerService en
una ServiceLayer de la capa de Servicio de SISTRANS, de la misma forma que
inyectamos los demás EJBs y Recursos manejados por el contenedor. En el método
crearTimer(), que será invocado de forma externa, se crea un Timer que comenzará a
ejecutarse dentro de un tiempoInicial y dormirá frecuenciaEnMilisegundos entre
ejecución y ejecución. Cada frecuenciaEnMilisegundos el servidor de aplicación
ejecutará el metodoDeTimeOut.
4.6.3. Implementación en la capa de Servicio
En la capa de servicio, SISTRANS provee una interfaz genérica llamada
TimerServiceLayer, que servirá como interfaz remota y/o local de todos los
SessionBeans (ServiceLayerBean) que implementen alguna Tarea.
TimerServiceLayer se compone de tres métodos:
configurar(): se invocará cuando se quiera crear un Timer para la Tarea; se
encarga de configurar el Timer y de lanzarlo.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 80
ejecutar(): será el método timeout de la Tarea; sirve para implementar la lógica
que se ejecutará en cada intervalo.
detener(): se invocará cuando se quieran eliminar los Timers activos de la
Tarea; cancela todos los Timers asociados a la ServiceLayer.
4.6.4. Ejemplo
Veamos un ejemplo muy simple. Supongamos que queremos ejecutar una TareaX de
forma repetitiva a cada hora.
Paso 1: Se creará una ServiceLayerBean que implemente TimerServiceLayer:
public class TareaXServiceLayerBean implements TimerServiceLayer {
private TimerService timerService;
@Override
public void configurar() {
...
timerService.createTimer(0, DateUtils.MILLIS_PER_HOUR, null);
...
}
@Override
public void ejecutar(Timer timer) {
// Código que se ejecutará cada hora y
// será disparado por el servidor de aplicaciones
}
@Override
public void detener() {
// getTimers devuelve todos los Timers
// asociados a esta ServiceLayer
Collection<Timer> timers = timerService.getTimers();
for (Timer timer : timers) {
timer.cancel();
}
}
}
Paso 2: Se declarará el Session Bean en el descriptor ejb-jar.xml:
<session>
<ejb-name>TareaXServiceLayerBean</ejb-name>
<business-remote>
ar.uba.fi.tprof.sistrans.servicio.TimerServiceLayer
</business-remote>
<ejb-class>
ar.uba.fi.tprof.sistrans.servicio.nombredelmodulo.TareaXService
LayerBean
</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<timeout-method>
<method-name>ejecutar</method-name>
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 81
<method-params>
<method-param>javax.ejb.Timer</method-param>
</method-params>
</timeout-method>
<resource-ref>
<res-ref-name>TimerService</res-ref-name>
<res-type>javax.ejb.TimerService</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
<injection-target>
<injection-target-class>
ar.uba.fi.tprof.sistrans.servicio.nombredelmodulo.TareaXServiceLayerBe
an</injection-target-class>
<injection-target-name>
timerService
</injection-target-name>
</injection-target>
</resource-ref>
</session>
Paso 3: Se desplegará el EJB:
Este paso no es más que desplegar la ServiceLayer de la misma forma en que se
despliegan los demás EJBs de SISTRANS.
Paso 4: Ejecutar configurar():
Para programar la TareaX, se deberá invocar al método configurar(). En este ejemplo,
configuraremos la tarea de forma remota. Este código podría estar dentro de una
aplicación cliente cualquiera como un Unit Test o una capa de presentación:
TimerServiceLayer servicio = (TimerServiceLayer)
ApplicationServerService.getObjectFromAS(
"TareaXServiceLayerBean/remote");
servicio.configurar();
Desde aquí, si todo salió bien, el método ejecutar() de la TareaX se ejecutará a cada
hora, siempre que el servidor de aplicaciones esté levantado. Además, con la
configuración default del TimerService, ejecutar() también se disparará cada vez que
se levante nuevamente el servidor y de allí a intervalos regulares de una hora.
Paso 5: Ejecutar detener():
En caso de querer detener la tarea, ejecutar el método detener(). En este ejemplo,
también lo hacemos de forma remota a través de un Unit Test:
TimerServiceLayer servicio = (TimerServiceLayer)
ApplicationServerService.getObjectFromAS(
"TareaXServiceLayerBean/remote");
servicio.detener();
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 82
4.7. Comunicación con Sistema Externo de Capacitación
Como se explica en el documento principal de Arquitectura, las capas de SISTRANS
están preparadas para ser fácilmente distribuidas. La capa de Servicio, montada sobre la
capa de Dominio, permite escribir muchas aplicaciones clientes o capas de Presentación
usando distintas tecnologías y plataformas. Incluso la misma capa de Servicio puede
separarse en partes, armando diferentes distribuciones para diferentes aplicaciones
clientes.
El objetivo principal de la capa de Servicio (Service Layer) es desacoplar la
Presentación del Dominio, publicando sólo los aspectos necesarios, encapsulando el
acceso al Modelo como un Facade.
4.7.1. sistrans-ejb-personal.jar
Para que la información de los Empleados pueda ser actualizada por un sistema externo,
SISTRANS provee una capa de Servicio reducida que sólo brinda acceso al Módulo
Personal (MP). Publicando la interfaz EmpleadoServiceLayer y utilizando la clase
Empleado y Rol como DTOs, una aplicación cliente puede invocar remotamente los
servicios del MP para actualizar los datos. La distribución que sólo incluye acceso al
Módulo Personal se llama: sistrans-ejb-personal y sistrans-dto-personal.
La distribución sistrans-ejb-personal contiene:
EmpleadoServiceLayer
RolServiceLayer
La distribución sistrans-dto-personal contiene:
Framework de Dominio
Persona
Sexo
NombresDeConsultas
Empleado
ItemDeCapacitacion
Licencia
Rol
4.7.2. Aplicación Extractor de Ejemplo
Para ejemplificar el uso de sistrans-ejb-personal y mostrar la forma en la que pueden
actualizarse los datos de un Empleado de forma remota, hemos construido una pequeña
aplicación de consola llamada sistrans-extractor, que toma los datos de un sistema
externo de capacitación dummy y los vuelca en SISTRANS.
A continuación podemos ver un diagrama de componentes que muestra las
dependencias entre los sistemas involucrados:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 83
Figura 4.9. Arquitectura de la aplicación cliente de sistrans-extractor
En la aplicación de ejemplo, el Sistema Externo de Capacitación es un sistema
simulado, de forma similar a como simulamos una capa de Persistencia en SISTRANS,
mediante el uso de un DummyMapper y de datos ficticios guardados en un archivo de
properties en formato JSON. El DummyMapper lee los datos de los supuestos
Empleados y se los devuelve al Extractor. El Extractor le pide a la capa de Servicio de
Personal que le entregue los Empleados obtenidos del Sistema de Capacitación para
actualizar la información. Modifica los datos del legajo de capacitación, las licencias y
los roles habilitados y, al terminar, le pide a la ServiceLayer que guarde las
modificaciones en SISTRANS.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 84
5. Calidad
5.1. Datos de Prueba
El proyecto cuenta con un conjunto de datos de prueba para proporcionar un contenido
con el cual poder demostrar y/o probar su funcionamiento. Dado que el núcleo del
proyecto es un modelo genérico "customizable" para cualquier tipo de empresa de
transporte de larga distancia, se eligieron datos para una de las alternativas posibles de
personalización. Se eligió entonces cargar datos pertenecientes al negocio de aerolíneas,
dado que es el más completo en cuanto a contenidos y control de sus pasajeros.
Para la carga masiva de datos de prueba reales (nota al pie: En realidad no son 100%
reales, pero podrían serlo ya que cumplen con datos obtenidos de entidades verdaderas)
se utilizaron tres métodos:
Parseo.
Clonación.
Fuerza bruta.
A continuación se detallan los métodos y los datos que se cargaron con cada uno.
5.1.1. Parseo
Este método consiste en el parseo y reconocimiento de campos de datos dentro de textos
cargados desde algún origen que provea datos reales.
En este proyecto se utilizó la carga por parseo para los datos correspondientes a las
siguientes entidades:
Waypoints.
Terminales.
Tramos.
Itinerarios.
La fuente de información utilizada proviene del sitio http://rfinder.asalink.net, donde se
pueden obtener rutas aéreas en base a un origen y destino dados.
5.1.2. Clonación
Este método consiste en generar una entidad "base" y luego duplicarla tantas veces
como se quiera, cambiando algunos parámetros propios de cada copia en particular.
En este proyecto se utilizó la carga por clonación para los datos correspondientes a las
siguientes entidades:
Viajes.
Unidades (Aviones).
En el caso de los Viajes, se cargó uno para cada vuelo distinto que tiene la aerolínea
ficticia de prueba, y luego se repitió con una frecuencia establecida. Existen vuelos
diarios, cada dos días y semanales, con destinos nacionales e internacionales.
Los datos propios de cada copia que se cambiaron en cada Viaje generado fueron las
Escalas, que poseen la fecha de realización del viaje. Para los demás datos (tarifas,
puntos de programa de recompensas, etc.), se usó información obtenida de páginas de
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 85
aerolíneas, tales como (en orden de mayor a menor uso) American Airlines, United
Airlines, Aerolíneas Argentinas, LAN Argentina, GOL Linhas Aéreas y US Airways. El
dato del costo por unidad de combustible se obtuvo de la página oficial de la IATA.
Para los "costos varios" del Viaje se realizó un cálculo en función de lo que gana cada
integrante del personal de a bordo por viaje, sumado a un costo por reposición de
insumos (en baños, iluminación, etc) y reparación o revisión de la Unidad.
En el caso de las Unidades, se cargaron dos tipos de aviones:
Boeing 737-500: para vuelos de cabotaje.
Boeing 747-400: para vuelos internacionales.
Los datos propios de cada copia de Unidad que se fueron variando son:
Matrícula.
Número de interno.
Número de serie.
Para la información de las Unidades se consultaron varias fuentes, entre las que se
destacan el sitio oficial de Boeing y Airliners.net
5.1.3. Fuerza bruta
Este método consiste en la carga explícita de los datos de cada entidad que queda luego
guardada en el sistema. Se utilizó para la carga de datos en entidades con atributos
altamente independientes entre instancias. Por lo tanto, la cantidad de estas entidades es
reducida respecto de las generadas con los métodos anteriormente descriptos.
En este proyecto se utilizó la carga por fuerza bruta para los datos correspondientes a las
siguientes entidades:
Personas
o Clientes (incluyendo Pasaportes y Contactos).
o Empleados tripulantes.
o Técnicos especialistas.
o Técnicos supervisores.
o Inspectores de calidad.
Servicios.
Roles.
Para las Personas se cargaron datos que podrían ser ciertos, pero no pertenecen a
personas reales. Por ejemplo, para los datos de direcciones se ingresaron calles y
numeraciones reales. Para los teléfonos y códigos postales, se ingresaron valores
acordes a la ciudad de residencia de la Persona. Para los documentos se ingresaron
números aproximados a la fecha de nacimiento.
5.1.4. Realización de la carga
Existen dos métodos posibles para cargar los datos de prueba en la base de datos del
sistema:
Utilizando el script de SQL provisto junto con la instalación: es conveniente
cuando se realice una instalación del sistema o se necesite una carga rápida de
los datos.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 86
Ejecutando el Unit Test denominado ―testStoreAll()‖ presente en la clase
―StoreMaestro‖: es conveniente en casos en los cuales se estén realizando
modificaciones a alguna de las entidades o consultas del sistema
(customizaciones).
5.2. Pruebas de Aceptación de Usuario (UAT)
Listado de pruebas de aceptación del usuario (UAT) de cada User Story, ordenados
según su realización por prioridad y por número de User Story.
Para la correcta ejecución de las siguientes pruebas es necesario que primero se carguen
los datos de prueba provistos en el sistema. Para más información, ver la sección
anterior de Carga de Datos de Prueba.
Para cada una de las pruebas de este documento, se deben realizar los siguientes pasos
antes de su ejecución:
1. Iniciar los servicios (motor de base de datos, servidor de aplicaciones, y servidor
web).
2. Abrir un navegador de Internet.
3. Escribir en la barra de dirección la URL "http://127.0.0.1:8081/sistrans-
aerolineas/" y presionar "Intro".
Siempre que se indique entre comillas un valor para ingresar, debe escribirse el mismo
en el campo correspondiente sin las comillas, a menos que se indique lo contrario.
5.3. Contenido
Por orden de prueba según prioridad en el Product Backlog:
Prueba N°1 (US1)
Prueba N°2 (US10)
Prueba N°3 (US15)
Prueba N°4 (US21)
Prueba N°5 (US20)
Prueba N°6 (US7)
Prueba N°7 (US18)
Prueba N°8 (US6)
Prueba N°9 (US11)
Prueba N°10 (US16)
Prueba N°11 (US17)
Prueba N°12 (US8)
Prueba N°13 (US22)
Prueba N°14 (US2)
Prueba N°15 (US4)
Prueba N°16 (US5)
Prueba N°17 (US3)
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 87
Prueba N°18 (US23)
Prueba N°19 (US12)
Prueba N°20 (US14)
Prueba N°21 (US19)
Por orden de User Story:
Prueba N°1 (US1)
Prueba N°14 (US2)
Prueba N°17 (US3)
Prueba N°15 (US4)
Prueba N°16 (US5)
Prueba N°8 (US6)
Prueba N°6 (US7)
Prueba N°12 (US8)
Prueba N°2 (US10)
Prueba N°9 (US11)
Prueba N°19 (US12)
Prueba N°20 (US14)
Prueba N°3 (US15)
Prueba N°10 (US16)
Prueba N°11 (US17)
Prueba N°7 (US18)
Prueba N°21 (US19)
Prueba N°5 (US20)
Prueba N°4 (US21)
Prueba N°13 (US22)
Prueba N°18 (US23)
Prueba N°1 (US1)
Para dar de alta una Unidad de transporte:
1. Apoyar el puntero del mouse sobre el menú "Flota" y luego hacer click en
"Agregar avión".
2. En el formulario que aparece:
1. En el campo "Nombre" ingresar "AZP".
2. En el campo "Descripción" ingresar "Fabricado por: The Boeing
Company en Seattle, Washington (EE.UU.)".
3. En el campo "Nro de Interno" ingresar "600".
4. En el campo "Matrícula" ingresar "LV-AZP".
5. En el campo "Marca" ingresar "Boeing".
6. En el campo "Modelo" ingresar "747-700".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 88
7. En el campo "Nacionalidad" ingresar "Estados Unidos".
8. En el campo "Año de Fabricación" ingresar "2001".
9. En el campo "Año de Incorporación" ingresar "2005".
10. En el campo "Nro de serie" ingresar "2792".
11. En el campo "Tiene GPS" hacer click para tildar el cuadro.
12. En el campo "Calefacción" hacer click para tildar el cuadro.
13. En el campo "Aire Acondicionado" hacer click para tildar el cuadro.
14. En el campo "Disponible para Alquiler" hacer click para tildar el cuadro.
15. En el campo "Disponible para uso Interno" hacer click para tildar el
cuadro.
16. En el campo "Habilitada" hacer click para tildar el cuadro.
17. En el campo "Cant. Motores" ingresar "4".
18. En el campo "Distancia Recorrida" ingresar "520000" y seleccionar la
medida "KM".
19. En el campo "Velocidad De Crucero" ingresar "950" y seleccionar la
medida "KM_H".
20. En el campo "Consumo Combustible" ingresar "0.0833333" y
seleccionar la medida "KM_LT".
21. Hacer click en el botón "Guardar".
Para modificar una Unidad de transporte:
1. Apoyar el puntero del mouse sobre el menú "Flota" y luego hacer click en
"Listar aviones".
2. De las unidades que aparecen, ubicar la que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En el formulario que aparece:
1. En el campo "Distancia recorrida" eliminar el valor presente e ingresar
"523000", y seleccionar la medida "KM".
2. Hacer click en el botón "Modificar".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 89
Para eliminar una Unidad de transporte:
1. Apoyar el puntero del mouse sobre el menú "Flota" y luego hacer click en
"Listar aviones".
2. De las unidades que aparecen, ubicar la que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En la ventana que aparece, hacer click en el botón "Si".
Prueba N°2 (US10)
Para dar de alta un Cliente:
1. Apoyar el puntero del mouse sobre el menú "Clientes" y luego hacer click en
"Agregar cliente".
2. En el formulario que aparece:
1. En el campo "Titulo" ingresar "Sr.".
2. En el campo "Nombre" ingresar "Ramon".
3. En el campo "Segundo nombre" ingresar "Oscar".
4. En el campo "Apellido" ingresar "Martinez".
5. En el campo "Tipo" ingresar "DNI".
6. En el campo "Número" ingresar "13400987".
7. En el campo "Sexo" seleccionar "MASCULINO".
8. En el campo "Compañía" ingresar "UA Sistemas S.R.L.".
9. En el campo "Domicilio" ingresar "Av. Independencia 1556".
10. En el campo "Ciudad" ingresar "Buenos Aires".
11. En el campo "Código postal" ingresar "C1008ACV".
12. En el campo "País" ingresar "Argentina".
13. En el campo "Correo Electrónico" ingresar
"rmartinez@uasistemas.com.ar".
14. En el campo "Fecha de nacimiento" seleccionar "1957-1 0 -1 1".
15. En el campo "Fecha de incorporación" ingresar "2009-07-09".
16. En el campo "Teléfono Móvil" ingresar "1549461444".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 90
17. En el campo "Teléfono Casa" ingresar "1147361766".
18. En el campo "Pregunta secreta" ingresar "Cual fue la matricula de mi
primer auto?".
19. En el campo "Respuesta secreta" ingresar "ASD723".
20. En el campo "Moneda Preferida" seleccionar "ARS".
21. En el campo "Fecha de baja automática" seleccionar "2014-01-01".
22. Hacer click en el botón "Guardar".
Para modificar un Cliente:
1. Apoyar el puntero del mouse sobre el menú "Clientes" y luego hacer click en
"Listar clientes".
2. De los clientes que aparecen, ubicar el que se ingresó en la primera parte de esta
prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En el formulario que aparece:
1. En el campo "Compañía" eliminar el valor presente.
2. En el campo "E-Mail" eliminar el valor presente e ingresar
"rmartinez@yahoo.com.ar" (sin las comillas).
3. Hacer click en el botón "Modificar".
Para eliminar un Cliente:
1. Apoyar el puntero del mouse sobre el menú "Clientes" y luego hacer click en
"Listar clientes".
2. De los clientes que aparecen, ubicar el que se ingresó en la primera parte de esta
prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En la ventana que aparece, hacer click en el botón "Si".
Prueba N°3 (US15)
Para dar de alta un Viaje:
1. Apoyar el puntero del mouse sobre el menú "Viajes" y luego hacer click en
"Agregar viaje".
2. En el formulario que aparece:
1. En el campo "Nombre" ingresar "Vuelo 1000".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 91
2. En el campo "Descripción" ingresar "Vuelo de Buenos Aires a Mar del
Plata".
3. En el campo "Estado" seleccionar el estado "PROGRAMADO".
4. En el campo "Avión" seleccionar el valor "508: BDL Boeing 737-500".
5. En el campo "Costo Unitario de Combustible" ingresar "2.546223" y
seleccionar la moneda "ARS".
6. En el campo "Unidad Expresada" seleccionar "KG".
7. En el campo "Costos Varios" ingresar "2000" y seleccionar la moneda
"ARS".
8. Hacer click en el botón "Siguiente".
9. Hacer click en el ícono , ubicado al pie de la tabla.
10. En el campo "Terminal" seleccionar "BUENOS AIRES /
AEROPARQUE JORGSA".
11. En el campo "Hora de salida" seleccionar "2010-02-01 12:00".
12. Hacer click en el botón "Agregar".
13. Hacer click en el ícono , ubicado al pie de la tabla (como en el paso
9).
14. En el campo "Terminal" seleccionar "MAR DEL PLATA".
15. En el campo "Hora de llegada" seleccionar "2010-02-01 12:55".
16. Hacer click en el botón "Agregar".
17. Hacer click en el botón "Siguiente".
18. En el campo "Itinerario Principal" seleccionar "Vuelo de SABE a MDP".
19. Hacer click en el botón "Siguiente".
20. Hacer click en el botón "Sugerir tripulación".
21. Hacer click en el botón "Siguiente".
22. En el sector "Servicios previos al abordaje":
1. Seleccionar "Bebida de espera".
2. Hacer click en el botón "Copy".
23. En el sector "Servicios a bordo":
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 92
1. Seleccionar "Almuerzo - Cena".
2. Hacer click en el botón "Copy".
24. Hacer click en el botón "Siguiente".
25. En el campo "Tarifa desde BUENOS AIRES / AEROPARQUE
JORGSA hasta MAR DEL PLATA" seleccionar "Tarifas de Buenos
Aires a Mar del Plata".
26. Hacer click en el botón "Guardar".
Para modificar un Viaje:
1. Apoyar el puntero del mouse sobre el menú "Viajes" y luego hacer click en
"Listar viajes por Nombre".
2. En el sector "Filtro":
1. En el campo "Nombre" ingresar "Vuelo 1000".
2. Hacer click en el botón "Buscar".
3. En el sector "Viajes":
1. Hacer click sobre el ícono correspondiente en la columna "Accion"
del viaje encontrado.
2. En el formulario que aparece:
1. En el campo "Estado" seleccionar "REALIZADO".
2. Hacer click en la solapa "Bitacora"
1. Hacer click en el ícono , ubicado al pie de la tabla.
2. En el formulario que aparece:
1. En el campo "Fecha" seleccionar "2010-02-01
12:10".
2. En el campo "Asunto" ingresar "Desmayo".
3. En el campo "Desarrollo" ingresar "Una pasajera
sufrió un desmayo durante el vuelo. Se le dio
asistencia médica y pudo mejorarse.".
4. Hacer click en el botón "Agregar".
3. Hacer click en el botón "Guardar Bitácora".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 93
Para eliminar un Viaje:
1. Apoyar el puntero del mouse sobre el menú "Viajes" y luego hacer click en
"Listar viajes por Nombre".
2. En el sector "Filtro":
1. En el campo "Nombre" ingresar "Vuelo 1000".
2. Hacer click en el botón "Buscar".
3. En el sector "Viajes":
1. Hacer click sobre el ícono correspondiente en la columna "Accion".
4. En la ventana que aparece, hacer click en el botón "Si".
Prueba N°4 (US21)
Dado que el sistema de pruebas fue desarrollado específicamente para el negocio de
aerolíneas no incorpora el concepto de Ruta. Sin embargo, para cargar los caminos a
seguir, se utilizan los Tramos.
Para dar de alta un Tramo:
1. Apoyar el puntero del mouse sobre el menú "Tramos" y luego hacer click en
"Agregar tramo".
2. En el formulario que aparece:
1. En el campo "Nombre" ingresar "De SABE a EZE".
2. En el campo "Descripción" ingresar "De SABE a EZE".
3. En el campo "Longitud" ingresar "17" y seleccionar la medida "NM".
4. En el campo "Comienzo" seleccionar "SABE".
5. En el campo "Fin" seleccionar "EZE".
6. Hacer click en el botón "Guardar".
Para modificar un Tramo:
1. Apoyar el puntero del mouse sobre el menú "Tramos" y luego hacer click en
"Listar tramos".
2. De los tramos que aparecen, ubicar el que se ingresó en la primera parte de esta
prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En el formulario que aparece:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 94
1. En el campo "Descripción" ingresar "De Aeroparque a Ezeiza.".
2. Hacer click en el botón "Modificar".
Para eliminar un Tramo:
1. Apoyar el puntero del mouse sobre el menú "Tramos" y luego hacer click en
"Listar tramos".
2. De los tramos que aparecen, ubicar el que se ingresó en la primera parte de esta
prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En la ventana que aparece, hacer click en el botón "Si".
Prueba N°5 (US20)
Para comprar un pasaje:
1. Apoyar el puntero del mouse sobre el menú "Pasajes" y luego hacer click en
"Comprar pasaje".
2. En el formulario que aparece:
1. En el campo "Tipo de Documento" ingresar "DNI".
2. En el campo "Nro. de Doc" ingresar "29385482".
3. Hacer click en el botón "Buscar".
4. Hacer click en el botón "Siguiente".
5. En el campo "Origen" seleccionar "BUENOS AIRES / AEROPARQUE
JORGSA".
6. En el campo "Destino" seleccionar "EL CALAFATE".
7. En el campo "Hora de Salida desde" seleccionar "2010-01-15 12:00".
8. En el campo "Hora de Salida hasta" seleccionar "2010-01-17 12:00".
9. Hacer click en el botón "Buscar".
10. En el viaje que aparece, hacer click en el ícono correspondiente en la
columna "Seleccionar".
11. Hacer click en el botón "Siguiente".
12. En el mapa de ubicaciones que aparece, apoyar el puntero del mouse
sobre los asientos y hacer click en la butaca "5A".
13. Hacer click en el botón "Siguiente".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 95
14. En el campo que contiene "Ingrese la forma de pago" ingresar "Efectivo"
(o elegirlo de la lista desplegable).
15. En el campo "Tipo de Pasajero" seleccionar "ADULTO".
16. Hacer click en el botón "Calcular Precio".
17. Hacer click en el botón "Comprar".
18. Tomar nota del campo "Record Locator" indicado en el formulario que
aparece, para utilizarlo en la prueba N°19 (US12) y/o en la prueba
N°21 (US19).
19. Hacer click en el botón "Aceptar".
Para reservar un pasaje:
1. Apoyar el puntero del mouse sobre el menú "Pasajes" y luego hacer click en
"Comprar pasaje".
2. En el formulario que aparece:
1. En el campo "Tipo de Documento" ingresar "DNI".
2. En el campo "Nro. de Doc" ingresar "26898237".
3. Hacer click en el botón "Buscar".
4. Hacer click en el botón "Siguiente".
5. En el campo "Origen" seleccionar "EZEIZA".
6. En el campo "Destino" seleccionar "RIO DE JANEIRO / GALEAO -
ANTOSB".
7. En el campo "Hora de Salida desde" seleccionar "2010-01-22 12:00".
8. En el campo "Hora de Salida hasta" seleccionar "2010-01-23 12:00".
9. Hacer click en el botón "Buscar".
10. En el viaje que aparece, hacer click en el ícono correspondiente en la
columna "Seleccionar".
11. Hacer click en el botón "Siguiente".
12. En el mapa de ubicaciones que aparece, apoyar el puntero del mouse
sobre los asientos y hacer click en la butaca "7A".
13. Hacer click en el botón "Siguiente".
14. En el campo que contiene "Ingrese la forma de pago" ingresar "Efectivo"
(o elegirlo de la lista desplegable).
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 96
15. En el campo "Tipo de Pasajero" seleccionar "ADULTO".
16. Hacer click en el botón "Calcular Precio".
17. Hacer click en el botón "Reservar".
18. Hacer click en el botón "Aceptar".
Para confirmar un pasaje:
1. Apoyar el puntero del mouse sobre el menú "Pasajes" y luego hacer click en
"Listar Pasajes por Cliente".
2. En el formulario que aparece:
1. En el campo "Tipo de Documento" ingresar "DNI".
2. En el campo "Nro. de Doc" ingresar "26898237".
3. En el campo "Estado Pasaje a Buscar" seleccionar "Reservado".
4. Hacer click en el botón "Listar Pasajes".
5. Entre los pasajes que aparecen, confirmar el reservado en la prueba
anterior ("Vuelo 500", ubicación "7A") haciendo click en el ícono
correspondiente en la columna "Acción".
6. En la ventana que aparece, hacer click en el botón "Si".
Para cancelar un pasaje:
1. Apoyar el puntero del mouse sobre el menú "Pasajes" y luego hacer click en
"Listar Pasajes por Cliente".
2. En el formulario que aparece:
1. En el campo "Tipo de Documento" ingresar "DNI".
2. En el campo "Nro. de Doc" ingresar "26898237".
3. En el campo "Estado Pasaje a Buscar" seleccionar "Vendido".
4. Hacer click en el botón "Listar Pasajes".
5. Entre los pasajes que aparecen, cancelar el confirmado en la prueba
anterior ("Vuelo 500", ubicación "7A") haciendo click en el ícono
correspondiente en la columna "Acción".
6. En la ventana que aparece, hacer click en el botón "Si".
Prueba N°6 (US7)
Para asignar una tripulación a un Viaje:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 97
1. Realizar el alta de un Viaje descrita en la prueba N°3 (US15) hasta el paso 2.19
inclusive.
2. Hacer click sobre el campo Tripulante y mantener presionado el botón del
mouse.
3. Apoyar el cursor sobre el valor "25.002: Sr. Rodolfo Gustavo Santillan" y soltar
el botón del mouse.
4. En el sector "Roles que cumplirá en el Viaje":
1. Seleccionar "Capitán".
2. Hacer click en el botón "Copy".
5. Hacer click en el botón "Agregar Tripulante".
6. Hacer click sobre el campo Tripulante y mantener presionado el botón del
mouse.
7. Apoyar el cursor sobre el valor "25.005: Sr. Leonardo Jose Ibanez" y soltar el
botón del mouse.
8. En el sector "Roles que cumplirá en el Viaje":
1. Seleccionar "Copiloto".
2. Hacer click en el botón "Copy".
9. Hacer click en el botón "Agregar Tripulante".
10. Hacer click sobre el campo Tripulante y mantener presionado el botón del
mouse.
11. Apoyar el cursor sobre el valor "24.001: Sra. Silvia Elba Ceballos" y soltar el
botón del mouse.
12. En el sector "Roles que cumplirá en el Viaje":
1. Seleccionar "Comisario de a bordo / Sobrecargo".
2. Hacer click en el botón "Copy".
13. Hacer click en el botón "Agregar Tripulante".
14. Hacer click sobre el campo Tripulante y mantener presionado el botón del
mouse.
15. Apoyar el cursor sobre el valor "24.008: Srta. Nancy Fabiana Galvan" y soltar el
botón del mouse.
16. En el sector "Roles que cumplirá en el Viaje":
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 98
1. Seleccionar "Auxiliar de vuelo (TCP)".
2. Hacer click en el botón "Copy".
17. Hacer click en el botón "Agregar Tripulante".
18. Hacer click sobre el campo Tripulante y mantener presionado el botón del
mouse.
19. Apoyar el cursor sobre el valor "24.004: Srta. Lucia Julia Leguizamon" y soltar
el botón del mouse.
20. En el sector "Roles que cumplirá en el Viaje":
1. Seleccionar "Auxiliar de vuelo (TCP)".
2. Hacer click en el botón "Copy".
21. Hacer click en el botón "Agregar Tripulante".
22. Hacer click sobre el campo Tripulante y mantener presionado el botón del
mouse.
23. Apoyar el cursor sobre el valor "24.002: Srta. Isabel Maria Olmos" y soltar el
botón del mouse.
24. En el sector "Roles que cumplirá en el Viaje":
1. Seleccionar "Auxiliar de vuelo (TCP)".
2. Hacer click en el botón "Copy".
25. Hacer click en el botón "Agregar Tripulante".
26. Hacer click en el botón "Siguiente".
27. Realizar los pasos desde el 2.22 en adelante del alta de un Viaje, en la prueba
N°3 (US15).
Prueba N°7 (US18)
Para dar de alta un Itinerario:
1. Apoyar el puntero del mouse sobre el menú "Itinerarios" y luego hacer click en
"Agregar itinerario".
2. En el formulario que aparece:
1. En el campo "Nombre" ingresar "Vuelo de SABE a GBE".
2. En el campo "Descripción" ingresar "Vuelo de Aeroparque a General
Belgrano".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 99
3. En el sector "Tramos":
1. Seleccionar "De SABE a GBE".
2. Hacer click en el botón "Copy".
4. Hacer click en el botón "Guardar".
Para modificar un Itinerario:
1. Apoyar el puntero del mouse sobre el menú "Itinerarios" y luego hacer click en
"Listar itinerarios".
2. De los itinerarios que aparecen, ubicar el que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En el formulario que aparece:
1. En el campo "Descripción" eliminar el valor presente e ingresar "Vuelo
de Aeroparque a General Belgrano, provincia de Buenos Aires".
2. Hacer click en el botón "Modificar".
Para eliminar un Itinerario:
1. Apoyar el puntero del mouse sobre el menú "Itinerarios" y luego hacer click en
"Listar itinerarios".
2. De los itinerarios que aparecen, ubicar el que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En la ventana que aparece, hacer click en el botón "Si".
Prueba N°8 (US6)
Para dar de alta un Empleado tripulante:
1. Apoyar el puntero del mouse sobre el menú "Empleados" y luego hacer click en
"Agregar Tripulante".
2. En el formulario que aparece:
1. En el campo "Nro. de Legajo" ingresar "25100".
2. En el campo "Titulo" ingresar "Sr.".
3. En el campo "Nombre" ingresar "Juan".
4. En el campo "Segundo nombre" ingresar "Amadeo".
5. En el campo "Apellido" ingresar "Pereyra".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 100
6. En el campo "Tipo" ingresar "DNI".
7. En el campo "Número" ingresar "17822933".
8. En el campo "Sexo" seleccionar "MASCULINO".
9. En el campo "Compañía" ingresar "Sistrans".
10. En el campo "Domicilio" ingresar "Av. San Juan 2448".
11. En el campo "Ciudad" ingresar "Buenos Aires".
12. En el campo "Código postal" ingresar "C1009BDD".
13. En el campo "País" ingresar "Argentina".
14. En el campo "Correo Electrónico" ingresar "jpereyra@sistrans.com.ar".
15. En el campo "Fecha de nacimiento" seleccionar "1965-11-12".
16. En el campo "Fecha de incorporación" ingresar "2009-08-19".
17. En el campo "Teléfono Móvil" ingresar "1549233812".
18. En el campo "Teléfono Casa" ingresar "1147673443".
19. En el campo "Horas de Vuelo" ingresar "1200".
20. En el sector "Roles habilitados":
1. Mantener presionada la tecla "Ctrl".
2. Hacer click en la opción "Piloto".
3. Hacer click en la opción "Copiloto".
4. Hacer click en la opción "Deadhead".
5. Hacer click en la opción "Capitan".
6. Soltar la tecla "Ctrl".
7. Hacer click en el botón "Copy".
21. Hacer click en el botón "Guardar".
Para modificar un Empleado tripulante:
1. Apoyar el puntero del mouse sobre el menú "Empleados" y luego hacer click en
"Listar empleados".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 101
2. De los empleados que aparecen, ubicar el que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En el formulario que aparece:
1. En el campo "Horas de Vuelo" eliminar el valor presente e ingresar
"1450".
2. En el sector "Roles habilitados":
1. Seleccionar "Deadhead".
2. Hacer click en el botón "Remove".
3. Hacer click en el botón "Modificar".
Para eliminar un Empleado tripulante:
1. Apoyar el puntero del mouse sobre el menú "Empleados" y luego hacer click en
"Listar empleados".
2. De los empleados que aparecen, ubicar el que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En la ventana que aparece, hacer click en el botón "Si".
NOTA: para poder dar de alta, modificar o eliminar un empleado de otro tipo (Técnico
Supervisor, Técnico Especialista, Inspector de Calidad, etc.), se deben seguir los
mismos pasos descriptos, con la excepción de:
En el paso 1, elegir el menú correspondiente al tipo de empleado a dar de alta.
Obviar los pasos donde se nombre el campo "Horas de Vuelo".
Prueba N°9 (US11)
Para validar un Pasaporte:
1. Realizar el alta de un Cliente descrita en la prueba N°2 (US10) hasta el paso
2.21 inclusive.
2. En el sector "Pasaporte":
1. En el campo "Numero de Serie" ingresar "568288843".
2. En el campo "Nacionalidad" ingresar "Argentina".
3. En el campo "Tipo" seleccionar "COMUN".
4. En el campo "Fecha de vencimiento" seleccionar "2012-05-14".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 102
5. En el campo "Linea 1 MRP" ingresar
"P<ARGMARTINEZ<<RAMON<OSCAR<<<<<<<<<<<<<<<<<<".
6. En el campo "Linea 2 MRP" ingresar
"5682888435ARG5710115M1205140<<<<<<<<<<<<<<08".
7. Hacer click en el botón "Guardar".
Prueba N°10 (US16)
Para cambiar las políticas de realización de un Viaje:
1. Editar el archivo "PoliticaRealizacionViajes.drl":
1. Agregar al final las siguientes instrucciones:
2. rule "Demora de prueba." when
$viaje: Viaje()
eval($viaje.cantidadDeDiasFaltantes() > 5)
then
$viaje.setEstado(EstadoViaje.DEMORADO);
end
3. Guardar el archivo.
4. Ejecutar las reglas.
Prueba N°11 (US17)
Para que el sistema sugiera una tripulación:
1. Realizar el alta de un Viaje descrita en la prueba N°3 (US15) hasta el paso 2.19
inclusive.
2. Hacer click en el botón "Sugerir Tripulación".
3. Realizar los pasos desde el 2.21 en adelante del alta de un Viaje, en la prueba
N°3 (US15).
Prueba N°12 (US8)
Para que se carguen en el sistema datos desde un sistema externo de capacitación de
prueba, compilar y ejecutar el proyecto "sistrans-extractor", según lo indicado en
Deployment y Ejecución de sistrans-ejb en la sección de tutoriales.
Prueba N°13 (US22)
Para estimar las unidades a utilizar, basándose en información histórica:
1. Apoyar el puntero del mouse sobre el menú "Ejecutivos" y luego hacer click en
"Cantidad de Unidades utilizadas".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 103
2. En el formulario que aparece:
1. En el campo "Fecha Desde" seleccionar "2010-01-01 00:00".
2. En el campo "Fecha Hasta" seleccionar "2010-02-01 00:00".
3. En el campo "Agrupado por" seleccionar "Dia".
4. Hacer click en el botón "Buscar".
Prueba N°14 (US2)
Para iniciar el proceso de reparaciones:
1. Realizar los pasos descritos en Deployment y Ejecución de sistrans-procesos-
reparaciones en la sección de Tutoriales.
2. Apoyar el puntero del mouse sobre el menú "Reparaciones" y luego hacer click
en "Iniciar Problema".
3. En el formulario que aparece:
1. En el campo "Avion" seleccionar "507: BDK Boeing 737-500".
2. En el campo "Descripción del problema" ingresar "El sensor del tren de
aterrizaje muestra una lectura errónea.".
3. En el sector "Empleado iniciador del Problema":
1. En el campo "Nro de Legajo" ingresar "25004".
2. Hacer click en el botón "Buscar".
4. En el sector "Técnico Supervisor de la Revisión":
1. En el campo "Nro de Legajo" ingresar "23000".
2. Hacer click en el botón "Buscar".
5. Hacer click en el botón "Iniciar Problema".
Prueba N°15 (US4)
Para dar de alta un Problema:
1. Realizar los pasos descritos en la prueba N°14 (US2).
Para mostrar los Problemas registrados en el sistema:
1. Apoyar el puntero del mouse sobre el menú "Reparaciones" y luego hacer click
en "Listar Problemas".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 104
Prueba N°16 (US5)
Para asignar Técnicos a un Problema:
1. Realizar los pasos descritos en la prueba N°14 (US2).
2. Abrir un navegador de Internet adicional (o una nueva solapa en el que se usó en
los pasos anteriores).
3. Escribir en la barra de dirección la URL "http://127.0.0.1:8080/jbpm-console/" y
presionar "Intro".
4. En la página que aparece:
1. En el sector "Log In":
1. En el campo "User Name" ingresar "manager".
2. En el campo "Password" ingresar "manager".
3. Hacer click en el botón "Log In".
2. En la página que aparece:
1. En el campo "Manage" seleccionar "All Tasks".
3. En la página que se actualiza:
1. Ubicar la tarea con nombre "Inspeccionar" y hacer click en el
vínculo "Start" correspondiente de la columna "Actions".
4. En la página que se actualiza:
1. Ubicar la tarea con nombre "Inspeccionar" y hacer click en el
vínculo "Examine" correspondiente de la columna "Actions".
5. En la página que aparece:
1. En el sector "Inspeccionar":
1. En el campo "Comentario" ingresar "Se encontró que el
indicador de tren de aterrizaje bajo queda siempre
encendido.".
2. En el campo "Sigue el problema?" hacer click en "Si".
3. En el campo "Puede seguir usandose la Unidad?" hacer
click en "No".
4. En el campo "Actions" hacer click en el botón "Save".
5. En el campo "Manage" seleccionar "All Tasks".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 105
6. En la página que aparece:
1. Ubicar la tarea con nombre "Inspeccionar" y hacer click en el
vínculo "End" correspondiente de la columna "Actions".
7. En la página que se actualiza:
1. Ubicar la tarea con nombre "Emitir pedido de reparacion" y hacer
click en el vínculo "Start" correspondiente de la columna
"Actions".
8. En la página que se actualiza:
1. Ubicar la tarea con nombre "Emitir pedido de reparacion" y hacer
click en el vínculo "Examine" correspondiente de la columna
"Actions".
9. En la página que aparece:
1. En el sector "Emitir pedido de reparación":
1. En el campo "Comentario" ingresar "Pedido de reparación
emitido y entregado.".
2. En el campo "Actions" hacer click en el botón "Save".
3. En el campo "Manage" seleccionar "All Tasks".
10. En la página que se actualiza:
1. Ubicar la tarea con nombre "Emitir pedido de reparacion" y hacer
click en el vínculo "End" correspondiente de la columna
"Actions".
11. En la página que se actualiza:
1. Ubicar la tarea con nombre "Asignar lista de tecnicos" y hacer
click en el vínculo "Start" correspondiente de la columna
"Actions".
12. En la página que se actualiza:
1. Ubicar la tarea con nombre "Asignar lista de tecnicos" y hacer
click en el vínculo "Examine" correspondiente de la columna
"Actions".
13. En la página que aparece:
1. En el sector "Asignar lista de tecnicos":
1. En el campo "Comentario" ingresar "Técnicos
especialistas.".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 106
2. En el campo "Lista de Técnicos" ingresar "22001,22003".
3. En el campo "Actions" hacer click en el botón "Save".
4. En el campo "Manage" seleccionar "All Tasks".
14. En la página que se aparece:
1. Ubicar la tarea con nombre "Asignar lista de tecnicos" y hacer
click en el vínculo "End" correspondiente de la columna
"Actions".
Prueba N°17 (US3)
Para emitir un pedido de revisión:
1. Realizar los pasos descritos en Deployment y Ejecución de sistrans-procesos-
reparaciones en la sección de Tutoriales.
2. Apoyar el puntero del mouse sobre el menú "Reparaciones" y luego hacer click
en "Iniciar Revision".
3. En el formulario que aparece:
1. En el campo "Avión" seleccionar el valor "508: BDL Boeing 737-500".
2. En el sector "Técnico Supervisor de la Revisión":
1. En el campo "Nro. de Legajo" ingresar "23000".
2. Hacer click en el botón "Buscar".
3. Hacer click en el botón "Iniciar Revisión".
Prueba N°18 (US23)
Para generar un reporte de cantidad de Viajes realizados:
1. Apoyar el puntero del mouse sobre el menú "Ejecutivos" y luego hacer click en
"Cantidad de Viajes realizados".
2. En el formulario que aparece:
1. Hacer click en la opción "Por Origen".
2. En el campo "Origen" seleccionar "BUENOS AIRES / AEROPARQUE
JORGSA".
3. Hacer click en el botón "Buscar".
Para generar un reporte de cantidad de Pasajes vendidos:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 107
1. Apoyar el puntero del mouse sobre el menú "Ejecutivos" y luego hacer click en
"Cantidad de Pasajes vendidos".
2. En el formulario que aparece:
1. Hacer click en la opción "Por Destino".
2. En el campo "Destino" seleccionar "MAR DEL PLATA".
3. Hacer click en el botón "Buscar".
Para generar un reporte de Viajes cancelados:
1. Apoyar el puntero del mouse sobre el menú "Ejecutivos" y luego hacer click en
"Cantidad de Pasajes vendidos".
2. En el formulario que aparece:
1. En el campo "Fecha Desde" seleccionar "2010-01-01 00:00".
2. En el campo "Fecha Hasta" seleccionar "2010-02-01 00:00".
3. Hacer click en el botón "Buscar".
Para generar un reporte de ganancias obtenidas:
1. Apoyar el puntero del mouse sobre el menú "Ejecutivos" y luego hacer click en
"Ganancias obtenidas".
2. En el formulario que aparece:
1. En el campo "Fecha Desde" seleccionar "2010-01-01 00:00".
2. En el campo "Fecha Hasta" seleccionar "2010-01-15 00:00".
3. En el campo "Moneda" seleccionar "ARS".
4. En el campo "Agrupado por" hacer click en "Dia".
5. Hacer click en el botón "Buscar".
Para generar un reporte de inversiones estimadas para Viajes:
1. Apoyar el puntero del mouse sobre el menú "Ejecutivos" y luego hacer click en
"Inversion estimada para Viajes".
2. En el formulario que aparece:
1. En el campo "Fecha Desde" seleccionar "2010-01-01 00:00".
2. En el campo "Fecha Hasta" seleccionar "2010-01-15 00:00".
3. En el campo "Moneda" seleccionar "ARS".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 108
4. En el campo "Ajuste [%]" ingresar "20".
5. En el campo "Agrupado por" hacer click en "Dia".
6. Hacer click en el botón "Buscar".
Prueba N°19 (US12)
Para realizar el check-in:
1. Realizar los pasos descritos en la prueba N°5 (US20), en la parte donde se
indica cómo comprar un Pasaje.
2. Apoyar el puntero del mouse sobre el menú "Clientes" y luego hacer click en
"Check-in".
3. En el formulario que aparece:
1. En el campo "Nombre" ingresar "Carlos".
2. En el campo "Apellido" ingresar "Robledo".
3. En el campo "Record Locator" ingresar el obtenido en el paso 1 de esta
prueba.
4. Hacer click en el botón "Buscar Pasaje".
5. En el sector "Equipajes", dentro del sector "Pasaje" que se completa:
1. Hacer click en el ícono , ubicado al pie de la tabla.
2. En el formulario que aparece:
1. En el campo "Tipo de Equipaje" seleccionar "VALIJA".
2. En el campo "Peso" ingresar "25", y seleccionar la medida
"KG".
3. Hacer click en el botón "Agregar".
3. Hacer click en el ícono , ubicado al pie de la tabla.
4. En el formulario que aparece:
1. En el campo "Tipo de Equipaje" seleccionar
"BOLSO_DE_MANO".
2. Hacer click en el botón "Agregar".
5. Hacer click en el botón "Realizar Check-in".
4. En el formulario que aparece, hacer clic en el botón "Aceptar".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 109
Prueba N°20 (US14)
Para agregar una Recompensa al programa de millas:
1. Apoyar el puntero del mouse sobre el menú "Clientes", después en
"Recompensas" y luego hacer click en "Agregar Recompensa".
2. En el formulario que aparece:
1. En el campo "Nombre" ingresar "Viaje al exterior (menos de 500Km)".
2. En el campo "Descripción" ingresar "Un viaje de ida hacia el exterior de
Argentina (hasta de 500 Km) en clase Turista, en temporada baja.".
3. En el campo "Costo" ingresar "500" y seleccionar la moneda "ARS".
4. En el sector "Valores de canje de Recompensa:
1. Hacer click en el ícono , ubicado al pie de la tabla.
2. En el formulario que aparece:
1. En el campo "Puntos necesarios" ingresar "1200".
2. Hacer click en el botón "Agregar".
5. Hacer click en el botón "Guardar".
Para modificar una Recompensas del programa de millas:
1. Apoyar el puntero del mouse sobre el menú "Clientes", después en
"Recompensas" y luego hacer click en "Listar Recompensas".
2. De las recompensas que aparecen, ubicar la que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion".
3. En el formulario que aparece:
1. En el sector "Valores de canje de Recompensa":
1. Hacer click en el ícono , ubicado al pie de la tabla.
2. En el formulario que aparece:
1. En el campo "Puntos necesarios" ingresar "1000".
2. En el campo "Dinero necesario" ingresar "200" y
seleccionar la moneda "ARS".
3. Hacer click en el botón "Agregar".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 110
2. Hacer click en el botón "Modificar".
Para eliminar una Recompensa del programa de millas:
1. Apoyar el puntero del mouse sobre el menú "Clientes", después en
"Recompensas" y luego hacer click en "Listar Recompensas".
2. De las recompensas que aparecen, ubicar la que se ingresó en la primera parte de
esta prueba (utilizar el botón "Siguiente") y hacer click sobre el ícono
correspondiente en la columna "Accion". En la ventana que aparece, hacer click
en el botón "Si".
Prueba N°21 (US19)
Para consultar el estado de un pasajero:
1. Realizar los pasos descritos en la prueba N°5 (US20), en la parte donde se
indica cómo comprar un Pasaje.
2. Apoyar el puntero del mouse sobre el menú "Pasajes" y luego hacer click en
"Mostrar estado".
3. En el formulario que aparece:
1. En el campo "Nombre" ingresar "Carlos".
2. En el campo "Apellido" ingresar "Robledo".
3. En el campo "Record Locator" ingresar el obtenido en el paso 1 de esta
prueba.
4. Hacer click en el botón "Mostrar estado".
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 111
6. Tutoriales
6.1. Tecnología y Herramientas
A continuación se enumeran cada una de las tecnologías y herramientas utilizadas en el
proyecto, desde entornos de desarrollo hasta librerías, aplicaciones de diagramas y
administradores de proyecto.
Assembla: http://www.assembla.com/
o Administrador de Proyecto web
o Repositorio SVN
o Wiki
Tortoise SVN: http://tortoisesvn.tigris.org/
o Cliente SVN para Windows
Subclipse: http://subclipse.tigris.org/
o Plugin para Eclipse que funciona como cliente de SVN
Eclipse: http://www.eclipse.org/
o IDE de desarrollo
Java SE 6 + Java EE 5: http://java.sun.com/javase/downloads/index.jsp
o Plataforma de Desarrollo
Java EE 5 + EJB 3: http://java.sun.com/javase/downloads/index.jsp
o Plataforma de Desarrollo
JPA + Hibernate: https://www.hibernate.org/
o ORM de Persistencia
MySQL: http://www.mysql.com/
o SGBD: Sistema de Gestión de Base de Datos
Maven 2: http://maven.apache.org/
o Administrador de Proyecto a nivel código
JBoss AS: http://www.jboss.org/jbossas/
o Servidor de Aplicaciones – Contenedor de EJBs
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 112
Apache Tomcat: http://tomcat.apache.org/
o Servidor de Aplicaciones Web – Contenedor de Servlets
JBoss jBPM: http://www.jboss.com/products/jbpm/
o Motor de Workflows (para el Módulo Reparaciones MREP)
JBoss Drools: http://www.jboss.org/drools/
o Motor de Reglas de Negocio
Rich Faces: http://www.jboss.org/richfaces
o Para la aplicación web DEMO de Aerolíneas
Apache Commons: http://commons.apache.org/
o Conjunto de librerías Java para facilitar la construcción del código
Google Docs: http://docs.google.com/
o Para administrar los Backlogs y los Burndown Charts
Dia: http://projects.gnome.org/dia/
o Para los diagramas UML y otros
StarUML: http://staruml.sourceforge.net/en/
o Para los diagramas de estado
Microsoft Office Visio 2007
o Para los diagramas de secuencia
6.2. Deployment y ejecución de sistrans-ejb
Paso 1:
Bajar el JBoss AS 5.0.1.GA desde:
http://www.jboss.org/jbossas/downloads/
El Application Server de JBoss no trae instalador. Simplemente se descomprime la
carpeta bajada en donde se quiera tener el servidor.
Paso 2:
Copiar las librerías necesarias por JBoss siguiendo los pasos descriptos en la
sección: Qué copiar en el Lib de JBoss.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 113
Paso 3:
Ir al repositorio:
/trunk/Fase2/Codigo/configuracion
Tomar el Data Source llamado sistrans-ds.xml y editarlo para que el usuario y
contraseña de la base de datos especificada coincida con la instalada en el sistema.
Luego copiar el archivo en la carpeta de JBoss:
/server/default/deploy
Mediante ese Data Source, la aplicación podrá conectarse a la base de datos.
Paso 4:
Ir al directorio del repositorio /trunk/Fase2/Codigo/jbossall-client-5.0.1.GA y copiar
el archivo jbossall-client-5.0.1.GA.jar en la carpeta del repositorio de librerías local:
[HOME_USUARIO]\.m2\repository\org\jboss\client\jbossall-client\5.0.1.GA (crear
los directorios que no existan).
Paso 5:
Ir al proyecto del repositorio /trunk/Fase2/Codigo/sistrans, compilarlo y empaquetarlo
con mvn clean install.
Paso 6:
Se habrá generado la carpeta target. Ahí dentro, tendremos el jar listo para deployar en
Jboss. Copiar el archivo a la carpeta de JBoss: /server/default/deploy.
Paso 7:
Arrancar el JBoss desde la carpeta bin con el comando run.bat en Windows y run.sh
en Linux.
6.3. Deployment y ejecución de la DEMO: sistrans-aerolineas
Paso 1:
Bajar el Apache Tomcat desde:
http://tomcat.apache.org/download-60.cgi
Paso 2:
Realizar la instalación, procurando que el puerto TCP en el cual se instale el servidor
sea el 8081.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 114
Paso 3:
Ir al proyecto del repositorio /trunk/Fase2/Codigo/sistrans y empaquetarlo con mvn
assembly:assembly. Ir al directorio del repositorio /trunk/Fase2/Codigo/sistrans-ejb
y empaquetarlo con assembly:assembly.
Paso 4:
Ir al directorio /trunk/Fase2/Codigo/sistrans/target y copiar el archivo sistrans-dto-
X.X.X-client.jar en la carpeta del repositorio de librerías local:
[HOME_USUARIO]\.m2\repository\ar\uba\fi\tprof\sistrans\sistrans-dto-
X.X.X (crear los directorios que no existan).
Cambiar el nombre del archivo copiado en el repositorio para que se llame sistrans-dto-
X.X.X.jar.
Hacer lo mismo con sistrans-ejb-client del proyecto sistrans-ejb.
Paso 5:
Ir al proyecto del repositorio /trunk/Fase2/Codigo/sistrans-aerolineas y generar el
archivo WAR:
1. Ejecutar el script deleteLibs.bat (en Windows) o deleteLibs.sh (en Unix).
2. Ejecutar el comando mvn war:inplace.
3. Ejecutar el comando mvn clean install.
Paso 6:
Se habrá generado la carpeta target. Ahí dentro, tendremos el war listo para deployar en
Tomcat: sistrans-aerolineas.war. Copiar el archivo a la carpeta de Tomcat: /webapp.
Paso 7:
Arrancar el Tomcat desde la carpeta bin con el comando startup.bat en Windows y
startup.sh en Linux.
6.4. Instalación de Maven2
Paso 1: Descargar Maven2
La versión actual de Maven2 es 2.0.10. Usaremos esta versión.
Nos dirigimos a la página oficial de descarga18
y descargamos el apache-maven-2.0.10-
bin.zip desde cualquier mirror que seleccionemos.
Paso 2: Instalación
18 http://maven.apache.org/download.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 115
En la misma página oficial de descarga tenemos instrucciones de instalación para los
sistemas operativos Windows 2000/XP y cualquiera de los basados en Unix, como
Linux, Solaris o Mac OS X.
Advertencia: Ojo que esta guía de instalación no incluye Windows Vista. Puede
suceder que Windows Vista traiga problemas de permisos a la hora de instalar y
ejecutar los comandos de Maven. Windows Vista toma las carpetas y archivos
ocultos como protegidos y también los archivos y carpetas que empiezan con
punto. Si se va a usar Windows Vista habría que prestarle atención a este detalle
no menor.
A continuación se incluyen las instrucciones de la página:
Windows 2000/XP
1. Unzip the distribution archive, i.e. apache-maven-2.0.10-bin.zip to the directory you
wish to install Maven 2.0.10. These instructions assume you chose C:\Program
Files\Apache Software Foundation. The subdirectory apache-maven-2.0.10 will be
created from the archive.
2. Add the M2_HOME environment variable by opening up the system properties
(WinKey + Pause), selecting the "Advanced" tab, and the "Environment Variables"
button, then adding the M2_HOME variable in the user variables with the value
C:\Program Files\Apache Software Foundation\apache-maven-2.0.10. Be sure to omit
any quotation marks around the path even if it contains spaces. Note: For Maven <
2.0.9, also be sure that the M2_HOME doesn't have a '\' as last character.
3. In the same dialog, add the M2 environment variable in the user variables with the
value %M2_HOME%\bin.
4. Optional: In the same dialog, add the MAVEN_OPTS environment variable in the
user variables to specify JVM properties, e.g. the value -Xms256m -Xmx512m. This
environment variable can be used to supply extra options to Maven.
5. In the same dialog, update/create the Path environment variable in the user variables
and prepend the value %M2% to add Maven available in the command line.
6. In the same dialog, make sure that JAVA_HOME exists in your user variables or in
the system variables and it is set to the location of your JDK, e.g. C:\Program
Files\Java\jdk1.5.0_02 and that %JAVA_HOME%\bin is in your Path environment
variable.
7. Open a new command prompt (Winkey + R then type cmd) and run mvn --version to
verify that it is correctly installed.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 116
Unix-based Operating Systems (Linux, Solaris and Mac OS X)
1. Extract the distribution archive, i.e. apache-maven-2.0.10-bin.tar.gz to the directory
you wish to install Maven 2.0.10. These instructions assume you chose
/usr/local/apache-maven. The subdirectory apache-maven-2.0.10 will be created from
the archive.
2. In a command terminal, add the M2_HOME environment variable, e.g. export
M2_HOME=/usr/local/apache-maven/apache-maven-2.0.10.
3. Add the M2 environment variable, e.g. export M2=$M2_HOME/bin.
4. Optional: Add the MAVEN_OPTS environment variable to specify JVM properties,
e.g. export MAVEN_OPTS="-Xms256m -Xmx512m". This environment variable can
be used to supply extra options to Maven.
5. Add M2 environment variable to your path, e.g. export PATH=$M2:$PATH.
6. Make sure that JAVA_HOME is set to the location of your JDK, e.g. export
JAVA_HOME=/usr/java/jdk1.5.0_02 and that $JAVA_HOME/bin is in your PATH
environment variable.
7. Run mvn --version to verify that it is correctly installed.
6.5. Qué copiar en la carpeta “lib” del JBoss
Para ejecutar correctamente todos los EJBs de SISTRANS en JBoss 5.0.1.GA, son
requeridas algunas bibliotecas, que se deben copiar en el directorio ―lib‖ del JBoss AS
que se esté utilizando.
Por ejemplo, si el AS que se usa es el default, las bibliotecas se copiarán en:
[JBOSS_DIR]/server/default/lib.
Las bibliotecas requeridas por SISTRANS son:
Conector MySQL:
mysql-connector-java-5.1.7-bin.jar (descargable
desde http://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-
5.1.7.zip/from/pick).
Apache Commons-lang:
commons-lang-2.4.jar (descargable desde
http://archive.apache.org/dist/commons/lang/binaries/commons-lang-2.4-
bin.zip).
JBoss Drools y dependencias que necesita (todo descargable desde
http://jboss.org/drools/downloads.html):
antlr-runtime-3.11.jar
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 117
drools-api-5.0.1.jar
drools-compiler-5.0.1.jar
drools-core-5.0.1.jar
mvel2-2.0.10.jar
Dependencias de Apache Commons y de la json-lib para el correcto funcionamiento del
Eager Loader del lado del servidor:
ezmorph-1.0.6.jar (descargable desde
http://sourceforge.net/projects/ezmorph/files/ezmorph/ezmorph-1.0.6/ezmorph-
1.0.6.jar/download)
json-lib-2.2.3-jdk15.jar (descargable desde http://sourceforge.net/projects/json-
lib/files/json-lib/json-lib-2.2.3/json-lib-2.2.3-jdk15.jar/download)
commons-beanutils-core-1.8.0.jar (descargable desde
http://archive.apache.org/dist/commons/beanutils/binaries/commons-beanutils-
1.8.0-bin.zip)
Dependencia con la capa de dominio de sistrans:
sistrans-X.X.X.jar (generar con mvn clean install en el proyecto ―sistrans‖)
6.6. Instalación de JBPM 3.3.1
Paso 1: Ejecutar Instalador
Por empezar descargaremos el jbpm-installer-3.3.1.GA del siguiente link:
http://sourceforge.net/projects/jbpm/files/f%29%20jBPM%20jPDL%203/jbpm-jpdl-
3.3.1.GA/jbpm-installer-3.3.1.GA.jar/download
Luego, ejecutaremos el jar (java -jar jbpm-installer-3.3.1.GA en una consola o doble
click sobre el archivo si ya tenemos configurado que una máquina virtual Java abra este
tipo de archivos).
El instalador creará una carpeta jbpm-3.3.1 con el código fuente, el GPD (plugin de
Eclipse), la documentación, scripts para la base de datos, ejemplos, librerías y archivos
de configuración.
En la instalación se pedirán cuatro cosas que son de importancia:
La ruta donde se quiere guardar esta carpeta
La ruta donde se encuentra el HOME del JBoss AS 5.0.1 (esto es porque
deployará algunas aplicaciones que luego usaremos)
La base de datos que usaremos (debemos elegir MySQL)
Qué consola jbpm se quiere instalar: IMPORTANTE: Instalar sólo la consola
JSF; NO INSTALAR LA CONSOLA GWT.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 118
Paso 2: Ejecutar script para la creación de tablas y roles de jbpmdb
En el repositorio del proyecto SISTRANS, en Fase2/Codigo/configuracion/jbpm-
3.3.1-instalacion, se encuentra el archivo script.sql para crear el esquema de tablas
para el funcionamiento de jbpm. Primero se deberá crear en MySQL una base de datos
con el nombre jbpmdb, y después ejecutar el script.
Paso 3: Arreglar la consola de jbpm para que funcione con JBoss 5.0.1.GA
En Fase2/Codigo/configuracion/jbpm-3.3.1-instalacion tenemos un zip llamado
app.zip. Se debe reemplazar el contenido de la carpeta
$JBOSS_HOME/server/default/deploy/jbpm/jsf-console.war/app por el contenido
de la carpeta app del zip.
Paso 4: Arreglar una dependencia de JSF en la consola de jbpm
Debemos ir a $JBOSS_HOME/server/default/deploy/jbpm/jsf-console.war/WEB-
INF/lib y reemplazar el archivo jsf-facelets-* que haya por el jsf-facelets.jar que se
encuentra en el directorio Fase2/Codigo/configuracion/jbpm-3.3.1-instalacion.
Paso 5: Configurar el DataSource de la consola de jbpm
Copiar el DataSource que se encuentra en Fase2/Codigo/configuracion/jbpm-3.3.1-
instalacion/jbpm-mysql-ds.xml a $JBOSS_HOME/server/default/deploy/jbpm y
configurar el usuario y password de la base de datos.
Paso 6: Instalar o Actualizar el GPD
El GPD es el plugin de jbpm para Eclipse. En Eclipse tenemos que ir a Help -->
Software Updates --> solapa: Available software --> botón: Add Site --> botón
Archive y elegiremos el archivo $JBPM_HOME/designer/jbpm-jpdl-designer-
site.zip, donde $JBPM_HOME representa el directorio que creó el instalador de jbpm.
Lo que sigue es similar a la instalación de cualquier plugin de Eclipse.
IMPORTANTE: Es fundamental tener exactamente la misma versión de GPD que
trae la instalación de la versión 3.3.1 de jbpm, ya que si no puede haber
incompatibilidades. Por esto recomendamos instalarlo de la manera descripta.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 119
7. Administración del Proyecto
Para la administración del proyecto se utilizó la metodología ágil denominada Scrum.
Esta metodología supone la confección de un ―Product backlog‖, con la información
necesaria para conocer las distintas funcionalidades que debe poseer el producto. El
proyecto se divide en una serie de iteraciones (denominadas ―Sprints‖) al final de las
cuales se completa una serie de ―User Stories‖ o funcionalidades. El ―Sprint burndown
chart‖ y el ―Product burndown chart‖ son indicadores del trabajo remanente para
cumplir con lo comprometido a nivel sprint y a nivel proyecto, respectivamente.
En esta sección se mostrarán los artefactos anteriormente descriptos, junto a otros que
consideramos útiles a la hora de llevar el control del proyecto.
7.1. Product Backlog
El Product Backlog del proyecto se confeccionó a partir de los requerimientos de la
propuesta del trabajo profesional, y se fueron priorizando sus User Stories en base al
valor que aportaban al negocio. De esta manera, se desarrollaron primero las
funcionalidades más importantes para el producto final, dejando para última instancia
las que menos valor aportan al proyecto.
El Product Backlog resultante de este proceso es el siguiente (por orden de prioridad):
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 120
ID Priori
dad
Estima
ción
Nombre del ítem Usuario Descripción Beneficio en el modelo
de negocio
Sprint
US1 1 3 ABM de Unidades de
transporte (MU)
Adriana Alta, baja y modificación de
Unidades de Transporte
(Módulo de Unidades)
Carga de Unidades de
Transporte al sistema.
1
US10 2 3 ABM de Clientes (MC) Adriana Alta, baja y modificación de
Clientes de la empresa. (Módulo
de Clientes)
Poder registrar en el
sistema a los Clientes
de la empresa.
1
US15 3 6 ABM de Viajes (MV) Adriana Alta, baja y modificación de
Viajes (Módulo de Viajes)
Poder registrar en el
sistema los Viajes que
realiza la empresa.
1
US21 4 3 ABM de Rutas (MR) Adriana Alta, baja y modificación de
Rutas (Módulo de Rutas)
Poder registrar en el
sistema las Rutas que
utiliza la empresa para
sus Viajes.
1
US20 5 11 Venta de Pasajes (MPAS) Adriana Generación y emisión de
pasajes. (Módulo de Pasajes)
Que los Clientes
puedan adquirir Pasajes
y administrar el cash-
flow.
2
US7 6 5 Armado de Tripulaciones
para Viajes (MP)
Adriana Confección de Tripulaciones
(conjunto de Personal de la
empresa calificado) para realizar
un Viaje en particular.
Poder registrar en el
sistema a los conjuntos
de empleados que se
asignan a viajes.
2
US18 7 5 Confección de Rutas para un
Viaje. (MV)
Adriana Consulta del estado de las
condiciones de las rutas.
Confección del conjunto de
Rutas a seguir con el Vehículo.
(Módulo de Viajes)
Poder conocer el estado
de un conjunto de Rutas
para determinar si son
aptas para un Viaje en
particular.
2
US6 8 3 ABM de Personal (MP) Adriana Alta, baja y modificación del
Personal de la empresa, como
Poder registrar en el
sistema a los empleados
2
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 121
ID Priori
dad
Estima
ción
Nombre del ítem Usuario Descripción Beneficio en el modelo
de negocio
Sprint
puede ser el conductor de un
vehículo o un piloto de avión.
(Módulo de Personal)
de la empresa.
US11 9 5 Validación de pasaporte
(MC)
Adriana Validación acerca de la
necesidad de poseer un
pasaporte para realizar un viaje
en función del destino. (Módulo
de Clientes)
Poder validar e
informar al pasajero si
debe tramitar el
pasaporte.
2
US16 10 5 Administración de Políticas
de Realización de Viajes
(PRV). (MV)
Adriana Establecimiento de políticas que
determinen la realización de un
viaje (Módulo de Viajes)
Que el sistema
determine automática-
mente si un Viaje se
realiza o no, en base a
un conjunto de reglas.
3
US17 11 8 Sugerencias de asignación de
tripulaciones a Viajes. (MV)
Adriana Sugerencia automática de
Tripulaciones para la realización
de Viajes, en función de ciertas
restricciones. (Módulo de
Viajes)
Que el sistema sugiera
automáticamente la
mejor Tripulación para
un Viaje, en base a un
conjunto de reglas.
3
US8 12 8 Comunicación con sistema
externo de capacitación (MP)
Adriana Comunicación del sistema con
otro externo para obtener
información de capacitación de
Personal (Módulo de Personal)
Conocer calificaciones
del Personal que
necesita estar
capacitado.
3
US22 13 4 Proyección de Unidades
necesarias (ME), parte 1.
Adriana Información de las Unidades
necesarias dependiendo de la
época del año y demandas
conocidas. (Módulo de
Ejecutivos)
Que la empresa se
anticipe a los
requerimientos de
servicio por parte de los
Clientes.
3
US2 14 6 Emisión de pedido de Adriana Generación de un pedido de Poder atender y 4
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 122
ID Priori
dad
Estima
ción
Nombre del ítem Usuario Descripción Beneficio en el modelo
de negocio
Sprint
Reparación (MREP). Reparación por parte de un
integrante del Personal. (Módulo
de Reparaciones)
registrar en el sistema
pedidos de
Reparaciones.
US4 15 6 Alta de Problemas (MREP) Adriana Alta de Problemas en una
Unidad (Módulo de
Reparaciones)
Carga de Problemas al
sistema.
4
US5 16 6 Asignación de Técnicos
(MREP).
Adriana Asignación de Técnico/s a un
Problema. (Módulo de
Reparaciones)
Hacer que un problema
tenga un reparador para
que lo solucione.
4
US3 17 6 Emisión de pedido de
Reparación automático
(MREP).
Adriana Generación de un pedido de
Reparación por parte del sistema
para revisiones de rutina.
(Módulo de Reparaciones)
Generar pedidos de
reparación
regularmente sin
intervención.
4
US23 18 8 Reportes varios (ME), parte
1.
Adriana Reportes (5) en función de la
información de otros módulos.
(Módulo de Ejecutivos)
Que los Ejecutivos
puedan disponer de la
información necesaria
para tomar decisiones
estratégicas a tiempo.
4
US13 19 15 Acceso para Clientes (MC) Adriana Acceso con usuario y
contraseña. Consulta de historial
de viajes, ofertas, publicidad,
noticias, avisos de cancelación
de viaje, calificación del
servicio, etc. (Módulo de
Clientes)
Que los Clientes
interactúen con el
sistema.
5
US9 20 15 Acceso para miembros del
Personal (MP)
Adriana Acceso con usuario y
contraseña. Alertas de cursos,
publicidad, noticias, avisos de
Que el Personal
interactúe con el
sistema.
5
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 123
ID Priori
dad
Estima
ción
Nombre del ítem Usuario Descripción Beneficio en el modelo
de negocio
Sprint
cancelación de viaje, calendario,
etc. (Módulo de Personal)
US12 21 3 Check-in de Clientes (MC) Adriana Realización del check-in del
pasajero para abordar el
Vehículo del Viaje. (Módulo de
Clientes)
Que el Cliente pueda
registrar en el sistema
su información de
check-in.
5
US14 22 11 Administración de programa
de millaje (MC)
Adriana Alta de clientes al programa de
recompensas. Canje de puntos
(millas) por viajes y/o servicios
y/o cambio de categoría de
cliente (Módulo de Clientes)
Poder administrar el
otorgamiento y canje de
puntos de un programa
de millas.
5
US19 23 5 Acceso para personas (MV) Adriana Acceso con contraseña. Consulta
de información acerca del estado
de un Viaje. (Módulo de Viajes)
Que las personas
puedan consultar el
estado de un Viaje.
5
US24 6 ABM de documentación
(MT)
Adriana Alta, baja y modificación de
documentos necesarios para
transportar bultos (facturas,
remitos, declaraciones de
aduana, etc.) (Módulo de
Tramites)
Poder registrar en el
sistema los documentos
que utiliza la empresa
para los trámites
aduaneros y de
transporte de carga.
US25 3 Publicación de servicios Adriana Publicación de servicios para
que otros sistemas puedan
obtener información.
Que otros sistemas
puedan mostrar y/o
interactuar con éste.
US26 4 Proyección de Unidades
necesarias (ME), parte 2.
Adriana Automatización de la estimación
de las Unidades necesarias
dependiendo de la época del año
y demandas a futuro. (Módulo
de Ejecutivos)
Que la empresa se
anticipe a los
requerimientos de
servicio por parte de los
Clientes.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 124
ID Priori
dad
Estima
ción
Nombre del ítem Usuario Descripción Beneficio en el modelo
de negocio
Sprint
US27 9 Reportes varios (ME), parte
2.
Adriana Reportes (6) en función de la
información de otros módulos.
(Módulo de Ejecutivos)
Que los Ejecutivos
puedan disponer de la
información necesaria
para tomar decisiones
estratégicas a tiempo.
172 Total
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 125
Las estimaciones están realizadas en ―Story Points‖, que representan un día / hombre de
ocho horas de trabajo. Las que se muestran en el Product Backlog son las estimaciones
iniciales para cada User Story, las cuales sufrieron cambios a medida que el proyecto
avanzaba, dado que se tenía menos incertidumbre por conocer las capacidades de
desarrollo del equipo y el trabajo por hacer.
Algunos de los User Stories fueron divididos en dos partes, para poder desarrollarlos en
distintos Sprints y facilitar la estimación. Estos ítems fueron:
US22: la parte de estimación automática fue dividida y transportada al US26.
US23: casi la mitad de los reportes pensados originalmente fueron transportados
al US27.
7.2. Desarrollo de los Sprints
7.2.1. Sprint 1
7.2.1.1. Sprint Backlog
El primer Sprint del proyecto de desarrolló entre el 1/6/2009 y el 15/7/2009, teniendo
una duración de 45 días (el más largo de los Sprints). El objetivo del mismo fue que el
sistema pueda registrar las entidades principales del negocio. En este sprint también se
realizó la instalación y configuración de los entornos de trabajo, además de la
capacitación en las tecnologías y la metodología de diseño utilizada.
El siguiente es el Sprint Backlog perteneciente al Sprint 1:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 126
User
Story
ID Estimación Nombre de Tarea Descripción
EX1
EX1.1 2 Armado del Ambiente de Desarrollo Instalación y configuración del ambiente de desarrollo del
proyecto.
EX1.2 2 Armado de Prototipo de Arquitectura Armado de la arquitectura básica.
EX1.3 5 Investigación del Dominio Investigación del negocio.
EX1.4 5 Investigación de las Metodologías Investigación de las Metodologías (DDD y Scrum).
EX1.5 5 Investigación de las Tecnologías Investigación de las Tecnologías (EJB3 y JBoss).
US1
US1.1 1 Entidades de Unidades de transporte
(MU)
Desarrollo de entidades en el modelo.
US1.2 1 Persistencia de Unidades Almacenamiento de las entidades en la base de datos.
US1.3 1 Pruebas de ABM Pruebas unitarias de las operaciones.
US10
US10.1 1 Entidades de Clientes (MC) Desarrollo de entidades en el modelo.
US10.2 1 Persistencia de Clientes Almacenamiento de las entidades en la base de datos.
US10.3 1 Pruebas de ABM Pruebas unitarias de las operaciones.
US15
US15.1 2 Entidades de Viajes (MV) Desarrollo de entidades en el modelo.
US15.2 1 Persistencia de Viajes Almacenamiento de las entidades en la base de datos.
US15.3 1 Pruebas de ABM Pruebas unitarias de las operaciones.
US15.4 1 Relación con Rutas Conexión con las entidades de Rutas (MR).
US15.5 1 Relación con Personal Conexión con las entidades de Personal (MP).
US21
US21.1 1 Entidades de Rutas (MR) Desarrollo de entidades en el modelo.
US21.2 1 Persistencia de Rutas Almacenamiento de las entidades en la base de datos.
US21.3 1 Pruebas de ABM Pruebas unitarias de las operaciones.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 127
7.2.1.2. Burndown Chart
Durante el avance del Sprint, se fue tomando nota del estado de desarrollo de cada tarea
día por día, generando el siguiente ―Sprint Burndown Chart‖:
Analizando el gráfico se puede ver que al inicio del Sprint se avanzó muy rápidamente,
y luego se fue estabilizando con el Baseline, llegando al final del Sprint a tiempo.
7.2.1.3. Riesgos
En este Sprint se manifestaron dos riesgos relacionados con las reuniones en la
Facultad, debido al alerta por la Gripe A.
Se identificaron y siguieron seis riesgos, descriptos a continuación:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 128
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Respon
sable
Estado
1 Dado que el equipo de
desarrollo utiliza al edificio
de la Facultad de Ingeniería
como centro de reuniones,
entonces posiblemente no
se pueda reunir en caso de
que éste edificio cierre sus
puertas.
3 2 6 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Realizar la reunión
en alguno de los
lugares alternativos
especificados durante
la mitigación.
Pablo
Linares
Manifestado.
2 Dado que las reuniones con
el cliente se realizan en
edificio de la Facultad de
Ingeniería, entonces
posiblemente no se pueda
realizar alguna reunión en
caso de que éste edificio
cierre sus puertas.
3 2 6 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Enviar un e-mail al
cliente para concertar
otro lugar o medio de
reunión, pudiendo
proponer los
analizados durante la
mitigación.
Pablo
Linares
Manifestado.
3 Dado que los integrantes
del equipo están trabajando
en otros proyectos y
pueden surgir imprevistos
en los mismos que hagan
que se necesiten horas
extra, entonces el tiempo
remanente para la
dedicación en este proyecto
posiblemente sea escaso.
2 2 4 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más horas
los fines de semana.
Pedir días libres en el
trabajo.
Pablo
Linares
No
manifestado.
4 Dado que la aplicación se
realizará utilizando la
1 3 3 Consultar la
bibliografía que
El Sprint
Burndown
Consultar a alguna
persona con
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 129
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Respon
sable
Estado
metodología de desarrollo
"Domain-Driven Design" y
el equipo no tiene
experiencia en la misma,
entonces el núcleo del
sistema posiblemente no
sea terminado a tiempo y la
implementación sea
ineficiente.
trata del tema. Chart se
desvía más
de 5
storypoints.
experiencia en la
implementación de
esta metodología.
5 Dado que la aplicación se
desarrollará utilizando
tecnologías Java Enterprise
y el equipo no tiene
experiencia en las mismas,
entonces el código
posiblemente no sea
terminado a tiempo y la
implementación será
ineficiente.
1 3 3 Utilizar
frameworks
para la
programación.
Capacitarnos en
las
funcionalidades
esenciales.
El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Consultar a alguna
persona con
experiencia en la
implementación de
esta tecnología.
Pablo
Linares
No
manifestado.
6 Dado que los integrantes
del equipo están trabajando
en otros proyectos,
entonces el tiempo
necesario para la
dedicación en este proyecto
posiblemente sea escaso.
1 2 2 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más horas
los fines de semana.
Pedir días libres en el
trabajo.
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 130
7.2.1.4. Impedimentos
Durante este Sprint se encontraron los siguientes impedimentos que condicionaron el
pleno avance del mismo:
Falta de tiempo de los integrantes del equipo por estar trabajando en otros
proyectos.
Cierre de la facultad para prevención de contagio por Gripe A.
La máquina de uno de los integrantes anda muy lenta cuando se hace correr el
servidor de aplicaciones junto con el motor de base de datos y el entorno de
desarrollo, debido a la falta de memoria física.
7.2.1.5. Sprint Review y metas
Al finalizar el Sprint, se realizó una reunión informal de revisión como balance de lo
sucedido durante el desarrollo. Como resultado, se pudieron obtener:
Puntos positivos:
Se logró hacer funcionar el ambiente completo del sistema (servidor de
aplicaciones + base de datos + servidor web).
Se pudieron completar todos los User Stories comprometidos.
No fueron necesarias reuniones presenciales para la codificación.
Puntos negativos:
Hubo una división de tareas técnicas y de administración en el equipo.
No hubo una definición temprana detallada de algunas entidades del modelo.
Futuras metas a alcanzar en futuros Sprint:
Considerar más tiempo (como US extra) para el desarrollo de la capa de
presentación.
Mezclar las tareas técnicas y de administración entre los miembros del equipo,
para que no queden sectorizadas por integrante y que todos tengan conocimiento
del proyecto.
Aprovechar el tiempo disponible del Sprint desde el inicio del mismo, como lo
hicimos en este sprint.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 131
7.2.2. Sprint 2
7.2.2.1. Sprint Backlog
El segundo Sprint del proyecto de desarrolló entre el 20/7/2009 y el 18/8/2009, teniendo
una duración de 30 días. El objetivo del mismo fue que el sistema pueda registrar al
personal de la empresa que lo utilice, y gestione la venta de Pasajes. En este sprint
también se mejoraron algunos aspectos del sistema desarrollados en el sprint anterior.
El siguiente es el Sprint Backlog perteneciente al Sprint 2:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 132
User Story ID Estimación Nombre de Tarea Descripción
EX2
EX2.1 1 Agregado de Bitácora de Viaje. Agregado de una lista de eventos ocurridos en un Viaje.
EX2.2 1 Soporte para Distancias y Velocidad. Soporte para distintas unidades de medición y conversión de las
mismas.
EX2.3 1 Herencia de Unidades. Refactor para que cada tipo de Unidad herede atributos de una
más gral.
EX2.4 2 Soporte detallado de Fechas. Soporte de Fechas, Horas y Zonas Horarias.
EX2.5 1 Mecanismo de Lazy Load. Implementación de carga tardía de atributos.
EX2.6 2 Atributos y ajustes generales del
Modelo.
Agregado de atributos. Refactor de ciertos aspectos del Modelo.
EX2.7 2 Diseño gráfico de la Presentación. Diseño gráfico de la capa de Presentación del sistema.
US20
US20.
1
1 Entidades para la Venta de Pasajes. Desarrollo de las entidades necesarias.
US20.
2
1 Relación con Viajes. Conexión con las entidades de Viajes (MV).
US20.
3
2 Emisión y administración de Tickets. Investigación y desarrollo de los procedimientos de emisión de
pasajes.
US20.
4
1 Pruebas de ABM. Pruebas unitarias de las operaciones.
US20.
5
1 Diseño e implementación de
Presentación.
Diseño de la capa de Presentación.
US7
US7.1 1 Entidades para Tripulaciones.
Pruebas.
Desarrollo de las entidades necesarias y las pruebas unitarias.
US7.2 1 Diseño e implementación de
Presentación.
Diseño de la capa de Presentación.
US18
US18.
1
1 Entidades para Rutas e Itinerarios. Desarrollo de las entidades necesarias y las pruebas unitarias.
US18.
2
1 Diseño e implementación de
Presentación.
Diseño de la capa de Presentación.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 133
US6
US6.1 1 Entidades y persistencia de Personal. Desarrollo de las entidades necesarias.
US6.2 1 Pruebas de ABM. Pruebas unitarias de las operaciones.
US11
US11.
1
1 Reglas para la validación de
Pasaportes.
Investigación y modelado de las reglas para validación de
pasaportes.
US11.
2
1 Entidades y servicios para validación. Desarrollo de las entidades necesarias y las pruebas unitarias.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 134
7.2.2.2. Burndown Chart
Durante el avance del Sprint, se fue tomando nota del estado de desarrollo de cada tarea
día por día, generando el siguiente ―Sprint Burndown Chart‖:
Analizando el gráfico se puede ver que al inicio del Sprint se avanzó a una velocidad
menor a la necesaria, pero luego se mejoró logrando un paralelismo con el Baseline.
Llegando al final del Sprint se pudieron llegar a completar todos los User Stories
comprometidos.
7.2.2.3. Riesgos
En este Sprint se identificó un riesgo adicional, el cual se manifestó, y se siguieron
controlando seis riesgos también presentes en el sprint anterior.
A continuación se describen los riesgos en detalle:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 135
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
7 Dado que los
integrantes del
equipo no poseen
mucha
experiencia en el
desarrollo de
interfaces web
enriquecidas,
entonces puede
llevar más tiempo
de desarrollo que
el estimado.
3 2 6 Consultar la
documentación
que trata del
tema. Consultar
con personas
que tengan
experiencia en
el tema.
El tiempo
utilizado
para
desarrollar la
Presentación
representa
un 25% del
Sprint.
Simplificar la
capa de
Presentación,
mostrando uno
de los usos del
sistema (para un
solo tipo de
empresa de
viajes).
Pablo
Linares
Manifestado.
1 Dado que el
equipo de
desarrollo utiliza
al edificio de la
Facultad de
Ingeniería como
centro de
reuniones,
entonces
posiblemente no
se pueda reunir
en caso de que
éste edificio
cierre sus puertas.
2 2 4 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Realizar la
reunión en
alguno de los
lugares
alternativos
especificados
durante la
mitigación.
Pablo
Linares
No
manifestado.
2 Dado que las
reuniones con el
2 2 4 Analizar otros
lugares o
La facultad
cierra.
Enviar un e-mail
al cliente para
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 136
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
cliente se realizan
en edificio de la
Facultad de
Ingeniería,
entonces
posiblemente no
se pueda realizar
alguna reunión en
caso de que éste
edificio cierre sus
puertas.
medios de
reunión.
concertar otro
lugar o medio de
reunión,
pudiendo
proponer los
analizados
durante la
mitigación.
3 Dado que los
integrantes del
equipo están
trabajando en
otros proyectos y
pueden surgir
imprevistos en
los mismos que
hagan que se
necesiten horas
extra, entonces el
tiempo remanente
para la
dedicación en
este proyecto
posiblemente sea
escaso.
2 2 4 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 137
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
5 Dado que la
aplicación se
desarrollará
utilizando
tecnologías Java
Enterprise y el
equipo no tiene
experiencia en las
mismas, entonces
el código
posiblemente no
sea terminado a
tiempo y la
implementación
será ineficiente.
1 3 3 Utilizar
frameworks
para la
programación.
Capacitarnos en
las
funcionalidades
esenciales.
El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
tecnología.
Pablo
Linares
No
manifestado.
6 Dado que los
integrantes del
equipo están
trabajando en
otros proyectos,
entonces el
tiempo necesario
para la
dedicación en
este proyecto
posiblemente sea
escaso.
1 2 2 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
No
manifestado.
4 Dado que la 1 2 2 Consultar la El Sprint Consultar a Pablo No
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 138
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
aplicación se
realizará
utilizando la
metodología de
desarrollo
"Domain-Driven
Design" y el
equipo no tiene
experiencia en la
misma, entonces
el núcleo del
sistema
posiblemente no
sea terminado a
tiempo y la
implementación
sea ineficiente.
bibliografía que
trata del tema.
Burndown
Chart se
desvía más
de 5
storypoints.
alguna persona
con experiencia
en la
implementación
de esta
metodología.
Linares manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 139
7.2.2.4. Impedimentos
Durante este Sprint se encontraron los siguientes impedimentos que condicionaron el
pleno avance del mismo:
Falta de tiempo de los integrantes del equipo por estar trabajando en otros
proyectos.
Cierre de la facultad para prevención de contagio por Gripe A durante la mitad
del sprint.
Uno de los integrantes no tuvo acceso a Internet de alta velocidad por unos días.
La recepción de correo en la casilla de Yahoo! se hizo muy lenta. Se recibieron
mensajes con varias horas de retraso.
7.2.2.5. Sprint Review y metas
Al finalizar el Sprint, se realizó una reunión informal de revisión como balance de lo
sucedido durante el desarrollo. Como resultado, se pudieron obtener:
Puntos positivos:
Se pudieron completar todos los User Stories comprometidos.
No fueron necesarias reuniones presenciales para la codificación.
Puntos negativos:
La capa de Presentación de ejemplo se volvió extremadamente complicada de
implementar y mantener.
Hubo una división de tareas técnicas y de administración en el equipo, aunque
en menor grado que en el sprint anterior.
Futuras metas:
Cambiar la forma en que se presentan los datos a fin de demostrar la
funcionalidad.
Volver a realizar reuniones presenciales para el análisis del modelo.
7.2.3. Sprint 3
7.2.3.1. Sprint Backlog
El tercer Sprint del proyecto de desarrolló entre el 31/8/2009 y el 21/9/2009, teniendo
una duración de 22 días. El objetivo del mismo fue dotar al modelo de mayor potencia
de procesamiento de reglas de negocio. En este sprint también se mejoraron algunos aspectos del sistema desarrollados en el sprint anterior.
El siguiente es el Sprint Backlog perteneciente al Sprint 3:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 140
User
Story
ID Estimación Nombre de Tarea Descripción
EX3
EX3.1 1 Vencimiento de pasajes. Implementación del mecanismo de vencimiento automático de
pasajes.
EX3.2 1 Mecanismo de programación de
tareas.
Investigación e implementación de un "scheduler" de tareas.
EX3.3 1 Registro de Pasajes cancelados. Implementación del registro de pasajes cancelados.
EX3.4 0,5 Carga de reglas verdaderas para
Reservas.
Carga de reglas reales que permitan realizar una Reserva.
US16
US16.1 1 Investigación de reglas. Investigación y establecimiento de las reglas para las PRV.
US16.2 1 Traducción e implementación de
reglas.
Traducción de las reglas al formato de Drools y su
implementación.
US16.3 1 Integración con un scheduler de
tareas.
Integrar con estructuras que permitan la ejecución periódica de las
reglas.
US16.4 1 Pruebas. Pruebas unitarias de aplicación de las reglas.
US17
US17.1 2 Especificación de condiciones. Investigación y establecimiento de condiciones y reglas para
Tripulaciones.
US17.2 2 Implementación. Desarrollo del sistema de reglas para sugerencia de Tripulaciones.
US17.3 1 Pruebas de sugerencia de
Tripulaciones.
Pruebas unitarias de las sugerencias de Tripulaciones.
EX4
EX4.1 1 Análisis de catálogo de precios de
Viajes.
Análisis de aspectos económicos para el catálogo de precios de
Viajes.
EX4.2 0,5 Pruebas. Pruebas unitarias de tasación de Viajes.
EX5
EX5.1 0,5 Investigación y desarrollo. Soporte para el cálculo de uso de combustible en Viajes.
EX5.2 0,5 Pruebas. Pruebas unitarias de aplicación de los cálculos.
US8
US8.1 1 Investigación y análisis de extractor. Especificación de los conceptos y arquitectura del extractor.
US8.2 2 Implementación de extractor de
ejemplo.
Desarrollo del extractor de datos de capacitación de Personal.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 141
User
Story
ID Estimación Nombre de Tarea Descripción
US8.3 2 Armado de datos de cursos para
ejemplo.
Armado de un set de datos reales para ejemplo.
US8.4 1 Pruebas. Pruebas unitarias de extracción de datos de capacitación de
Personal.
US22
US22.1 0,5 Investigación y desarrollo. Soporte para consulta de Unidades necesarias en base a datos
históricos.
US22.2 0,5 Pruebas. Pruebas unitarias de la consulta de Unidades necesarias.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 142
7.2.3.2. Burndown Chart
Durante el avance del Sprint, se fue tomando nota del estado de desarrollo de cada tarea
día por día, generando el siguiente ―Sprint Burndown Chart‖:
Analizando el gráfico se puede ver que durante todo el Sprint se avanzó a una velocidad
casi constante y muy parecida al Baseline, llegando al final del Sprint completando
todos los User Stories comprometidos.
7.2.3.3. Riesgos
En este Sprint no se manifestó ningún riesgo ni se identificó riesgo adicional. Sin
embargo, se siguieron controlando los siete riesgos presentes en el sprint anterior,
descritos a continuación:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 143
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
3 Dado que los integrantes
del equipo están trabajando
en otros proyectos y
pueden surgir imprevistos
en los mismos que hagan
que se necesiten horas
extra, entonces el tiempo
remanente para la
dedicación en este proyecto
posiblemente sea escaso.
2 2 4 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más
horas los fines
de semana.
Pedir días libres
en el trabajo.
Pablo
Linares
No
manifestado.
7 Dado que los integrantes
del equipo no poseen
mucha experiencia en el
desarrollo de interfaces
web enriquecidas, entonces
puede llevar más tiempo de
desarrollo que el estimado.
2 2 4 Consultar la
documentación
que trata del
tema. Consultar
con personas
que tengan
experiencia en
el tema.
El tiempo
utilizado
para
desarrollar
la
Presentación
representa
un 25% del
Sprint.
Simplificar la
capa de
Presentación,
mostrando uno
de los usos del
sistema (para
un solo tipo de
empresa de
viajes).
Pablo
Linares
No
manifestado.
5 Dado que la aplicación se
desarrollará utilizando
tecnologías Java Enterprise
y el equipo no tiene
experiencia en las mismas,
entonces el código
posiblemente no sea
terminado a tiempo y la
implementación será
1 3 3 Utilizar
frameworks
para la
programación.
Capacitarnos en
las
funcionalidades
esenciales.
El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
tecnología.
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 144
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
ineficiente.
1 Dado que el equipo de
desarrollo utiliza al edificio
de la Facultad de Ingeniería
como centro de reuniones,
entonces posiblemente no
se pueda reunir en caso de
que éste edificio cierre sus
puertas.
1 2 2 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Realizar la
reunión en
alguno de los
lugares
alternativos
especificados
durante la
mitigación.
Pablo
Linares
No
manifestado.
2 Dado que las reuniones con
el cliente se realizan en
edificio de la Facultad de
Ingeniería, entonces
posiblemente no se pueda
realizar alguna reunión en
caso de que éste edificio
cierre sus puertas.
1 2 2 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Enviar un e-
mail al cliente
para concertar
otro lugar o
medio de
reunión,
pudiendo
proponer los
analizados
durante la
mitigación.
Pablo
Linares
No
manifestado.
6 Dado que los integrantes
del equipo están trabajando
en otros proyectos,
entonces el tiempo
necesario para la
dedicación en este proyecto
posiblemente sea escaso.
1 2 2 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más
horas los fines
de semana.
Pedir días libres
en el trabajo.
Pablo
Linares
No
manifestado.
4 Dado que la aplicación se 1 2 2 Consultar la El Sprint Consultar a Pablo No
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 145
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
realizará utilizando la
metodología de desarrollo
"Domain-Driven Design" y
el equipo no tiene
experiencia en la misma,
entonces el núcleo del
sistema posiblemente no
sea terminado a tiempo y la
implementación sea
ineficiente.
bibliografía que
trata del tema.
Burndown
Chart se
desvía más
de 5
storypoints.
alguna persona
con experiencia
en la
implementación
de esta
metodología.
Linares manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 146
7.2.3.4. Impedimentos
Durante este Sprint se encontraron los siguientes impedimentos que condicionaron el
pleno avance del mismo:
Falta de tiempo de los integrantes del equipo por estar trabajando en otros
proyectos.
La recepción de correo en la casilla de Yahoo! se hace muy lenta. Se reciben
mensajes con varias horas de retraso.
7.2.3.5. Sprint Review y metas
Al finalizar el Sprint, se realizó una reunión informal de revisión como balance de lo
sucedido durante el desarrollo. Como resultado, se pudieron obtener:
Puntos positivos:
Se pudieron completar todos los User Stories comprometidos.
Se realizaron reuniones presenciales para el análisis del modelo.
Se logró incorporar al sistema un motor de reglas.
Puntos negativos:
Algunos aspectos del sistema no pudieron ser documentados.
No se avanzó con la capa de presentación visual para probar el funcionamiento
del sistema.
Futuras metas:
Continuar realizando reuniones presenciales para el análisis del modelo.
Mantener actualizada la documentación, como parte de las tareas en los US.
7.2.4. Sprint 4
7.2.4.1. Sprint Backlog
El cuarto Sprint del proyecto de desarrolló entre el 23/9/2009 y el 21/10/2009, teniendo
una duración de 29 días. El objetivo del mismo fue que el sistema incorpore
completamente la administración de Reparaciones y brinde los principales reportes de
negocio. En este sprint también se agregó la carga masiva de datos de ejemplo ―reales‖.
El siguiente es el Sprint Backlog perteneciente al Sprint 4:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 147
User
Story
ID Estimación Nombre de Tarea Descripción
US17
US17.1 1 Reporte de cantidad de Viajes
realizados.
Reporte de cantidad de Viajes realizados por Unidad y por fechas.
US17.2 1 Reporte de cantidad de Pasajes
vendidos.
Reporte de cantidad de Pasajes vendidos por Unidad y por fechas.
US17.3 1 Reporte de cantidad de Viajes
cancelados.
Reporte de cantidad de Viajes cancelados y causa de la
cancelación.
US17.4 1 Reporte de ganancias obtenidas. Reporte de ganancias obtenidas durante determinada temporada.
US17.5 1 Reporte de costos de Viajes. Reporte de costos necesarios para realizar los Viajes en una
temporada.
EX6
EX6.1 1 Carga de datos maestros adicionales. Carga de nuevas Unidades, Terminales, Waypoints, Rutas, etc.
EX6.2 1 Carga datos transaccionales
adicionales.
Carga de nuevos Viajes, Escalas, etc.
US2
US2.1 2 Entidades para el alta de
Reparaciones.
Análisis y desarrollo de las entidades necesarias.
US2.2 1 Análisis del uso de un motor de
workflows.
Análisis del uso de un motor de workflows.
US2.3 1 Persistencia de las entidades. Almacenamiento de las entidades en la base de datos.
US2.4 1 Pruebas unitarias. Pruebas unitarias de las operaciones.
US4
US4.1 1 Entidades para el alta de Problemas. Análisis y desarrollo de las entidades necesarias.
US4.2 1 Persistencia de las entidades. Almacenamiento de las entidades en la base de datos.
US4.3 1 Relación con Reparaciones. Conexión con las entidades de Reparaciones.
US4.4 1 Pruebas unitarias. Pruebas unitarias de las operaciones.
US5
US5.1 1 Entidades para Técnicos. Análisis y desarrollo de las entidades necesarias.
US5.2 1 Persistencia de las entidades. Almacenamiento de las entidades en la base de datos.
US5.3 1 Relación con Reparaciones y
Problemas.
Conexión con las entidades de Reparaciones y de Problemas.
US5.4 1 Pruebas unitarias. Pruebas unitarias de las operaciones.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 148
User
Story
ID Estimación Nombre de Tarea Descripción
US3
US3.1 2 Automatización de pedido de
Reparación.
Sistema para generación periódica automática de Reparaciones.
US3.2 1 Integración con un scheduler de
tareas.
Integrar con estructuras que permitan la ejecución periódica de las
reglas.
US3.3 1 Pruebas. Pruebas unitarias de las operaciones.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 149
7.2.4.2. Burndown Chart
Durante el avance del Sprint, se fue tomando nota del estado de desarrollo de cada tarea
día por día, generando el siguiente ―Sprint Burndown Chart‖:
Analizando el gráfico se puede ver que al inicio y hacia el final del Sprint se avanzó a
una velocidad casi constante y muy parecida al Baseline. En el medio hubo un desfasaje
considerable, pero luego pudo ser subsanado. Esto pudo ser gracias a la activación de
ciertos riegos dependientes del desvío del burndown chart, activando la contingencia y
avanzando en el trabajo el fin de semana del 12 de Octubre.
Llegando al final del Sprint se pudieron llegar a completar todos los User Stories
comprometidos.
7.2.4.3. Riesgos
En este Sprint se manifestaron dos riesgos, disparados por el atraso ocurrido a la mitad
del sprint. Afortunadamente en el fin de semana largo correspondiente al 12 de Octubre
se pudo avanzar en el proyecto de forma tal que los riesgos manifestados fueron
extinguidos.
En este sprint se identificó un riesgo adicional relacionado a la nueva tecnología
adoptada, y se siguieron controlando los siete riesgos presentes en el sprint anterior,
descriptos a continuación:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 150
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
8 Dado que la
aplicación
incorporará
tecnologías de
motores de reglas
y "workflows", y
el equipo no tiene
experiencia en las
mismas, entonces
el código
posiblemente no
sea terminado a
tiempo y la
implementación
será ineficiente.
2 3 6 Capacitarnos en
las
funcionalidades
básicas
necesarias para
realizar las
tareas que
demande el
proyecto.
El Sprint
Burndown
Chart se
desvía más
de 5
storypoints
en US que
utilicen
alguna de
estas
tecnologías.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
tecnología.
Simplificar el
desarrollo al
punto de no
utilizarlas.
Pablo
Linares
No
manifestado.
3 Dado que los
integrantes del
equipo están
trabajando en
otros proyectos y
pueden surgir
imprevistos en
los mismos que
hagan que se
necesiten horas
extra, entonces el
tiempo
remanente para la
2 2 4 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
Manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 151
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
dedicación en
este proyecto
posiblemente sea
escaso.
5 Dado que la
aplicación se
desarrollará
utilizando
tecnologías Java
Enterprise y el
equipo no tiene
experiencia en las
mismas, entonces
el código
posiblemente no
sea terminado a
tiempo y la
implementación
será ineficiente.
1 3 3 Utilizar
frameworks
para la
programación.
Capacitarnos en
las
funcionalidades
esenciales.
El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
tecnología.
Pablo
Linares
Manifestado.
1 Dado que el
equipo de
desarrollo utiliza
al edificio de la
Facultad de
Ingeniería como
centro de
reuniones,
entonces
1 2 2 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Realizar la
reunión en
alguno de los
lugares
alternativos
especificados
durante la
mitigación.
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 152
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
posiblemente no
se pueda reunir
en caso de que
éste edificio
cierre sus
puertas.
2 Dado que las
reuniones con el
cliente se realizan
en edificio de la
Facultad de
Ingeniería,
entonces
posiblemente no
se pueda realizar
alguna reunión en
caso de que éste
edificio cierre sus
puertas.
1 2 2 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Enviar un e-mail
al cliente para
concertar otro
lugar o medio de
reunión,
pudiendo
proponer los
analizados
durante la
mitigación.
Pablo
Linares
No
manifestado.
6 Dado que los
integrantes del
equipo están
trabajando en
otros proyectos,
entonces el
tiempo necesario
para la
dedicación en
1 2 2 - El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 153
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
este proyecto
posiblemente sea
escaso.
4 Dado que la
aplicación se
realizará
utilizando la
metodología de
desarrollo
"Domain-Driven
Design" y el
equipo no tiene
experiencia en la
misma, entonces
el núcleo del
sistema
posiblemente no
sea terminado a
tiempo y la
implementación
sea ineficiente.
1 2 2 Consultar la
bibliografía que
trata del tema.
El Sprint
Burndown
Chart se
desvía más
de 5
storypoints.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
metodología.
Pablo
Linares
No
manifestado.
7 Dado que los
integrantes del
equipo no poseen
mucha
experiencia en el
desarrollo de
interfaces web
1 2 2 Consultar la
documentación
que trata del
tema. Consultar
con personas
que tengan
experiencia en
El tiempo
utilizado
para
desarrollar la
Presentación
representa un
25% del
Simplificar la
capa de
Presentación,
mostrando uno
de los usos del
sistema (para un
solo tipo de
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 154
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
enriquecidas,
entonces puede
llevar más tiempo
de desarrollo que
el estimado.
el tema. Sprint. empresa de
viajes).
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 155
7.2.4.4. Impedimentos
Durante este Sprint se encontraron los siguientes impedimentos que condicionaron el
pleno avance del mismo:
Falta de espacio en disco en la máquina de uno de los integrantes.
Falta de tiempo de los integrantes del equipo por estar trabajando en otros
proyectos.
La recepción de correo en la casilla de Yahoo! se hace muy lenta. Se reciben
mensajes con varias horas de retraso.
7.2.4.5. Sprint Review y metas
Al finalizar el Sprint, se realizó una reunión informal de revisión como balance de lo
sucedido durante el desarrollo. Como resultado, se pudieron obtener:
Puntos positivos:
Se pudieron completar todos los User Stories comprometidos.
Se realizaron reuniones presenciales para el análisis del modelo.
Se incorporó de forma regular la realización minutas de reunión, en forma de
"to-do lists".
Se logró incorporar al sistema un motor de workflows.
Puntos negativos:
Varios riesgos importantes se manifestaron, pero pudieron ser solucionados
rápidamente.
Algunos aspectos del sistema no pudieron ser documentados.
No se avanzó con la capa de presentación visual para probar el funcionamiento
del sistema.
Futuras metas:
Continuar realizando reuniones presenciales para el análisis del modelo.
Mantener actualizada la documentación, como parte de las tareas en los US.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 156
7.2.5. Sprint 5
7.2.5.1. Sprint Backlog
El quinto Sprint del proyecto de desarrolló entre el 26/10/2009 y el 20/11/2009,
teniendo una duración de 26 días. El objetivo del mismo fue proveer acceso a los
distintos módulos del sistema, a través de una completa y mejorada capa de
presentación. En este sprint también se mejoraron algunos aspectos del sistema
desarrollados en el sprint anterior.
El siguiente es el Sprint Backlog perteneciente al Sprint 5:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 157
User
Story
ID Estimación Nombre de Tarea Descripción
EX7
EX7.1 1 Separación de capas. Separación de la capa de negocio de la capa de aplicación.
EX7.2 1 Refactor del extractor. Refactor para soporte de distintos tipos de empleados.
EX7.3 1 Refactor de la capa de servicio. Refactor para estandarizar métodos y mejorar la actualización de
Entities.
EX7.4 2 Correcciones al módulo de
reparaciones.
Correcciones y ajustes al seguimiento de las tareas de Reparación.
EX7.5 1 Repositorio de información. Agregar al repositorio la información más importante utilizada.
EX8
EX8.1 3 Capa de presentación para Unidades. Interfaz de usuario para la administración de Unidades.
EX8.2 3 Capa de presentación para Viajes. Interfaz de usuario para la administración de Viajes.
EX8.3 3 Capa de presentación para Rutas. Interfaz de usuario para la administración de Rutas.
EX8.4 3 Capa de presentación para Pasajes. Interfaz de usuario para la administración de Pasajes.
EX8.5 2 Capa de presentación para
Ejecutivos.
Interfaz de usuario para la administración de reportes para
Ejecutivos.
US13
US13.1 3 Acceso por usuario y contraseña. Interfaz para acceso de Clientes.
US13.2 1 Consulta de historial. Consulta para obtener historial de viajes.
US13.3 2 Encuestas. Formulario para la carga de encuestas de satisfacción del Cliente.
US13.4 1 Noticias (ofertas, novedades,
publicidad).
Entidades e interfaz para mostrar publicidad a los Clientes.
US9
US9.1 3 Acceso por usuario y contraseña. Interfaz para acceso de Empleados.
US9.2 1 Consultas. Consultas para obtener datos útiles para el Empleado.
US9.3 1 Cancelaciones. Información de cancelaciones de Viajes para
EmpleadosTripulantes.
US9.4 1 Noticias (cursos). Entidades e interfaz para mostrar publicidad e información a
Empleados.
US12
US12.1 1 Atributos y/o entidades de check-in. Agregado de los atributos y/o entidades necesarias para el check-
in.
US12.2 1 Pruebas de check-in. Pruebas unitarias de la operación de check-in de pasajeros.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 158
User
Story
ID Estimación Nombre de Tarea Descripción
US14
US14.1 1 Entidades para programa de millaje. Entidades y/o atributos necesarios para el programa de millaje.
US14.2 1 Catálogo de puntos y premios. Entidades para los datos maestros de puntajes y valor de premios.
US14.3 1 Sistema de otorgamiento de puntos. Cálculo de los puntos a otorgar en función del historial de viajes.
US14.4 1 Pruebas unitarias. Pruebas del programa millaje.
US19
US19.1 1 Acceso por clave. Acceso a la información de Viaje a través de código de
seguimiento.
US19.2 1 Pruebas unitarias. Pruebas del acceso.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 159
7.2.5.2. Burndown Chart
Durante el avance del Sprint, se fue tomando nota del estado de desarrollo de cada tarea
día por día, generando el siguiente ―Sprint Burndown Chart‖:
Analizando el gráfico se puede ver que al inicio del Sprint se avanzó a una velocidad
bastante rápida respecto del Baseline, pero hacia el final la pendiente del Total es más
horizontal. Esto es debido a que este sprint se enfocó principalmente en la realización de
una buena capa de presentación, que al equipo le costó mucho realizar tanto en este
como en el primer sprint.
Como puede verse al final del gráfico, este fue el único sprint en el cual no se pudieron
completar todas las funcionalidades comprometidas: dado el atraso producido por la
complejidad de la capa de presentación, no hubo tiempo para realizar el acceso
autenticado de Clientes y Empleados. Esto último hubiese llevado alrededor de 12
storypoints adicionales, según estimaciones posteriores.
7.2.5.3. Riesgos
En este Sprint se manifestaron cuatro riesgos, asociados con el gran desfasaje respecto
del Baseline del Sprint Burndown Chart. Dos de ellos no fueron de gran impacto.
No se identificó ningún riesgo adicional respecto del sprint anterior.
Los riesgos para este sprint fueron:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 160
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
7 Dado que los
integrantes del
equipo no poseen
mucha
experiencia en el
desarrollo de
interfaces web
enriquecidas,
entonces puede
llevar más
tiempo de
desarrollo que el
estimado.
3 2 6 Consultar la
documentación
que trata del
tema. Consultar
con personas
que tengan
experiencia en
el tema.
El tiempo
utilizado
para
desarrollar la
Presentación
representa un
50% más del
estimado.
Simplificar la
capa de
Presentación,
mostrando uno
de los usos del
sistema (para un
solo tipo de
empresa de
viajes). Realizar
la capa de
Presentación
utilizando otra
tecnología más
simple.
Pablo
Linares
No
manifestado.
3 Dado que los
integrantes del
equipo están
trabajando en
otros proyectos y
pueden surgir
imprevistos en
los mismos que
hagan que se
necesiten horas
extra, entonces el
tiempo
remanente para
la dedicación en
1 3 3 - El Sprint
Burndown
Chart se
desvía más
de 10
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
Manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 161
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
este proyecto
posiblemente sea
escaso.
5 Dado que la
aplicación se
desarrollará
utilizando
tecnologías Java
Enterprise y el
equipo no tiene
experiencia en
las mismas,
entonces el
código
posiblemente no
sea terminado a
tiempo y la
implementación
será ineficiente.
1 3 3 Utilizar
frameworks
para la
programación.
Capacitarnos en
las
funcionalidades
esenciales.
El Sprint
Burndown
Chart se
desvía más
de 10
storypoints.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
tecnología.
Pablo
Linares
Manifestado.
8 Dado que la
aplicación
incorporará
tecnologías de
motores de reglas
y "workflows", y
el equipo no
tiene experiencia
en las mismas,
1 2 2 Capacitarnos en
las
funcionalidades
básicas
necesarias para
realizar las
tareas que
demande el
proyecto.
El Sprint
Burndown
Chart se
desvía más
de 10
storypoints
en US que
utilicen
alguna de
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
tecnología.
Simplificar el
desarrollo al
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 162
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
entonces el
código
posiblemente no
sea terminado a
tiempo y la
implementación
será ineficiente.
estas
tecnologías.
punto de no
utilizarlas.
1 Dado que el
equipo de
desarrollo utiliza
al edificio de la
Facultad de
Ingeniería como
centro de
reuniones,
entonces
posiblemente no
se pueda reunir
en caso de que
éste edificio
cierre sus
puertas.
1 2 2 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Realizar la
reunión en
alguno de los
lugares
alternativos
especificados
durante la
mitigación.
Pablo
Linares
No
manifestado.
2 Dado que las
reuniones con el
cliente se
realizan en
edificio de la
Facultad de
1 2 2 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Enviar un e-mail
al cliente para
concertar otro
lugar o medio de
reunión,
pudiendo
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 163
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
Ingeniería,
entonces
posiblemente no
se pueda realizar
alguna reunión
en caso de que
éste edificio
cierre sus
puertas.
proponer los
analizados
durante la
mitigación.
6 Dado que los
integrantes del
equipo están
trabajando en
otros proyectos,
entonces el
tiempo necesario
para la
dedicación en
este proyecto
posiblemente sea
escaso.
1 2 2 - El Sprint
Burndown
Chart se
desvía más
de 15
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
Manifestado.
4 Dado que la
aplicación se
realizará
utilizando la
metodología de
desarrollo
"Domain-Driven
1 2 2 Consultar la
bibliografía que
trata del tema.
El Sprint
Burndown
Chart se
desvía más
de 10
storypoints.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
metodología.
Pablo
Linares
Manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 164
ID Descripción Probabilidad Impacto Exposición Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
Design" y el
equipo no tiene
experiencia en la
misma, entonces
el núcleo del
sistema
posiblemente no
sea terminado a
tiempo y la
implementación
sea ineficiente.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 165
7.2.5.4. Impedimentos
Durante este Sprint se encontraron los siguientes impedimentos que condicionaron el
pleno avance del mismo:
Falta de tiempo de los integrantes del equipo por estar trabajando en otros
proyectos.
Exámenes parciales de materias de la facultad.
7.2.5.5. Sprint Review y metas
Al finalizar el Sprint, se realizó una reunión informal de revisión como balance de lo
sucedido durante el desarrollo. Como resultado, se pudieron obtener:
Puntos positivos:
Se realizaron reuniones presenciales para el análisis del modelo.
Se avanzó mucho con la capa de presentación visual para probar y mostrar el
funcionamiento del sistema.
Se continuó realizando minutas de reunión, en forma de "to-do lists".
Puntos negativos:
No se pudieron completar todos los User Stories comprometidos. Sin embargo,
se pudo consensuar con el cliente la no realización de los mismos, dado el
escaso valor que aportan al negocio.
Varios riesgos importantes se manifestaron, pero pudieron ser solucionados
rápidamente.
Algunos aspectos del sistema no pudieron ser documentados todavía.
Futuras metas:
Continuar realizando reuniones presenciales para el control y seguimiento de lo
realizado.
Documentar los aspectos del sistema que todavía no fueron documentados.
Mantener actualizada la documentación administrativa, como parte de las tareas
en los US.
7.2.6. Sprint 6
7.2.6.1. Sprint Backlog
El sexto y último Sprint del proyecto de desarrolló entre el 24/11/2009 y el 21/12/2009,
teniendo una duración de 28 días. El objetivo del mismo fue cerrar el proyecto,
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 166
completando la documentación y probando en profundidad lo hecho. En este sprint se
decidió no incorporar mayores funcionalidades, debido a dos factores:
Era necesaria una estabilización de las últimas funcionalidades incorporadas y una prueba completa del producto en profundidad.
Las funcionalidades que quedaban por implementar casi no agregaban valor al
proyecto, en comparación con realizar una buena documentación.
El siguiente es el Sprint Backlog perteneciente al Sprint 6:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 167
User
Story
ID Estimación Nombre de Tarea Descripción
EX9
EX9.1 2 Corrección y agregado de
funciones.
Corrección y agregado de las últimas funcionalidades a la Presentación.
EX9.2 1 Pruebas de la capa de
Presentación.
Conjunto de pruebas de aceptación (UAT) para la capa de Presentación.
EX10
EX10.1 1 Pruebas del MC. Actualización de las pruebas y corrección de los defectos que surjan.
EX10.2 1 Pruebas del MU. Actualización de las pruebas y corrección de los defectos que surjan.
EX10.3 1 Pruebas del MR. Actualización de las pruebas y corrección de los defectos que surjan.
EX10.4 1 Pruebas del MV. Actualización de las pruebas y corrección de los defectos que surjan.
EX10.5 1 Pruebas del MPAS. Actualización de las pruebas y corrección de los defectos que surjan.
EX10.6 1 Pruebas del MP. Actualización de las pruebas y corrección de los defectos que surjan.
EX10.7 3 Pruebas de los módulos restantes. Actualización de las pruebas y corrección de los defectos que surjan.
EX11
EX11.1 1 Documentación del MC. Agregado de documentación Javadoc en el código y documentos Word.
EX11.2 1 Documentación del MU. Agregado de documentación Javadoc en el código y documentos Word.
EX11.3 1 Documentación del MR. Agregado de documentación Javadoc en el código y documentos Word.
EX11.4 1 Documentación del MV. Agregado de documentación Javadoc en el código y documentos Word.
EX11.5 1 Documentación del MPAS. Agregado de documentación Javadoc en el código y documentos Word.
EX11.6 1 Documentación del MP. Agregado de documentación Javadoc en el código y documentos Word.
EX11.7 3 Documentación de los módulos
restantes.
Agregado de documentación Javadoc en el código y documentos Word.
EX12
EX12.1 2 Resumen de presentación. Redacción de un resumen de lo que incluirá la presentación.
EX12.2 5 Diapositivas de presentación. Creación de una presentación en diapositivas acerca del proyecto.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 168
7.2.6.2. Burndown Chart
Durante el avance del Sprint, se fue tomando nota del estado de desarrollo de cada tarea
día por día, generando el siguiente ―Sprint Burndown Chart‖:
Analizando el gráfico se puede ver que al inicio del Sprint se avanzó a muy poca
velocidad, lo cual agregó un desfasaje grande respecto del Baseline. Esto fue debido a
que los primeros días se realizaron revisiones sobre temas pendientes del sprint anterior
que no fueron incluidos en el sprint backlog.
Hacia la mitad del sprint la velocidad empezó a ser como la del Baseline, salvo un punto
en el cual parecía que iba a estancarse nuevamente. En este punto, se realizó una
reestimación de las revisiones a las pruebas de los módulos del sistema (user story
―EX10‖), dando como resultado el notorio salto de casi 6 storypoints.
Al final del sprint pudieron realizarse todos los user stories comprometidos.
7.2.6.3. Riesgos
En este Sprint no se manifestó ningún riesgo, aunque en un momento estuvieron a punto
de activarse los relacionados con el desfasaje respecto del Baseline.
En este sprint no se identificó ningún riesgo adicional respecto del sprint anterior.
Los riesgos para este sprint fueron:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 169
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
7 Dado que los integrantes
del equipo no poseen
mucha experiencia en el
desarrollo de interfaces
web enriquecidas, entonces
puede llevar más tiempo de
desarrollo que el estimado.
2 2 4 Consultar la
documentación
que trata del
tema. Consultar
con personas
que tengan
experiencia en
el tema.
El tiempo
utilizado
para
desarrollar la
Presentación
representa un
50% más del
estimado.
Simplificar la
capa de
Presentación,
mostrando uno
de los usos del
sistema (para un
solo tipo de
empresa de
viajes). Realizar
la capa de
Presentación
utilizando otra
tecnología más
simple.
Pablo
Linares
No
manifestado.
3 Dado que los integrantes
del equipo están trabajando
en otros proyectos y
pueden surgir imprevistos
en los mismos que hagan
que se necesiten horas
extra, entonces el tiempo
remanente para la
dedicación en este proyecto
posiblemente sea escaso.
1 3 3 - El Sprint
Burndown
Chart se
desvía más
de 10
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
No
manifestado.
5 Dado que la aplicación se
desarrollará utilizando
tecnologías Java Enterprise
y el equipo no tiene
1 3 3 Utilizar
frameworks
para la
programación.
El Sprint
Burndown
Chart se
desvía más
Consultar a
alguna persona
con experiencia
en la
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 170
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
experiencia en las mismas,
entonces el código
posiblemente no sea
terminado a tiempo y la
implementación será
ineficiente.
Capacitarnos en
las
funcionalidades
esenciales.
de 10
storypoints.
implementación
de esta
tecnología.
8 Dado que la aplicación
incorporará tecnologías de
motores de reglas y
"workflows", y el equipo
no tiene experiencia en las
mismas, entonces el código
posiblemente no sea
terminado a tiempo y la
implementación será
ineficiente.
1 2 2 Capacitarnos en
las
funcionalidades
básicas
necesarias para
realizar las
tareas que
demande el
proyecto.
El Sprint
Burndown
Chart se
desvía más
de 10
storypoints
en US que
utilicen
alguna de
estas
tecnologías.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
tecnología.
Simplificar el
desarrollo al
punto de no
utilizarlas.
Pablo
Linares
No
manifestado.
1 Dado que el equipo de
desarrollo utiliza al edificio
de la Facultad de Ingeniería
como centro de reuniones,
entonces posiblemente no
se pueda reunir en caso de
que éste edificio cierre sus
puertas.
1 2 2 Analizar otros
lugares o
medios de
reunión.
La facultad
cierra.
Realizar la
reunión en
alguno de los
lugares
alternativos
especificados
durante la
mitigación.
Pablo
Linares
No
manifestado.
2 Dado que las reuniones con
el cliente se realizan en
edificio de la Facultad de
1 2 2 Analizar otros
lugares o
medios de
La facultad
cierra.
Enviar un e-mail
al cliente para
concertar otro
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 171
ID Descripción Probabi
lidad
Impac
to
Exposi
ción
Plan de
mitigación
Trigger Plan de
contingencia
Responsable Estado
Ingeniería, entonces
posiblemente no se pueda
realizar alguna reunión en
caso de que éste edificio
cierre sus puertas.
reunión. lugar o medio de
reunión,
pudiendo
proponer los
analizados
durante la
mitigación.
6 Dado que los integrantes
del equipo están trabajando
en otros proyectos,
entonces el tiempo
necesario para la
dedicación en este proyecto
posiblemente sea escaso.
1 2 2 - El Sprint
Burndown
Chart se
desvía más
de 15
storypoints.
Utilizar más
horas los fines
de semana. Pedir
días libres en el
trabajo.
Pablo
Linares
No
manifestado.
4 Dado que la aplicación se
realizará utilizando la
metodología de desarrollo
"Domain-Driven Design" y
el equipo no tiene
experiencia en la misma,
entonces el núcleo del
sistema posiblemente no
sea terminado a tiempo y la
implementación sea
ineficiente.
1 2 2 Consultar la
bibliografía que
trata del tema.
El Sprint
Burndown
Chart se
desvía más
de 10
storypoints.
Consultar a
alguna persona
con experiencia
en la
implementación
de esta
metodología.
Pablo
Linares
No
manifestado.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 172
7.2.6.4. Impedimentos
Durante este Sprint se encontraron los siguientes impedimentos que condicionaron el
pleno avance del mismo:
Falta de tiempo de los integrantes del equipo por estar trabajando en otros
proyectos.
Exámenes parciales de materias de la facultad.
7.2.6.5. Sprint Review y metas
Al finalizar el Sprint, se realizó una reunión informal de revisión como balance de lo
sucedido durante el desarrollo. Como resultado, se pudieron obtener:
Puntos positivos:
Se realizaron reuniones presenciales para el análisis del modelo.
Se avanzó mucho con la capa de presentación visual para probar y mostrar el
funcionamiento del sistema.
Se continuó realizando minutas de reunión, en forma de "to-do lists".
Puntos negativos:
No se pudieron completar todos los User Stories comprometidos. Sin embargo,
se pudo consensuar con el cliente la no realización de los mismos, dado el
escaso valor que aportan al negocio.
Varios riesgos importantes se manifestaron, pero pudieron ser solucionados
rápidamente.
Algunos aspectos del sistema no pudieron ser documentados todavía.
Futuras metas:
Continuar realizando reuniones presenciales para el control y seguimiento de lo
realizado.
Documentar los aspectos del sistema que todavía no fueron documentados.
Mantener actualizada la documentación administrativa, como parte de las tareas
en los US.
7.3. Product Burndown Chart
7.3.1. Gráfico
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 173
Con la información proporcionada por los Sprint Burndown Charts, se confeccionó un
diagrama del progreso del proyecto hacia el producto final. Este diagrama es conocido como ―Product Burndown Chart‖ o ―Release Burndown Chart‖.
Para la diagramación del mismo, se tomaron en cuenta los tiempos estimados iniciales
de los User Stories originales, realizando un ajuste sobre estos valores si los User
Stories eran reestimados al incorporarse al Sprint o bien si se incorporaban User Stories Extra.
El gráfico resultante es el siguiente:
En el eje vertical se pueden ver los storypoints necesarios para terminar el producto. En
el eje horizontal se ubican los Sprints. El primer punto del diagrama indica el momento
en el que empezó el proyecto: ambas curvas (Baseline y Real) convergen en el punto en
el cual se estimó el esfuerzo total del proyecto inicialmente (172 storypoints). Luego,
cada uno de los puntos siguientes indica el estado del proyecto al finalizar cada sprint.
7.3.2. Cálculo del gráfico
Para calcular el gráfico se tomaron los valores de los user stories realizados con éxito en
cada sprint, y se restaron al valor del product burndown anterior. En el caso del esfuerzo
reestimado, la cantidad de storypoints estimados de más se restaron, y los estimados de
menos se sumaron, a la cantidad de storypoints obtenidos del sprint.
Cada punto entonces se calcula como:
Esfuerzo_PBC_sprint = Esfuerzo_PBC_sprint_anterior +
Esfuerzo_exitoso_sprint_actual + Diferencia_esfuerzo_reestimado +
Esfuerzo_US_extras
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 174
Donde:
Esfuerzo_exitoso_sprint_actual = Esfuerzo_estimado_fin -
Esfuerzo_estimado_inicio
Y:
Diferencia_esfuerzo_reestimado = Esfuerzo_reestimado - Esfuerzo_original
De esta manera, se puede graficar el progreso del proyecto respecto de una línea recta
de Baseline, como si no hubiese sido necesario reestimar los valores iniciales.
El que sigue es un resumen de los storrypoints modificados respecto esfuerzo estimado
originalmente:
Sprint Esfuerzo reestimado Esfuerzo US extras
1 0 19
2 -15 10
3 -9 7
4 -10 2
5 -28 20
6 -28 28
El valor negativo en el campo ―Esfuerzo reestimado‖ indica que cuando se reestimaron
los user stories del sprint, se llegó a la conclusión de que costarían menos esfuerzo que
el determinado originalmente.
7.4. Otros indicadores
7.4.1. Velocidad
Otro indicador que se tomó en cuenta es el de la velocidad de desarrollo por sprint. Con
él se puede ver la capacidad del equipo para completar los user stories de cada sprint.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 175
Cada punto del valor de velocidad fue calculado realizando el promedio de user stories
completados por sprint, basándose en la información de sprints anteriores. El gráfico
debe leerse como la velocidad del equipo al final de cada sprint, y no como la velocidad
puntual del sprint.
En el gráfico puede verse que la velocidad máxima se alcanzó hacia la mitad del
proyecto, con un promedio de seis user stories realizados exitosamente por sprint.
Luego fue mermando de a poco hacia el final del proyecto, debido a que comenzó a
cobrar peso la estabilización y documentación de lo realizado, en contraste con el valor
que los últimos user stories aportaban al negocio.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 176
8. Bibliografía
Domain-Driven Design: Tackling Complexity in the Heart of Software
Eric Evans
http://www.amazon.com/exec/obidos/ASIN/0321125215/domainlanguag-20
Patterns of Enterprise Application Architecture
(Addison-Wesley Signature Series)
Martin Fowler, David Rice, Matthew Foemmel, Edward Hieatt, Robert Mee,
Randy Stafford
http://www.amazon.com/Enterprise-Application-Architecture-Addison-Wesley-
Signature/dp/0321127420/ref=pd_bxgy_b_img_b
EJB 3 in Action
Debu Panda, Reza Rahman, Derek Lane
http://www.manning.com/panda/
Domain Driven Design Quickly
Abel Avram & Floyd Marinescu
http://www.infoq.com/minibooks/domain-driven-design-quickly
Scrum and XP from the Trenches
Henrik Kniberg
http://www.infoq.com/minibooks/scrum-xp-from-the-trenches
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 177
9. Anexos
9.1. Domain-Driven Design
9.1.1. Introducción
9.1.1.1. Aplicaciones Enterprise
Una aplicación enterprise es un sistema fuertemente orientado a un negocio
determinado, que debe cumplir ciertos requerimientos no funcionales. En general, las
aplicaciones enterprise:
Persisten datos de forma masiva
Suelen ser multi-usuarios (varios usuarios pueden acceder de forma concurrente)
Cuentan con muchísimas interfaces de usuario
Se integran con otros sistemas
Presentan disonancia conceptual (usuarios con vistas contrapuestas)
Tienen lógica de negocio
¿Una aplicación enterprise es aquella que cumple con todas las características recién
enunciadas? No necesariamente. Una aplicación enterprise es aquella que tiene
lógica de negocio, un sistema fuertemente orientado al negocio y por eso en mucha
bibliografía a las aplicaciones enterprise se las suele llamar aplicaciones de negocio.
En general, que tengamos una lógica de negocio acarrea que debamos guardar el estado
(los conceptos o las entidades) de esa lógica para poder recuperarlo en todo momento.
También implica que esos conceptos puedan ser mostrados de alguna manera a los
usuarios del negocio, a los clientes, y en general, los clientes suelen ser muchos, y
suelen ejecutar consultas en paralelo. Así es como un requerimiento no funcional lleva a
otro y nos encontramos con que, cuando nos enfrentamos a una aplicación enterprise
que va creciendo en tamaño y complejidad, son necesarias casi todas las características
antes enumeradas.
El concepto de aplicación enterprise nació con el fin de modularizar y organizar el
desarrollo de aplicaciones complejas de negocio, cuyo número de desarrolladores,
analistas, diseñadores crecía exponencialmente al paso que se multiplicaban los
requerimientos no funcionales. Como la posibilidad de automatizar negocios cada vez
más complejos se hizo posible gracias al escalamiento de hardware y de paradigmas y
técnicas de programación más efectivas (como la orientación a objetos y las
metodologías de desarrollo), se necesitó una forma de separar lo que es la lógica de
negocio (requerimientos funcionales) de lo que es la lógica de la aplicación
(requerimientos no funcionales). Entonces comenzaron a surgir algunos frameworks,
primero en el mundo de Java, que intentaban lograr esta separación. Surgió la
especificación de Sun Microsystems para los Enterprise Java Beans (EJB) y un
tiempo después Microsoft se metió en el mercado para hacerle frente con una
plataforma bastante más sencilla llamada .NET, pero que demoró mucho en madurar.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 178
Durante demasiados años, tanto la plataforma enterprise de Java (J2EE) como .NET
tuvieron muchísimos problemas. Las especificaciones no eran del todo felices y, en el
afán de abstraer al programador de los requerimientos no funcionales comunes a todas
las aplicaciones enterprise (la lógica de aplicación), las herramientas para diseñar una
buena lógica de negocio se vio limitada, brutalmente recortada, logrando que la
programación orientada a objetos retrocediera unos cuantos pasos. Hasta se habló de
anti-patrones en J2EE y se publicaron varias tesis y artículos al respecto.
No fue hasta que comenzaron a surgir los famosos frameworks livianos (como Spring
por ejemplo) que los programadores pudieron volver a aplicar la programación
orientada a objetos en todo su esplendor para construir lógicas de negocio más robustas,
escalables y parecidas a la realidad. Sun Microsystems tomó muchas de las ideas de los
frameworks livianos y lanzó una nueva especificación: EJB 3.0, a la vez que cambió el
nombre de su plataforma J2EE a JavaEE.
9.1.1.2. Arquitectura de 4-tiers
Los requerimientos no funcionales más comunes en una aplicación enterprise son:
Bajo Tiempo de Respuesta
Alta Interactividad con el Usuario
Baja Latencia
Muchas Transacciones por segundo (throughput)
Alta Carga (número de usuarios concurrentes)
Baja Degradación (variación del Tiempo de Respuesta con la Carga)
Alta Eficiencia (performance)
Alta Capacidad (máxima entre el throughput y la carga)
Alta Escalabilidad (horizontal: + servidores; vertical: +CPU, +memoria)
Alta Disponibilidad o Nivel de Servicio
Para satisfacer este tipo de requerimientos, en general, las aplicaciones enterprise han
adoptado un tipo de arquitectura casi estándar, que consiste en dividir el sistema en
cuatro capas físicas (tiers):
Presentación
Acceso al Negocio
Negocio o Dominio
Persistencia
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 179
Figura 9.1: Arquitectura Enterprise de 4 Capas Físicas
El Cliente, por ejemplo un browser (si hablamos de una aplicación web) o una ventana
gráfica del sistema operativo (si hablamos de una aplicación desktop), accede a la capa
de Presentación. La capa de presentación es responsable del formateo de los datos para
la visualización y de la interpretación de los comandos del usuario. En la capa de
presentación podrían vivir los servlets, por ejemplo, si hablamos de una aplicación web
en Java.
Esta capa podría acceder directamente a la capa de negocio o dominio, de hecho
muchos autores proponen eso. Pero en realidad, lo más correcto sería contar con una
capa (que a veces es muy delgada) entre la de presentación y la de dominio, para que
desacople ambas y podamos construir distintas presentaciones que accedan
concurrentemente y se abstraigan del uso de la lógica de negocio. Esta capa de la que
hablo es la de Acceso al Negocio o Capa de Aplicación o Capa de Servicio (Martin
Fowler la llama Service Layer). En la capa de Acceso al Negocio vivirán los casos de
uso del sistema, los requerimientos funcionales, los servicios de la lógica de dominio,
de la lógica de negocio, que deben ser expuestos. Esta capa tendrá permiso para
manipular los objetos de negocio que viven en la Capa de Negocio, en el dominio de la
aplicación. Podría decirse que se trata de un facade del dominio.
La Capa de Negocio es la más importante, ya que aquí es donde vive el modelo, donde
vive la lógica de negocio y, como antes mencionamos, la lógica de negocio es lo más
importante en una aplicación enterprise.
Por último, tenemos una capa de Persistencia, cuya función principal es la de
desacoplar la aplicación de la base de datos para no depender de un SGBD específico y
gestionar el acceso a la misma de forma eficiente. Esta capa debería hacernos menos
dolorosa una posible migración futura de base de datos.
Si prestan atención al gráfico de arquitectura pueden ver que la capa de Acceso al
Negocio apunta a la capa de Dominio, y a su vez, la capa de Persistencia también apunta
a la capa de Dominio. Estas flechas que parecen tan inocentes están simbolizando
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 180
dependencia. Según cómo el framework implemente la capa de Persistencia, el dominio
apuntará a la de Persistencia o al revés. Lo que trata de hacer un ORM como Hibernate,
por ejemplo, es invertir la dependencia del flujo normal de tiers para que el dominio
no tenga que conocer absolutamente nada de la aplicación. De esta forma, logramos
desacoplar por completo la lógica de negocio, para usarla en cualquier otra
aplicación o plataforma.
9.1.1.3. El Dominio es lo Único Importante
La capa de negocio es la más importante porque es la única que no depende de la
tecnología. Comúnmente se le llama Aplicación a lo que comprende las capas de
presentación, acceso al negocio y persistencia, y Negocio específicamente a la capa de
dominio.
Tiers de Aplicación:
Presentación
Acceso al Negocio
Persistencia
Tiers de Negocio:
Capa de dominio
Esta separación parece trivial, pero encierra conceptos fuertísimos que implican una
forma de llevar la programación de una aplicación sencilla, tradicional, a una aplicación
compleja como es una enterprise.
9.1.1.4. El dominio no depende de la aplicación
El primer concepto es que el dominio no depende de la tecnología o aplicación. Al no
depender de la aplicación, tenemos aislado lo que es el módulo donde trabajarán
fuertemente los analistas funcionales para representar el negocio en un modelo. Este
modelo o dominio, que no es más que un conjunto de objetos y clases interrelacionados
al mejor estilo de la programación orientada a objetos, es el negocio, y puede ser
reutilizado en distintas aplicaciones, puede ser desenganchado de una aplicación e
injertado en otra, con una tecnología completamente diferente, como si se tratara de una
pieza de Lego.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 181
Figura 9.2: El Dominio puede ser injertado en cualquier Aplicación
9.1.1.5. Tiers V.S. Layers
El segundo concepto es que la arquitectura del dominio es independiente de la
arquitectura de la aplicación. Y aquí nos encontramos con una primera disonancia
conceptual, que nos lleva a clasificar las capas en físicas (tiers) y lógicas (layers).
Capas Físicas o Tiers: Se llaman capas físicas porque en general son las más
propicias a ubicarse en servidores distribuidos físicamente. Podemos contar, por
ejemplo, con un servidor de aplicaciones distribuido, el SGBD podría ubicarse
en un servidor, el dominio podría ser accedido de forma remota (mediante RMI
o similar), el acceso al negocio podría ser consumido quizá mediante SOA por
diferentes plataformas y/o dispositivos y los clientes podrían ser muchos y
ubicarse en cualquier parte del planeta. De todas formas, aunque no tengamos
servidores disgregados en el espacio, separar la aplicación en capas físicas nos
ayuda a distribuir la lógica de la aplicación.
Capas Lógicas o Layers: Estas capas nos sirven para separar las
incumbencias en la lógica del negocio. Si bien cualquier capa física, por
dentro, podría contar con varias capas lógicas, lo que más nos interesa es
concentrarnos en la lógica de dominio. Por eso, cuando nos refiramos a layers,
nos estaremos refiriendo a las capas lógicas que viven en el tier del dominio.
Cuando un dominio es muy complicado y extenso, a menudo resulta útil para el
analista y/o diseñador optar por una arquitectura de capas, donde en cada capa
vivirán distintos paquetes que sólo se relacionan entre sí y con unos pocos
paquetes de la capa inferior, o para ser más prolijos, con la interfaz que publica
la layer inferior.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 182
Figura 9.3: Tiers V.S. Layers
9.1.1.6. Domain-Driven Design
El tercer y más trascendente concepto es que el dominio es lo único importante. Es
una idea fuerte, básica, simple, y muy difícil de aceptar y/o implementar. Por eso es que
no se suele aplicar en muchos ambientes de desarrollo, donde parece que la tecnología y
la forma de resolver los requerimientos no funcionales es lo más prioritario.
Domain-Driven Design (DDD) es un conjunto de buenas prácticas, patrones y
recomendaciones para construir software sólido y robusto a partir de la creación del
dominio. Las bases fundamentales de esta forma de trabajar fueron establecidas por
Eric Evans en su famoso libro: Domain-Driven Design: Tackling Complexity in the
Heart of Software (ISBN: 0-321-12521-5). Eric Evans es un defensor fanático de esta
idea de que el dominio es lo único importante y propone que todo el desarrollo de una
aplicación (sea enterprise o no), debería ser guiado por el dominio.
Domain-Driven Design está dividido en dos grandes incumbencias:
La construcción de buenos Modelos (Model-Driven Design): donde se
introducen los patrones Entities, Value Objects, Services, Modules, Aggregates,
Factories y Repositories, que sirven para la construcción efectiva de un modelo
de negocio correcto. Evans establece el polémico concepto de lenguaje ubicuo,
en el que propone que todos los integrantes de un equipo de trabajo (incluyendo
los clientes y expertos del dominio) deben comunicarse utilizando una misma
terminología. Esta terminología en general será la del experto del dominio o, en
algunos casos excepcionales, la que el analista funcional estableció mediante
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 183
mutuo acuerdo con el experto del dominio. Evans explica que es importante que
en toda comunicación, verbal o escrita, que se efectúe dentro del marco del
proyecto, se utilice el glosario que el analista y el experto del negocio
convinieron, inclusive si la charla es entre programadores. Esta imposición
acarrea un corolario polémico y fascinante: no sólo el modelo de dominio y los
diagramas de diseño deben usar este lenguaje, también el código fuente. Evans
propone un código escrito a muy alto nivel, donde los nombres de cada objeto
y/o componente del código (sea método, clase, variable, paquete, etc.) sean
extraídos directamente del glosario del lenguaje ubicuo.
Figura 9.4: Los Componentes Fundamentales de un Modelo Guiado por el Dominio
La preservación de la integridad del Modelo: no sólo es importante construir
un buen modelo, también es fundamental mantenerlo. Muchos de los conceptos
de Eric Evans van de la mano de la filosofía de las metodologías ágiles. Evans
nos dice que si hay modificaciones en el código o el diseño, deben ser reflejadas
automáticamente en el modelo y, si hay modificaciones en el modelo, deben ser
reflejadas en el diseño y en el código. Esta segunda parte del libro habla de
refactorizar constantemente, de actualizar periódicamente el glosario del
lenguaje ubicuo, de reconocer los conceptos claves del modelo y mantenerlos
vigentes a lo largo de todo el proceso de desarrollo. A medida que los dominios
van creciendo, van apareciendo patrones a nivel macro y formas de separar
contextos y de distribuirlos de diferentes formas para facilitar el desarrollo. Es
aquí donde entra más que nada el mundo de las aplicaciones enterprise, porque
si de ellas hablamos, hablamos de negocios complejos y de dominios extensos.
Evans presenta los patrones de Bounded Context, Continuous Integration,
Context Map, Shared Kernel, Customer-Supplier, Conformist, Anticorruption
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 184
Layer, Separate Ways, Open Host Service y Distillation, que atacan de
diferentes formas la escalabilidad y reorganización de modelos grandes.
Figura 9.5: Patrones dedicados a mantener la Integridad del Modelo
9.1.1.7. La importancia de un dominio portable
Todo esto nos lleva a la idea de construir un dominio portable. El negocio es el core, la
estrella única e indiscutida de toda aplicación enterprise. Hoy en día los frameworks que
hay en el mercado que logran la portabilidad del dominio son pocos. El framework es
parte de la tecnología, pero como su nombre lo indica es el marco de trabajo del
desarrollo de software. Si somos estrictos con las enseñanzas de DDD, llamarle
ingenuamente framework a una herramienta de trabajo es contradecir la filosofía de
DDD. Deberíamos llamarle framework al modelo, al dominio, y no a la tecnología
que usamos para construir la aplicación que ejecute ese dominio.
Hoy en día contamos con herramientas o plataformas que son compatibles con las
filosofías de DDD y que nos ofrecen una forma de construir la aplicación sin resultar
intrusiva con el dominio.
Si analizamos la historia de la Ingeniería del Software, podemos llegar a la conclusión
de que la madurez de los procesos de desarrollo (no sólo de aplicaciones enterprise) se
ve en el grado de separación de incumbencias entre la lógica de negocio y la lógica de
aplicación. La construcción de sistemas de software ha comenzado siendo muy técnica
para derivar cada vez más en abstracciones y nuevas abstracciones hasta alcanzar un
objetivo final: modelar y programar procesos de negocios independientes de la
tecnología.
9.1.2. Poniendo el Modelo de Dominio a trabajar
Evans asegura que, por lo general, los dominios de software no tienen casi relación con
las computadoras, los lenguajes de programación o cualquier otro aspecto técnico. En la
mayoría de los proyectos de software, la parte más crítica y compleja del desarrollo es
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 185
comprender el dominio del negocio. Para representar un dominio, los especialistas en
sistemas podemos usar lo que Evans llama Modelo de Dominio, que es una abstracción
rigurosamente organizada y selectiva del conocimiento. Un Modelo de Dominio puede
ser comunicado a través de un diagrama, un fragmento de código fuente (bien escrito,
de forma trasparente y explícita) o una oración en español, inglés o el idioma que sea.
9.1.2.1. Masticando el Conocimiento
Evans propone que la construcción de un modelo de dominio es un proceso iterativo.
El modelo debe irse construyendo de a poco entre el equipo de desarrollo y el experto
de dominio, a través de:
Brainstorming y refinamiento: DDD es una filosofía basada en las
metodologías ágiles y, como éstas, propone que la conversación sea el medio de
comunicación para compartir información de la forma más rápida y eficiente.
Evans propone que, en lo posible, todo el equipo de desarrollo tenga acceso a los
expertos de dominio, incluso los programadores, ya que son, en definitiva, los
que van a poner el modelo de dominio a trabajar.
Un Modelo de Dominio borrador: En base a la conversación se puede ir
construyendo un esbozo de lo que será el modelo de dominio. El experto irá
corrigiendo lo que a él le parezca que no está correcto y desarrollador y experto
llegarán a un acuerdo.
Un Diagrama de Clases temprano: Con este modelo de dominio borrador,
podemos construir una versión early de un diagrama de clases.
Un Prototipo muy simple guiado por un framework de automatización de
pruebas: Esto es, sentarse y, con el esbozo del diagrama de clases y el modelo
de dominio, construir un prototipo bien simple del dominio. Evans aconseja
evitar todo tipo de código de presentación o infraestructura. La idea es probar si
el negocio fue bien modelizado, no si los objetos se persisten correctamente o si
la aplicación se ve bien en determinado navegador. No queremos perder
tiempo en ninguna otra cosa que no sea el dominio. Y si el prototipo es una
ejecutable en consola, adelante.
Feedback del Prototipo: El experto de dominio interactuará con el prototipo,
revisando si las reglas de negocio son correctas, si el sistema hace lo que debe
hacer y, en base al feedback recibido, el equipo corregirá el modelo de dominio,
lo mejorará y lo refinará. Así, volverá a corregir el prototipo y también el
modelo de dominio.
Este proceso se repetirá hasta que el modelo, el diagrama y el prototipo sean correctos.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 186
Figura 9.6: Proceso iterativo para construcción de Modelos de Dominio
El modelo, el código y el diseño deben evolucionar juntos, de la mano, y de ninguna
forma se debe permitir que se desincronicen. Cuando un concepto se actualice en el
modelo, se deberá reflejar automáticamente en el código y en el diseño; y lo mismo al
revés. El conocimiento es un proceso de aprendizaje continuo.
Pero entonces, ¿para qué están los analistas? ¿Por qué no dejar que el experto de
dominio construya el modelo de su negocio y nosotros, los programadores, lo
codifiquemos? La respuesta es simple: porque el experto de dominio casi nunca es
consciente de la complejidad de sus procesos mentales en el día a día de su trabajo. El
experto de dominio da por sabidas un montón de reglas, pasa por alto un montón de
contradicciones y llena muchos baches con sentido común. El software no puede
hacer eso. Por eso, una de las tareas más difíciles de un analista de sistemas es construir
un modelo de dominio que refleje el negocio de la manera más fiel posible.
Un modelo es un sistema de abstracción que describe aspectos selectivos de un
dominio y puede ser usado para solucionar problemas relacionados con ese
dominio. Un modelo debe servir para un uso particular, por eso no es necesario (ni útil)
que el modelo sea lo más realista posible (fiel no es lo mismo que realista). El modelo
debe permitir al software ingresar en el dominio. Una porción de modelo que no se ve
reflejada en el código fuente final es irrelevante y debe ser descartada.
En un modelo hay cuestiones de negocio y cuestiones de diseño (que conciernen pura y
exclusivamente a la mantenibilidad y claridad del código). El uso de patrones de diseño,
por ejemplo, es algo fundamental a la hora de construir un modelo saludable. La buena
práctica de exponer de forma explícita las reglas de negocio es otra; exponerlas y
Modelo de Dominio (Draft)
Diagrama de Clases (Early)
Prototipo Simple
Feedback del Prototipo
Brainstorming y
Refinamiento
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 187
aislarlas, para que sean fáciles de encontrar y modificar, en caso de que no sean
correctas o hayan cambiado.
Masticar el conocimiento es un proceso lento, iterativo y de exploración, y uno nunca
sabe cuándo puede terminar.
9.1.2.2. Comunicación y el Uso del Lenguaje
El modelo de dominio es la base de un lenguaje común para un proyecto de software.
A este lenguaje común, Domain-Driven Design lo llama lenguaje ubicuo.
El lenguaje ubicuo de un proyecto debe incluir:
Nombres de clases y sus operaciones destacadas (sobre todo las relacionadas
estrechamente con el negocio)
Términos para discutir reglas de negocio que se han hecho explícitas en el
modelo
Nombres de patrones de análisis y de diseño que se aplican al modelo de
dominio
El lenguaje ubicuo debe ser utilizado por todas las personas involucradas en el proyecto,
inclusive programadores y expertos de dominio. Los programadores deben poder
describir en todo momento no sólo los artefactos del sistema, sino también las tareas y
funcionalidades, en función del lenguaje (inclusive cuando se trata de una charla
informal entre programadores).
El modelo de dominio es la columna vertebral del lenguaje ubicuo. El lenguaje debe
ser usado en todas las conversaciones y artefactos que se construyan dentro del contexto
del proyecto, incluyendo diagramas, documentos y, por supuesto, reuniones. Claro que
el lenguaje ubicuo no es un artefacto que surge con una sola iteración. Construir un
lenguaje común para todo el proyecto implica un proceso iterativo, de continua
refactorización, en el que se deben mantener sincronizados modelo, lenguaje y código,
ya que el código fuente también debe ser escrito respetando el lenguaje ubicuo. Si
los programadores descubren, por ejemplo, que una clase de dominio debe llamarse de
otra forma, no pueden refactorizar el nombre de la clase sin refactorizar también el
nombre del concepto en el modelo de dominio y en el lenguaje ubicuo. Un cambio en
el lenguaje ubicuo implica un cambio en el modelo y en el código; los tres
artefactos deben evolucionar juntos, como un único bloque de conocimiento.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 188
Figura 9.7: Los tres artefactos fundamentales de DDD
Una de las técnicas que según Evans ayuda mucho a la construcción de diagramas y de
un modelo de dominio es la de modelar en voz alta. Evans sugiere que hablemos del
modelo como si fuera del código, combinemos conceptos con las reglas permitidas por
el modelo. Debemos encontrar una forma fácil de contar la historia del dominio y los
nuevos términos e ideas reflejarlas en los diagramas y en el código.
Una de las ideas más revolucionarias de DDD es ésta de que todo el equipo utilice el
mismo lenguaje, incluido el experto de dominio. En general, la gente que viene del
mundo técnico desecha esta idea, pensando que el experto de dominio en cierta forma es
un chico, al cual hay que proteger mediante un escudo de ciertos conceptos que le
resultarían demasiado abstractos o que no entenderían (por no comprender la teoría de
la orientación a objetos). Estos analistas y/o desarrolladores tienen como principio
recolectar los requerimientos en la terminología del entrevistado. Sin embargo, DDD
obliga a olvidar este fundamento. DDD dice que si un experto de dominio no entiende
el modelo, entonces hay algo mal con el modelo.
El experto de dominio debe usar el lenguaje ubicuo, el lenguaje del modelo, en los
requerimientos, user stories y/o casos de uso. Así, conociendo y manejando la
terminología podrá trabajar directamente con el modelo a través de los UAT o
similares, sin intermediarios que funcionen como traductores.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 189
Figura 9.8: Lenguaje Ubicuo
El modelo de dominio puede contener diagramas, pero Evans sugiere que el modelo no
sean diagramas. Esto significa que, los diagramas por sí solos no dicen nada. Es
conveniente que haya más textos que diagramas (aunque los diagramas también son
necesarios, y mucho). La mayoría de los diagramas utilizarán la notación UML (quizá
en algunos casos convendrá relajar un poco la convención en favor de la claridad) y
quizá algunos que otros diagramas explicativos, que no sigan ninguna convención
establecida. Muchas veces un dibujo informal o un diagrama ad-hoc puede ayudar
a los miembros del equipo a entender ciertos aspectos complicados del diagrama
de clases o de otro diagrama o concepto del modelo.
Los diagramas no deben incluir demasiado detalle. Como nos recuerda Evans, nadie
puede ver el bosque a través de los árboles. Para un exhaustivo nivel de detalle,
tenemos el código, que si logramos que quede prolijo, claro, transparente y en función
del lenguaje ubicuo, puede servir para soportar a la documentación. Los diagramas
deben servir para enfocar la atención de las personas en los puntos centrales. No
siempre UML es capaz de transmitir los dos aspectos más importantes de un
modelo: el significado de los conceptos que se representan y el significado de lo que
los objetos deben hacer. Por eso es importante no oscurecer la idea que se quiere
transmitir con detalles de implementación. Por eso es importante mezclar los diagramas
UML y los diagramas explicativos con texto. Evans dice que prefiere escribir los
documentos con párrafos escritos, ilustrados con diagramas simples y selectivos. El
modelo no es el diagrama.
En caso de utilizar una tecnología de alto nivel que permita generar ejecutables a partir
de diagramas UML, entonces el UML es el lenguaje de programación. En este caso el
UML es el código, el UML contiene todos o casi todos los detalles. El UML se ha
convertido en el programa y el verdadero significado del modelo no se encuentra
realmente ahí.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 190
La documentación debe complementar el código y las conversaciones.
El mayor valor de un documento de diseño es explicar los conceptos del modelo, servir
como guía de navegación a través de los detalles del código y quizá introducirnos en la
filosofía, las convenciones y la forma de uso del modelo. Un documento debe estar
implicado en las actividades del proyecto. Si el documento no tiene impacto en el
lenguaje ubicuo, entonces algo en la metodología de trabajo está funcionando mal. Los
documentos que quedan desactualizados y no tiene sentido perder tiempo para
ponerlos al día, deben ser archivados como historial para que no creen confusión
en el lenguaje y la filosofía del dominio y del proyecto. Mantenerlo en el mismo
repositorio de los documentos actualizados, puede herir profundamente al lenguaje
ubicuo, al modelo de dominio y al código; en resumen, al proyecto.
El lenguaje ubicuo permite que una especificación de requerimientos, por ejemplo, sea
más concisa y menos ambigua. Lo ideal es usar al lenguaje ubicuo, y su evolución,
como guía para decidir qué documentos se mantienen vivos en el proyecto y qué
documentos deben archivarse en el historial.
9.1.2.3. Uniendo el Modelo y la Implementación
Todo programador sabe que un modelo funcional no puede servir como guía de
implementación. Todo aquel que se haya sentado al menos una vez a escribir código
sabe que, como cualquier dominio, el dominio de los lenguajes de máquina también
tiene sus baches que llenar, sus contradicciones, sus caminos sinuosos, sus trucos, en
resumen: sus detalles técnicos. Bajo ningún modo podemos pretender que un modelo de
dominio funcional sirva como guía para que los programadores escriban el código.
DDD, como muchas otras metodologías ágiles, no apoya la distinción marcada de
roles dentro del equipo de trabajo de un proyecto. Sin bien se necesitan las funciones
de analistas, diseñadores, desarrolladores, testers, líderes, Evans cree en un equipo
multidisciplinario, en el que cualquiera puede cumplir cualquier tarea en cualquier
momento. Las personas que van a meter mano en el código (llamémoslos
programadores, desarrolladores, técnicos o lo que sea) tienen que tener contacto con el
experto de dominio y deben participar en las reuniones donde se define el modelo de
dominio y se discute acerca de las reglas de negocio y de las palabras que deben o no ir
en el lenguaje ubicuo. En otras palabras: Evans no cree en una estructura jerárquica
dentro del proyecto, sino en miembros de un mismo equipo, que comparten las mismas
funciones, el mismo lenguaje y, lo más importante, los mismos objetivos.
Muchos proyectos se ven afectados por una falta de conexión entre el modelo y el
código. Esto suele suceder por una separación marcada, a veces artificial, entre análisis
y diseño. Los analistas construyen un modelo de análisis sin contemplar aspectos de
diseño, para que el modelo sirva sólo para fines de entendimiento del negocio. Pero, si
los desarrolladores encuentran que para implementar cierta funcionalidad, deben
cambiar o ignorar ciertos aspectos del modelo, que francamente no se adaptan a la
tecnología, y si para colmo a eso le sumamos que los programadores no tengan acceso
al experto de dominio para hacerle preguntas, el equipo de desarrollo se verá obligado
a no contemplar el modelo, implementar de la forma que a ellos les parece y así, al
poco tiempo, el modelo de dominio quedará tan desactualizado que no servirá para
nada, el código no responderá a las exigencias del usuario y el proyecto terminará en los
atrasos, presiones, tensiones y fracasos habituales.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 191
El modelo es una proyección del dominio. Una proyección de Domain-Driven Design
en un proyecto sería Model-Driven Design. Model-Driven Design descarta la
dicotomía entre el análisis y el diseño en favor de un modelo único que sirva para
los dos propósitos. Este enfoque demanda un modelo que funcione correctamente tanto
para el análisis como para el diseño. Cuando el modelo no muestra ser práctico para la
implementación, se debe refactorizar hasta conseguir uno nuevo; cuando un modelo no
muestra ser práctico para expresar los conceptos claves del dominio, se debe
refactorizar hasta conseguir uno nuevo. Esto acarrea un modelo más difícil de crear, un
análisis y un diseño más difíciles de construir (nadie dijo que DDD es fácil; nadie dijo
que desarrollar software fuera fácil), pero como recompensa tendremos un modelo
relevante y ejecutable a la vez, un modelo que podremos poner a trabajar.
Así, DDD ha convertido el desarrollo de software en un proceso iterativo de
refinamiento del modelo, refinamiento del diseño y refinamiento del código, como
una sola actividad indivisible.
Figura 9.9: Desarrollo de Software como Proceso Iterativo de Continuo Refinamiento
Para asegurarnos de mantener esta dependencia entre modelo y diseño lo más fuerte
posible, es importante trabajar sobre un paradigma que nos ayude con este trabajo. El
paradigma de los lenguajes imperativos estructurados, por ejemplo, no ayuda para nada.
Podemos hacer un modelo de dominio muy limitado con un lenguaje del estilo C, ya
que la condición de mantener la sincronía con el código es demasiado restrictiva. Un
lenguaje procedural no está para nada alineado con el paradigma del modelado. En
cambio, el paradigma de la orientación a objetos (Java podría ser un ejemplo) o el
paradigma lógico (al estilo Prolog, donde un programa es un conjunto de reglas lógicas
y hechos que operan sobre esas reglas), encaja perfecto en la filosofía de Model-
Driven Design.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 192
El desarrollo de software es todo diseño. La diferenciación de roles entre los
miembros de un equipo, la separación entre análisis, diseño y programación interfiere
directamente con la filosofía de DDD. Si las personas que escriben el código no se
sienten responsables por el modelo, o no entienden cómo el modelo puede funcionar en
una aplicación, entonces el modelo no sirve para nada. Si los desarrolladores no
mantienen sincronizados el modelo y el lenguaje con el código, el modelo deja de
servir. Con Model-Driven Design, una porción del código es una expresión del
modelo, así como una porción del modelo es una expresión del dominio con DDD.
Los programadores son modeladores. Cada programador debe estar involucrado en
las discusiones sobre el modelo y debe tener contacto con el experto de dominio, y
conocer, manejar y actualizar el lenguaje ubicuo.
Eric Evans asegura que el resultado de esta rigurosa práctica, tan fácil de
evangelizar pero tan difícil de implementar, es un sistema con funcionalidades
ricas, correctas y exactas basadas en un entendimiento profundo del dominio.
9.1.3. Los Componentes Fundamentales de un Modelo Guiado por el Dominio
Desarrollar un buen Modelo de Dominio es un arte, pero la tarea de diseñar e
implementar elementos individuales del modelo puede resultar relativamente
sistemática. En la Parte II de su libro Domain-Driven Design: Tackling Complexity in
the Heart of Software (ISBN: 0-321-12521-5), Eric Evans propone seguir un conjunto
de patrones de dominio, ya probados y estudiados, para conseguir modelar un dominio
que resulte práctico para la implementación.
Figura 9.10: Los Componentes Fundamentales de un Modelo Guiado por el Dominio
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 193
9.1.3.1. Aislando el Dominio
Usualmente, las líneas de código que efectivamente resuelven los problemas del
dominio constituyen apenas una pequeña porción del sistema. Sin embargo, la
importancia de estas líneas es absolutamente desproporcionada con respecto a su
tamaño. En un sistema grande la importancia de separar los objetos de dominio del
resto de la aplicación es extremadamente importante. La tarea principal de un
equipo de trabajo de DDD es aislar el dominio de los demás conceptos del sistema
relacionados con la tecnología. La estrategia de dividir las funcionalidades del
sistema en capas es uno de los caminos más apropiados para desacoplar el dominio
de la tecnología.
9.1.3.2. Layered Architecture
Anteriormente vimos una separación de capas típica, que es la que propone Martin
Fowler en su famoso libro Patterns of Enterprise Application Architecture, la
arquitectura de 4 capas físicas: Presentación / Service Layer / Dominio / Persistencia.
Pero Fowler explica muy bien que ésta no es la única forma de dividir en capas una
aplicación, y en el capítulo 8, en la última sección, da ejemplos de varios otros
esquemas de capas para arquitecturas enterprise:
Presentación / Controlador / Dominio / Data Mapping / Data Source [Capas de
Brown]
Cliente / Presentación / Negocio / Integración / Recursos [Capas del viejo core
de J2EE]
Presentación / Negocio / Acceso a Datos [Capas de Microsoft DNA]
Presentación / Aplicación / Servicios / Dominio / Persistencia [Capas de
Marinescu]
Consumer / Consumer Helper / Aplicación / Dominio / Acceso a Persistencia /
Public Stored Procedures / Private Stored Procedures [Capas de Nilsson]
Evans propone una arquitectura muy parecida a la de Fowler, pero sin capa de Acceso al
Negocio o Service Layer:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 194
Figura 9.11: Layered Architecture
Hay un montón de formas de dividir un sistema de software en capas, pero a través de la
experiencia y la convención, la industria del desarrollo de software ha convergido en
este patrón llamado Layered Architecture, el cual nos muestra que, por lo menos,
vamos a contar con una capa de dominio, una capa de infraestructura, una capa de
aplicación y algún cliente o interfaz de usuario que consuma esa aplicación. Los
nombres de las capas en las diferentes arquitecturas pueden variar, alguna capa puede
estar o no estar, o se puede dividir en dos o más, pero lo importante es que nunca
puede faltar la capa de Dominio o de Negocio. Esta capa se debe aislar del resto de
las capas del sistema. Esta capa será la expresión final del negocio, la
implementación limpia de un modelo guiado por el dominio. Domain-Driven Design
requiere sólo la capa de negocio para existir. Los objetos de dominio deben quedar
libres de la responsabilidad de mostrarse, guardarse y/o responder a tareas de la
aplicación, para poder enfocarse en expresar el modelo de dominio.
9.1.3.3. Anti-Patrón: Smart UI
Smart UI es un anti-patrón en el contexto de la filosofía de DDD, es una elección
mutuamente exclusiva con el enfoque de Eric Evans. Sin embargo, puede darse el caso
de tener que desarrollar una aplicación tan sencilla para la cual no haga falta adentrarse
en la complejidad de DDD. Optar por un Modelo de Dominio para organizar la
arquitectura de un sistema implica una curva de aprendizaje realmente alta. Martin
Fowler nos habla de Transaction Script, de Table Module, y de Domain Model, tres
patrones para encarar la arquitectura del sistema. DDD es un conjunto de buenas
prácticas para implementar un Domain Model.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 195
Smart UI es un patrón que entra en esta categoría de patrones de organización del
dominio de Fowler, y es mucho más sencillo que un Transaction Script, ya que Smart
UI no separa la vista de la aplicación y tan siquiera Transaction Script sí.
Evans dice que este patrón tiene varias ventajas: la productividad para el desarrollo de
una aplicación simple es muy alta, los desarrolladores no necesitan mucha experiencia
para construir una aplicación, etc. Pero también hay serias desventajas: la migración a
otra tecnología es imposible, el escalamiento se hace tortuoso, no hay reutilización de
código ni de conceptos (prácticamente no hay conceptos), la integración con otras
aplicaciones es casi imposible (salvo a través de una base de datos) y, por supuesto, la
desventaja más importante y, supongo, la que resume todo, Smart UI no es
Orientación a Objetos.
De todas formas, es un patrón más de dominio a considerar para cuando hay muy poco
tiempo, la aplicación es muy chica o se trata simplemente de un prototipo no evolutivo.
9.1.3.4. Un Modelo Expresado en Software
9.1.3.5. Associations
Un modelo que tiene una asociación entre un Cliente y un Vendedor muestra dos
cosas. Por un lado, abstrae una relación comercial entre dos personas físicas, reales. Por
el otro, representa una referencia entre dos objetos, la encapsulación de una búsqueda a
una base de datos a través de una clave foránea o cualquier otra implementación a nivel
diseño o código fuente.
Para que el modelo sea más sencillo y fácil de implementar, es importante limitar las
asociaciones lo más posible. Para esto, existen al menos tres criterios para simplificar
una asociación:
1) Imponer una dirección a la asociación
2) Añadir un cualificativo en algún extremo de la asociación (para reducir
la multiplicidad)
3) Eliminar las asociaciones no esenciales
El libro de Evans da como ejemplo una relación llamada presidente entre Persona y
País. Es una relación 1 a *, donde un País tuvo muchas Personas que fueron
presidentes.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 196
Figura 9.12: Asociación
A priori esta asociación es bidireccional. Sin embargo, dependiendo del dominio, quizá
no sea necesario que esta asociación realmente sea bidireccional. En este ejemplo,
raramente alguien va a necesitar conocer de qué País fue presidente tal Persona; la
consulta más interesante va a ser qué Personas fueron presidentes de tal País.
Claramente esta asociación puede convertirse en unidireccional aplicando el primer
criterio e imponiéndole la dirección desde País hasta Persona:
Figura 9.13: Imponiendo una relación a la Asociación
Este refinamiento refleja una mejor visión del dominio y hace más práctico al diseño.
Claramente una dirección es mucho más importante que la otra y, de esta forma, se
refleja en el modelo y desacopla el concepto importantísimo de Persona del concepto
mucho menos importante de presidente.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 197
El segundo criterio hace referencia a un entendimiento mucho más profundo del
dominio. Agregar un cualificativo en algún extremo de la asociación puede reducir esta
relación de 1 a * a una simple relación de 1 a 1, y como corolario explicitar una regla
muy importante en el modelo. En el ejemplo, puede darse el caso de que al negocio lo
que más le importe preguntar es quién fue el presidente de tal País en determinado
período:
Figura 9.13: Añadiendo un cualificativo a la Asociación
Notemos que ahora la relación presidente cualificada en un período entre País y
Persona, reduce la multiplicidad de la asociación a una Persona fue presidente de un
País en determinado período.
El último criterio es bastante obvio y hace referencia a que si en realidad no es relevante
para el modelo relacionar Personas con Países directamente conviene remover la
asociación. Recordemos: limitar las asociaciones lo más posible.
9.1.3.6. Entities
El patrón Entity se basa en que hay objetos que no son fundamentalmente definidos por
sus atributos, sino más bien por un hilo de continuidad e identidad que se mantiene a
través de todo un ciclo de vida. Una Entidad puede crearse, persistirse, recuperarse,
viajar a través de una red y armarse del otro lado, e independientemente de que para
reconstruirlo tengamos que crear una instancia nueva de objeto, la entidad deberá
conservarse. Un caso de pérdida de identidad en un sistema de software conduce a
serios problemas de corrupción de datos y errores fatales de ejecución.
Toda Entidad debe contar con un método para comparar su identidad con otra
instancia de su misma clase. A veces un objeto puede poseer la misma identidad que
otro, a pesar de no coincidir el valor de todos sus atributos. A veces puede ocurrir el
caso contrario. Una Entidad debe ser distinguible más allá de que exista otro objeto con
todos sus atributos equivalentes. La identidad de una Entidad va más allá del valor
de sus atributos.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 198
Una Entidad es algo que tiene continuidad a través de un ciclo de vida y es
distinguible independientemente de los atributos que son importantes para la
aplicación.
Se deben definir operaciones que garanticen la producción de un único resultado para
cada objeto. Se puede adjuntar un símbolo o un UUID (unique id). El modelo debe
definir qué significa tener una única identidad.
Ejemplos obvios de Entities pueden ser: Persona, Cliente, Factura, Vuelo, País, y un
largo etcétera.
La responsabilidad más básica de un Entity es establecer continuidad de modo que su
comportamiento sea claro y predecible. DDD recomienda modelar las Entidades lo más
pequeñas y sencillas posible, añadiendo sólo el comportamiento y los atributos
necesarios. Cualquier comportamiento y/o atributo que pueda ser trasladado a otra
Entidad o a otro Value Object, bienvenido sea. Y la operación obligatoria,
imprescindible, es la igualdad ante otro objeto.
La definición de identidad emerge del modelo. Definir las Entidades demanda entender
profundamente el dominio. Antes hablamos de generar un único ID para cada Entidad.
El ID se debe generar cuando la Entidad se crea por primera vez y luego, ese
identificador, deberá permanecer inmutable; se puede persistir en una base de datos,
pasar a través de una red, lo que sea, pero jamás se debe alterar el valor de un ID. Y
como el ID es generado automáticamente por el dominio, el usuario nunca debe verlo o
tener acceso a él, exceptuando que el mismo sea de particular interés, como puede ser
un trackID, un número de ticket, de reclamo, etc.
En muchos casos puede suceder también que el ID venga de afuera del sistema, desde
otro sistema, por ejemplo. Éste puede ser el caso del Documento Nacional de Identidad
(DNI) para Argentina o del Número de Seguro Social para Estados Unidos; estos ID
suelen ser generados por entidades gubernamentales. Usar como identidad un DNI o
cualquiera de este tipo de identificaciones no es un mecanismo seguro (puede suceder
que un extranjero no posea DNI o que una persona no desee revelar su Número de
Seguro Social por cuestiones de privacidad).
La generación de un único ID para definir la identidad de un Entity está muy
relacionado con el patrón Identity Field de Martin Fowler.
9.1.3.7. Value Objects
Mantener el seguimiento de las Entidades es esencial, pero darle identidad a otros
objetos que no son Entidades puede herir gravemente la performance y ensuciar el
modelo. No todos los objetos son Entidades. Hay algunos objetos que representan
aspectos descriptivos del dominio sin incluir un concepto de identidad. Estos objetos
son los llamados Value Objects.
Ejemplos de Value Objects pueden ser: Color, Dirección, Rueda, Lapicera,
Herramienta, etc. Sin embargo, decidir qué objetos son Value Objects y qué objetos
Entities dependerá mucho del dominio. En un sistema de servicios postales, Dirección
probablemente sea un Entity y no un Value Object como en la mayoría de los casos.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 199
Los Value Objects son instanciados para representar elementos del diseño de los
cuales importa qué son y no quiénes son.
Los Value Objects no necesariamente tienen que ser simples. Nada impide que un
Value Object contenga un montón de atributos y operaciones. En general, son objetos
usados para pasar por parámetro en los mensajes entre otros objetos. Frecuentemente
son transitorios, creados únicamente para la operación y luego descartados. Suelen ser
usados como atributos de Entities u otros Value Objects.
Como recomendación principal, Evans nos dice que debemos tratar a los Value
Objects como objetos inmutables. Es muy importante conceptualmente que los Value
Objects sean inmutables, ya que no nos interesa distinguir un Value Object de otro,
cuando necesitamos alterar su estado, simplemente tiramos el original y creamos uno
nuevo. Por otro lado, Evans también nos dice que es recomendable dedicar tiempo a la
optimización del manejo de los Value Objects, ya que suelen ser numerosos en
cualquier dominio. Esto nos lleva a una contradicción, ya que crear objetos inmutables y
tirarlos a cada rato, claramente no es óptimo. Por eso, hay casos especiales en los que,
en pos de la performance, se puede permitir que los Value Objects sean mutables; por
ejemplo cuando los valores del Value Objects cambian frecuentemente o cuando las
operaciones de creación y destrucción del objeto son muy costosas.
En general, se prefiere que los Value Objects sean inmutables.
9.1.3.8. Services
En algunos casos, el diseño más claro y pragmático incluye operaciones que
conceptualmente no pertenecen a ningún objeto. Sería un error encajarle esas
operaciones a cualquier Entidad o Value Object que se encuentre por ahí dando vueltas.
Por eso, para estos casos, estas operaciones deben ser incluidas como métodos en un
Servicio que se modele de forma explícita en el dominio.
Los Servicios son actividades, funciones, operaciones, no cosas. No conservan
estado; son stateless. Un Servicio es una operación ofrecida como una interfaz
suelta en el dominio, que no encapsula estado, como sí lo hacen los Entities y los
Value Objects. Services es un patrón bastante común en los frameworks técnicos, pero
el concepto también puede ser aplicado a la capa de dominio.
Un Servicio debe tener una responsabilidad bien definida, y esa responsabilidad y su
interfaz deben estar definidas como parte del Modelo de Dominio. Los nombres de las
operaciones deben surgir del Lenguaje Ubicuo o deben ser agregados. Los
parámetros y los resultados del Servicio deben ser objetos de dominio.
Cuando un proceso significativo, o una transformación en el dominio, no es una
responsabilidad natural de un Entity o un Value Object, se debe agregar una operación
al modelo como una interfaz independiente declarada como un Servicio.
Los Servicios no sólo son usados en la capa de dominio. Es importante distinguir los
Servicios que pertenecen al dominio, de los Servicios que pueden encontrarse en otra
capa de infraestructura o de aplicación. A veces puede resultar una tarea difícil. Una
regla valiosa puede ser considerar que los Servicios técnicos carecen absolutamente
de significado para el negocio, en cambio los de dominio forman parte del modelo,
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 200
y está bien que así sea. Un Servicio para exportar un reporte a PDF claramente es un
Servicio técnico. Un Servicio para transferir dinero de una cuenta a otra es un Servicio
de dominio.
Es muy común construir una capa de Servicios para manipular la capa de dominio. Es
una forma de desacoplar el dominio de la presentación. Muchos de los Servicios de
dominio pueden vivir en esta capa. Es la capa de Acceso al Negocio o Service Layer.
9.1.3.9. Modules
La modularización en la capa de dominio debe emerger como una parte significativa del
modelo; debe servir para contar la historia del dominio a gran escala, a muy alto nivel.
Hay un límite para la cantidad de objetos en los que una persona puede pensar a la vez.
Por eso, es importante modulizar de forma de agrupar conceptos o incumbencias de
negocio. En general, los lenguajes de programación proveen una sintaxis para crear
Módulos, y los IDEs hacen su parte mostrándonos esos módulos agrupados de forma
visual. Si estamos en el mundo de Java, por ejemplo, estos módulos serán los paquetes.
Bajo acoplamiento y alta cohesión son dos principios generales de diseño que aplican
tanto a clases individuales como a Módulos. Un bajo acoplamiento entre los diferentes
módulos, hace posible el análisis del módulo de forma aislada, con el mínimo de
referencias e interacciones con el mundo exterior, compuesto por un ecosistema de otros
módulos.
Refactorizar Módulos es más trabajoso y más difícil que refactorizar clases;
probablemente no sea una tarea que tengamos que hacer frecuentemente, a menos que
partamos de un diseño demasiado pobre.
Los Módulos son mecanismos de comunicación. Cuando se decide colocar una clase
dentro de algún módulo, es una forma de explicarle al próximo programador que mire el
diseño, que el concepto y la incumbencia que representa esa clase sólo se puede
entender dentro del contexto del Módulo en que fue ubicada. Si pensamos en términos
de un libro, los Módulos son los capítulos.
La modularización de un dominio es una tarea que requiere alto nivel de abstracción y
sumo cuidado. Un error temprano en la elección de los Módulos puede desembocar en
Módulos con alto acoplamiento, lo que después complicará muchísimo las tareas de
refactorización.
Pero, ¿qué significa un error en la modularización del dominio? Para DDD, por
supuesto, una forma errónea de modularizar la capa de dominio es de acuerdo a
incumbencias técnicas. Recordemos que la capa de dominio debe ser una proyección
del Modelo de Dominio, del cual el experto del negocio debe tener conocimiento y
comprender. Por eso la separación de Módulos debe ser de acuerdo a conceptos de
negocio. Eric Evans pone el ejemplo de muchas malas implementación de Java EE
usando EJBs. A menudo, se suelen encontrar Entity Beans en el modelo, que agrupan un
conjunto de atributos para después poder persistir o hacer cualquier otra cosa, y por otro
lado un conjunto de Session Beans que operan sobre esos datos haciendo uso de la
lógica de negocio. Claramente estos Entity Beans no se corresponden con los Entities
de DDD. Los Entities deben contener los datos y la lógica de negocio para operar sobre
esos datos. Hacer lo contrario es lo que Martin Fowler llama un modelo anémico.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 201
Encima, dice Evans, el error más grave se da a la hora de modularizar, cuando se suele
ubicar a los Entity Beans en un paquete y a los Session Beans en otro. Eso es un
ejemplo de modularización por incumbencias técnicas. En todo caso, el Entity Bean
y el SessionBean que pertenecen al mismo concepto (en resumen: al mismo Entity)
deberían vivir en un mismo paquete.
La separación de paquetes por incumbencias técnicas, tiene dos grandes costos:
El código no revelará de forma explícita el modelo
Los desarrolladores del dominio perderán la capacidad de dividir el modelo en
piezas significativas
Los Módulos, en una capa de dominio, sirven para separar el negocio en áreas o
incumbencias significativas y también para aislar la capa entera del resto del
código. En cambio, es muy posible que para el resto de las capas, una modularización
por incumbencias técnicas sea mucho más apropiada.
9.1.3.10. Paradigmas de Modelado
No es necesario que un Modelo de Dominio tenga que estar construido con un Modelo
de Objetos. Evans dice que existen Model-Driven Designs implementados en lenguajes
de paradigma lógico como Prolog, con modelos construidos en base a reglas lógicas y
hechos.
Si gran parte del problema del dominio se podría expresar de forma más natural
en otro paradigma, quizá tendría sentido cambiar de paradigma y elegir otra
plataforma de implementación. Pero también se puede dar el caso de que sólo una
parte del dominio responda a X paradigma, en cuyo caso, si la interdependencia con esa
pieza del problema es razonablemente pequeña, se puede encapsular. Podemos tener
un modelo que mezcle paradigmas, pero sólo si es necesario; mezclar paradigmas
aumenta la complejidad del desarrollo.
Como desarrolladores, a menudo nos enfrentamos a sistemas cuyos fragmentos de
código están implementados con diferentes paradigmas y éstos se mezclan de formas
más o menos elegantes. El ejemplo clásico es el del paradigma orientado a objetos y el
de tablas relacionales para los motores de base de datos. Los ORM, en estos casos, se
encargan de desacoplar de forma elegante estos dos paradigmas, quitando la
responsabilidad al programador de tener que lidiar con la impedancia entre ambos
diseños. Otro ejemplo clásico puede ser el de un conjunto de reglas de negocio
representado por un motor de reglas de negocio, o un proceso modelado con un
paradigma gráfico como el que implementa un motor de workflows.
El paradigma predominante hoy en día es el orientado a objetos. Evans nos da cuatro
consejos para lidiar con distintos paradigmas inmersos en un sistema orientado a
objetos:
No luchar contra la implementación del paradigma. Siempre existe otra
forma de pensar en el dominio. Es importante encontrar los conceptos del
modelo que encajan con el paradigma.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 202
Apoyarse en el lenguaje ubicuo, como nexo conductor entre ambos
paradigmas.
No obsesionarse con UML. UML es ideal para el paradigma de objetos, pero la
fijación de UML puede conducir a diseños demasiados retorcidos para otros
paradigmas.
Ser escéptico. ¿Es realmente apropiada la herramienta? Sólo porque tengamos
algunas reglas de negocio, por ejemplo, no significa que tengamos que lidiar con
la complejidad de un motor de reglas de negocios. Las reglas pueden ser
expresados en objetos, por ejemplo usando el patrón Specification. La mezcla
de paradigmas complicará el sistema a veces de forma innecesaria.
9.1.3.11. El Ciclo de Vida de un Objeto de Dominio
Cada objeto en el dominio tiene un ciclo de vida que puede ser más o menos complejo
dependiendo de su responsabilidad y/o propósito. Hay muchos objetos que son simples,
transitorios, que se crean con un constructor simple, se usan para algún cálculo y se
abandonan a las piadosas manos del recolector de basura. Pero los objetos que más nos
interesan son aquellos cuya vida se prolonga más allá de la existencia del programa que
las usa.
Figura 8.14: Ciclo de Vida de un Objeto de Dominio
Estos objetos son Entidades o Value Objects, que son creados a través de un Factory,
modificados en memoria y guardados, reconstruidos o archivados en un Repository.
9.1.3.12 Aggregates
Ejemplo típico: una Persona (un Entity) que tiene una Dirección (un Value Object).
Ambos objetos están asociados mediante una composición. La Dirección pertenece a la
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 203
Persona y no tiene razón de ser fuera de la misma. No se actualiza una Dirección, se
actualiza una Persona, se actualiza la dirección de una Persona.
Una Agregación es un grupo de objetos asociados que deben tratarse como una
unidad a la hora de manipular sus datos. En el caso del ejemplo, Persona y
Dirección forman parte de una misma Agregación. Otro ejemplo típico es el de Auto,
con Rueda y Motor; salvo que se trate de un dominio muy específico, los componentes
del auto sólo se modificarán a través del Auto. Auto, Rueda y Motor formarán una
única Agregación.
Cada Agregación cuenta con una Entidad Raíz (root) y una Frontera (boundary).
La Frontera define qué está dentro de la Agregación y qué no. La Entidad Raíz es una
Entidad contenida en la Agregación y será el único punto de entrada a la
Agregación. Esto significa que:
La Entidad Raíz es responsable de chequear las reglas de consistencia
(invariantes) entre los distintos objetos de la Agregación en la carga,
modificación y eliminación de datos.
La Entidad Raíz tiene una identidad global. Las Entidades Internas tienen
una identidad local. Las Entidades Internas sólo pueden ser distinguibles
dentro de la Agregación.
Fuera del contexto de la Agregación, no puede existir ninguna referencia a un
miembro que no sea la Entidad Raíz. Los demás miembros de la Asociación no
existen más allá de la Frontera.
La Entidad Raíz puede manejar referencias a Entidades Internas de otras
Agregaciones, pero estas referencias deben ser transitorias. La Entidad Raíz
no puede conservar la referencia.
La Entidad Raíz puede manejar referencias a Value Objects de otras
Agregaciones y no importa lo que suceda con ella; los Value Objects son sólo
valores y al no tener identidad tampoco tienen una relación fuerte con la
Agregación.
Sólo la Entidad Raíz puede ser obtenida directamente a través de un query a la
base de datos. Los demás objetos de la Agregación son obtenidos navegando a
través de las Asociaciones.
Los objetos miembro de la Agregación pueden contener referencias a otras
Entidades Raíz de distintas Agregaciones.
Una operación de eliminación debe remover absolutamente toda la Agregación
en una sola transacción. Con un lenguaje que provea un garbage collector, esto
es fácil, ya que no existe ninguna referencia fuera de la Agregación salvo la de
la Entidad Raíz. Por eso, al eliminar la Entidad Raíz, se eliminará la
Agregación completa.
Cuando se hace commit sobre un cambio efectuado en cualquier objeto dentro de
la Agregación, todas las reglas internas de consistencia (invariantes) de la
Agregación deben ser satisfechas.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 204
Las Agregaciones marcan el alcance de las reglas de consistencia que deben
mantenerse en todas las etapas del ciclo de vida de los objetos. Los siguientes dos
patrones, Factories y Repositories, operan sobre las Agregaciones, encapsulando la
complejidad de las transiciones durante el ciclo de vida.
9.1.3.13. Factories
El concepto de Factory es bien simple y quien conozca los patrones fundamentales de
Erich Gama entenderá perfectamente. Los Factories sirven para encapsular la creación
de objetos complejos. La creación de una Entidad, por ejemplo, podría ser tan compleja
que involucre a muchas otras Entidades y Value Objects. Imaginemos que se trata de
la Entidad Raíz de una Agregación. Es evidente que su creación implica la creación de
muchos otros objetos y el cumplimiento de reglas de negocio y consistencia que deben
hacerse cumplir. Para abstraer al cliente y al objeto en sí de este complejo mecanismo es
que se provee un Factory que se encargue del trabajo sucio.
Eric Evans presenta este patrón clasificándolo como componente fundamental de un
Model-Driven Design. El patrón nos dice que traslademos la responsabilidad de crear
instancias de objetos complejos y Agregaciones a un objeto externo, que puede no
tener responsabilidad en el modelo, pero que sigue siendo parte de la capa de
dominio. Luego, proporcionemos una interfaz que encapsule todo el complejo montaje
de relaciones, así el cliente puede referenciar a dicha interfaz y no a una instancia
concreta.
Mediante los Factories podemos crear Agregaciones enteras al momento de
instanciar la Entidad Raíz, haciendo cumplir todas sus invariantes.
Las implementaciones de Factory más populares son las de Erich Gama: Factory
Method, Abstract Factory, Builder y Prototype. Los cuatro son Patrones Creacionales,
según la clasificación de Design Patterns de GoF.
Los Factories sirven para la creación de objetos (la primera transición en el ciclo de
vida). Aquí se hace un fuerte énfasis en la utilización de Factories para la
reconstitución de objetos desde una base de datos, una red o lo que sea. Un Factory
usado para este propósito cuenta con dos principales diferencias respecto a los demás
Factories de creación:
No asigna nuevas identidades a los Entities. Sólo reconstituye el objeto desde la
persistencia, respetando su identidad ya definida.
Maneja distintas invariantes. Si el objeto ya existiera en algún lado del sistema,
las reglas de integración exclusivas para la alta no tienen sentido en esta fase del
ciclo de vida. Sin embargo, la reconstrucción puede ocasionar inconsistencias y
ciertas invariantes pueden no cumplirse. El Factory debería contar con una
estrategia de reparación, lo que puede complicar muchísimo más el código que
en un simple Factory de creación.
Por ende, los Factories encapsulan las transiciones de creación y reconstitución del
ciclo de vida del objeto. Otras transiciones cuya complejidad técnica pueden
contaminar de forma no deseada la capa de dominio son las que van y vuelven desde el
almacenamiento. Los encargados de encapsular estas transiciones son los Repositories.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 205
9.1.3.14. Repositories
Para operar sobre un objeto, necesitamos obtener una referencia al mismo. Existen dos
formas de obtener esta referencia:
A través de una operación de creación: un Factory, un constructor, un
operador de creación nativo del lenguaje.
A través de una asociación entre objetos: navegando a través de la relación
con otro objeto.
La segunda forma es muy poderosa y es uno de los conceptos fundamentales de la
orientación a objetos. Pero para poder llegar al objeto que queremos navegando a través
de la red de Asociaciones, necesitamos obtener el primer objeto de todos, el que para
una Agregación sería la Entidad Raíz.
Si bien desde un punto de vista técnico, la reconstitución de un objeto es un caso
concreto de la creación, desde el punto de vista del dominio, un cliente necesita un
medio práctico para adquirir referencias a objetos que ya existen persistidos en una base
de datos o en algún otro servidor de la red. El patrón Repository es un simple
framework conceptual que encapsula el proceso de reconstitución y lo diferencia del
proceso de creación encapsulado por el patrón Factory. Un Factory construye nuevos
objetos; un Repository busca objetos viejos, ya creados.
Un Repository representa todos los objetos de una cierta clase como un conjunto
conceptual (comúnmente emulado). Su interfaz es similar a la de una colección
ordinaria, en la que uno puede agregar o remover objetos. Los Repositories
encapsulan el mecanismo de reconstitución de los objetos. Reciben un simple request
para obtener un objeto o una lista de objetos que satisfagan un cierto criterio y ellos se
encargan de reconstruir los objetos de donde sea que haya que hacerlo, de una base de
datos, de un archivo de texto, de memoria, de una red, de un web service, etc., etc.
Es importante entender que los Repositories son también conceptos del dominio. Es la
forma que el modelo de dominio tiene de reconstituir Entidades y Value Objects y
almacenarlos para que puedan sobrevivir más allá de la ejecución del programa. La
interfaz del Repository vivirá en la capa de dominio; la implementación es posible
que viva en otra capa (por ejemplo en la de Persistencia). Un Repository relegará
las queries recibidas en un Data Mapper, en otro Repository o en algún otro objeto
específico de infraestructura que se encargue de resolver la petición. Martin Fowler
trata muy bien este tema desde el punto de vista técnico en su Patterns of Enterprise
Application Architecture, encapsulándolo en tres patrones del tipo Object-Relational
Metadata Mapping: Metadata Mapping, Query Object y Repository. Se puede
encontrar una buena implementación de Repository en ese libro, una implementación
anterior a DDD.
Un Repository sirve para crear la ilusión de que tenemos una colección en
memoria de absolutamente todos los objetos de dominio de un tipo específico. Necesitaremos un Repository para cada tipo de objeto al que accederemos de forma
global. Por supuesto que no haremos un Repository para cada objeto. A las demás
Entidades y Value Objects accederemos a través de las relaciones de este objeto
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 206
reconstituido con el Repository. Como regla general, es casi seguro que tengamos un
Repository por cada Entidad Raíz de cada Agregación.
9.1.4. Refactorizando Hacia una Visión Más Profunda
Domain-Driven Design (DDD) dice que el verdadero desafío en el desarrollo de una
aplicación empresarial es encontrar un modelo incisivo, que capture hasta los conceptos
más sutiles del dominio y los vuelque en un diseño práctico. Refactorizar es una
práctica que conduce a ese modelo. Refactorizar es rediseñar de forma tal que no se
altere la funcionalidad del sistema. Para esto puede ayudar un buen conjunto de
pruebas automatizadas que nos permitan experimentar con el código y el modelo con
relativa tranquilidad.
Evans habla de tres niveles de refactorización:
Nivel 1: cambios mecánicos que hacen más fácil de leer el código
Nivel 2: cambios que permiten aplicar patrones de diseño
Nivel 3: cambios que permiten obtener un modelo más profundo
Un modelo profundo (deep model) proporciona una lúcida expresión de las
incumbencias principales de un dominio y de su conocimiento más importante, a la
vez que aparta los aspectos superficiales.
9.1.4.1. Progreso
El retorno de inversión de la refactorización no es lineal. Las revelaciones más
importantes surgen abruptamente y así un modelo cada vez más profundo va
emergiendo gradualmente tras jornadas discontinuas de refactorización. Cada
refinamiento del código y del modelo aclara el panorama del equipo de trabajo. Este
tipo de progreso (breakthrough) no es una técnica, es un evento.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 207
Figura 9.15: Tiempos de Refactorización V.S. Valor agregado (Progresos)
A menudo, cuando la perspectiva de un progreso se presenta resulta aterrador. El
calendario siempre es apretado y decisivo. Pero hay que recordar que estos progresos
pueden implicar importantes adelantos en el desarrollo del proyecto. Evans nos
recomienda que no nos paralicemos tratando de lograr un progreso. Usualmente los
progresos se presentan solos después de varias modestas refactorizaciones. Concentrémonos en masticar el conocimiento y en cultivar un lenguaje ubicuo
robusto.
9.1.4.2. Haciendo Explícitos los Conceptos Implícitos
Muchas transformaciones del modelo de dominio ocurren cuando los desarrolladores
reconocen un concepto que acaba de insinuarse en una en una discusión o que estaba
implícito en el diseño y encuentran la forma de representarlo de forma explícita con uno
o más objetos o relaciones. Por eso, los desarrolladores deben estar atentos a este tipo de
insinuaciones y algunas veces deben salir a buscarlas de forma proactiva. Muchos de
estos descubrimientos surgen de:
Prestar atención al lenguaje del equipo
Eliminar torpezas en el diseño y aparentes contradicciones en las declaraciones
de los expertos
Explorar la literatura del dominio
Hacer mucha y mucha experimentación
Cuando el usuario o el experto de dominio usan palabras que no están en el lenguaje
ubicuo o en el diseño, estamos frente a un signo de advertencia bien grande. Es una
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 208
advertencia doblemente fuerte cuando no sólo los usuarios sino también los
desarrolladores usan este vocabulario ajeno al modelo. Es cuando tenemos que
sentarnos a refactorizar.
Los conceptos que necesitamos no siempre están flotando en la superficie, ni
emergiendo en las conversaciones o los documentos. Tendremos que cavar, incluso
excavar, incluso inventar. El lugar donde cavar es en la parte más débil de nuestro
diseño, el lugar donde los procedimientos son cosas complicadas, retorcidas y difíciles
de explicar, el lugar donde cada nuevo requerimiento parece agregar más complejidad.
A veces, para descubrir estos conceptos ocultos contamos con un experto de dominio
colaborador, a veces no. A veces contamos con bibliografía donde los conceptos están
bien definidos y detallados, a veces no. Muchos dominios no tienen modelos tan
refinados como los de contabilidad o finanzas, pero en otros casos podemos dar con
pensadores en el campo, quienes quizás se tomaron el trabajo de organizar y abstraer las
prácticas comunes del negocio, o artículos especializados, white papers, blogs, etcétera.
En DDD la experimentación es una de las prácticas más importantes. La
experimentación es la forma de saber si algo funciona o no. En el camino a un
modelo profundo hay mucha prueba y error, mucha obstinación y muchas lecciones
aprendidas.
¿Cómo modelar los conceptos menos obvios?
El paradigma de la orientación a objetos nos lleva a buscar y a inventar cierto tipo de
conceptos. Son los famosos sustantivos y verbos que nos enseñan cuando somos
neófitos en la materia, intentando en vano simplificar el proceso de relevamiento de un
dominio. Pero hay otras categorías de conceptos también muy importantes:
1) Restricciones Explícitas
Algunas veces las restricciones (constraints) encuentran un hogar dentro de un objeto o
un método cuya responsabilidad no está relacionada con la restricción de forma directa,
pero cuando la lógica se torna más complicada, es conveniente aislar la regla en una
porción de código aparte (sea método o clase), donde la restricción tenga espacio para
crecer naturalmente. Si la regla es más complicada debe tener su clase propia y hasta su
paquete.
Hay tres advertencias que podemos recibir de que una regla o restricción está
contaminando la clase en donde se ubicó y debe mudarse a un lugar más espacioso:
Evaluar la restricción requiere datos que no tienen que ver con la definición del
objeto
Reglas relacionadas aparecen en múltiples objetos, forzando la duplicación o
herencia de objetos que no deberían pertenecer a la misma familia
Un montón de diseño, requerimientos y conversaciones giran alrededor de la
restricción, pero en la implementación la regla está oculta en un código
procedural
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 209
DDD propone un patrón para encapsular reglas de negocio un poco más complicadas.
Es el patrón Specification.
2) Procesos como Objetos de Dominio
Reglas de negocio y procesos son dos grandes categorías de conceptos de modelo que
no vienen a la mente cuando estamos programando en un lenguaje orientado a objetos.
Los procesos pueden expresarse con el patrón Service. La clave para distinguir un
proceso que debe ser expuesto de forma explícita en el modelo de otro que debe
permanecer escondido entre Entidades y ValueObjects, es simple: ¿El proceso es algo
de lo que el experto de dominio habla mucho, o sólo se trata de un aspecto técnico,
de un proceso algorítmico del código?
Si bien los patrones Specification (para expresar reglas de negocio) y Service (para
expresar procesos) son elegantes y poderosos, hay casos en los que no resultan
suficientes y tenemos que adentrarnos en el mundo de los motores de reglas de negocios
y de workflows.
9.1.4.3. Diseño Flexible
El propósito final del software es servir a los usuarios. Pero primero, ese mismo
software debe servir a otros desarrolladores. Cuando un sistema con un comportamiento
complejo carece de un buen diseño, se vuelve difícil de refactorizar y de manipular. El
diseño flexible (supple design) es el complemento de un modelo profundo.
Simple no significa fácil. Para crear elementos que puedan ensamblarse en elaborados
sistemas y mantenerse simples se necesita de un estilo de diseño moderadamente
riguroso. Para abrazar el cambio, el diseño tiene que ser fácil de entender y, por ende,
fácil de modificar. Las primeras versiones suelen ser rígidas, toscas; sólo a través de
sucesivas refactorizaciones y sucesivos progresos, podremos alcanzar un diseño
flexible.
Figura 9.16: El camino hacia un Diseño Flexible
No hay ciencia ni fórmula para lograr esto; sin embargo, Evans propone un conjunto de
patrones que contribuyen a alcanzar el diseño flexible:
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 210
Figura 9.17: Patrones para alcanzar el Diseño Flexible
9.1.4.4. Intention-Revealing Interfaces
Cuando hablamos de lógica de dominio compleja queremos hablar de reglas, de
conceptos de negocio, que se interrelacionan en un modelo de dominio que puede
analizarse usando distintos niveles de abstracción. El paradigma de la orientación a
objetos nos permite abstraernos de los detalles del código, permite encapsular en clases
e interfaces un conjunto de instrucciones confiriéndoles un nombre, un concepto, una
responsabilidad. Así, cuando tengamos que comunicarnos con el experto de dominio,
con clientes programadores o hasta con nosotros mismos, podremos hablar de paquetes,
entidades, objetos de valor y servicios, pudiendo revisar las interfaces, la lista de operaciones, para darnos cuenta o recordar qué rol cumple cada uno.
Pero si las interfaces de los objetos de dominio están mal diseñadas y no revelan de
forma explícita lo que pueden hacer y cómo deben utilizarse, estamos en un problema,
porque el programador cliente que tenga que invocarlas deberá internarse en la
implementación y seguir el código para entender su uso. De esta forma estamos
perdiendo el tremendo valor de la encapsulación. Si un programador debe consultar
la implementación de un componente para poder usarlo, el valor de la
encapsulación se ha perdido.
El patrón Interfaces que Revelan sus Intenciones habla sobre darle nombres
significativos a las clases y a las operaciones que describan sus efectos y propósitos.
Una buena elección de nombres, de distribución de métodos, de parámetros, alivia al
programador cliente de la necesidad de entender los mecanismos internos del
componente. Estos nombres deberían ajustarse a los del lenguaje ubicuo para que los
miembros del equipo puedan inferir rápidamente su significado. Todos los mecanismos
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 211
complicados deben estar encapsulados dentro de una interfaz abstracta que se
comunique en términos de intenciones, en lugar de algoritmos.
Para ayudar a la buena elección de nombres, a la feliz distribución de métodos,
parámetros, paquetes, también se pueden considerar los test unitarios. Los test pueden
comunicar mucho más que un documento verboso o que un diagrama. Los test revelan
de forma explícita el comportamiento de las interfaces, desnudando las entradas y
las salidas, comunicando directamente al programador cliente la forma de uso del
componente.
9.1.4.5. Side-Effect-Free Functions
A groso modo, las operaciones pueden dividirse en dos categorías:
Comandos (commands)
Consultas (queries)
Las consultas obtienen información del sistema sin modificarlo (por ejemplo un getter).
Los comandos son operaciones que introducen un cambio en el sistema (por ejemplo un
setter). En una aplicación compleja, muchas operaciones llaman a otras operaciones y
éstas pueden invocar a muchas operaciones más. De esta forma, se vuelve muy difícil
anticipar todas las consecuencias de invocar una operación.
En teoría de programación las operaciones que devuelven un resultado sin producir un
efecto secundario (side effect), un cambio en el sistema, son llamadas funciones. Una
función puede ser llamada múltiples veces y retornar el mismo valor cada vez. Las
funciones son mucho más fáciles de probar que las operaciones que tienen efectos
secundarios. Las funciones implican menor riesgo.
Evans aconseja usar Funciones Libres de Efectos Secundarios siempre que sea
posible y sobre todo mantener los comandos y las consultas estrictamente separados en
diferentes operaciones. Además, siempre que se pueda devolver un Objeto de Valor
(ValueObject) como resultado de un cálculo es preferible antes que una Entidad. Un
Objeto de Valor puede crearse en el momento, para devolver el resultado. En cambio,
las Entidades tienen un ciclo de vida bastante más complicado. Los Objetos de Valor
son inmutables, lo que implica que, desde el punto de vista del modelo, todas sus operaciones son funciones.
9.1.4.6. Assertions
Separar estrictamente las funciones y los comandos es un excelente comienzo. Y si
además hacemos que estas operaciones formen parte de una interfaz declarativa, que
revela explícitamente sus intenciones, mucho más. Pero lamentablemente no nos
podemos librar de las operaciones que producen cambios en el sistema, sino nuestros
diseños no tendrían mucha utilidad. El patrón Aserciones (Assertions) hace explícitos
los efectos secundarios de los comandos, los declara para facilitar su uso. Las
Aserciones describen estados, no procedimientos, por lo tanto son fáciles de analizar.
Con Aserciones podemos establecer las post-condiciones de una operación y las
invariantes de clases y agregaciones. Si las Aserciones no pueden codificarse
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 212
directamente en el lenguaje de programación, siempre podemos escribir pruebas
unitarias. Los test unitarios siempre son buenos porque al configurarlos podemos hacer
explícitas las pre-condiciones de la operación y, después de la ejecución, chequeamos
con Aserciones que las post-condiciones se hayan cumplido.
En Java, por ejemplo, una prueba unitaria muy simple, usando Aserciones podría ser:
public void testSuma() {
int sumando1 = 25;
int sumando2 = 5;
int resultado = suma(sumando1, sumando2);
assertEquals(30, resultado);
}
Evans dice que las Aserciones no sólo deberían usarse en los unit test, también deberían
utilizarse en el código mismo, y poderse activar o desactivar por configuración,
dependiendo del ambiente en que estemos trabajando.
9.1.4.7. Conceptual Contours
El cuarto patrón, Contornos Conceptuales (Conceptual Contours) habla de
descomponer los elementos de diseño (operaciones, interfaces, clases, agregaciones,
etc.) en unidades cohesivas, teniendo en consideración las divisiones de importancia del
dominio, observando los ejes de cambio y estabilidad a través de sucesivas
refactorizaciones. Es importante modulizar el modelo, alinearlo con los aspectos
consistentes del dominio y establecer contornos conceptuales que permitan desglosar un gran sistema en áreas de conocimiento distintas.
El objetivo es un simple conjunto de interfaces que se combinen de forma lógica,
descubriendo así de forma explícita el lenguaje ubicuo en el modelo y en el código,
y apartando los aspectos irrelevantes. No hay una receta para esto. No hay procesos
fijos establecidos que ayuden a lograr acertados contornos conceptuales.
Lamentablemente, sí hay que tener mucha intuición, y mucho conocimiento del
dominio. Comúnmente los contornos conceptuales son resultados de muchas
refactorizaciones orientadas al negocio, muchas refactorizaciones rumbo hacia una visión más profunda.
9.1.4.8. Standalone Classes
Otra verdad cruel: las interdependencias complican el entendimiento de los modelos
y de los diseños, hacen que sean más difícil de testear y de mantener y, por lo
general, suelen acumularse fácilmente.
El objetivo de los patrones de Módulos y Agregaciones es limitar la red de
interdependencias entre los objetos. Pero incluso dentro de un Módulo o dentro de una
Agregación, la red de interdependencias puede ser lo suficientemente compleja para
retrasar severamente la evolución del proyecto. Por eso, cuando se está diseñando, se
debe pensar con cuidado cada dependencia. Cada dependencia debe ser sospechosa
hasta demostrar que es indispensable para definir al modelo. El bajo acoplamiento
entre clases y paquetes es fundamental. El objetivo no es eliminar todas las
dependencias, eso es imposible, pero sí eliminar todas las dependencias que no son esenciales.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 213
Refactorizar las más intrincadas dependencias en Clases Independientes (Standalone
Classes) es el objeto supremo de este patrón. El más bajo acoplamiento es la forma más
básica de reducir la sobrecarga conceptual en un modelo, y una Clase Independiente,
una clase suelta, es el acoplamiento más bajo que se puede lograr. (Por supuesto que el
nombre del patrón es más bien una metáfora; no se puede construir un sistema con todas
clases individuales sin relaciones entre sí, pero sí se puede aspirar a llegar al más bajo acoplamiento posible.)
9.1.4.9. Closure of Operations
Los matemáticos son fanáticos acerca de no mezclar conceptos distintos. Cuando uno
suma un número entero con otro número entero, el resultado también es un número
entero. Entonces se dice que los números enteros son cerrados bajo la operación de la
suma. La propiedad de clausura provee un modo de definir una operación sin la
necesidad de involucrar ningún otro concepto foráneo. El uso básico de XSLT es
transformar un documento XML en otro documento XML. Esta operación es cerrada
bajo el conjunto de los documentos XML. La propiedad de clausura simplifica
tremendamente la interpretación de una operación y es fácil encadenar o combinar
operaciones cerradas.
En diseño y/o programación esto se traduce en: siempre que se pueda, hacer que el
objeto que devuelva una operación sea del mismo tipo que sus parámetros. Una
operación cerrada provee una interfaz de alto nivel sin introducir una dependencia
con otros conceptos.
Este patrón, Clausura de Operaciones (Closure of Operations) se puede aplicar con
mayor facilidad en operaciones con ValueObjects. Lo que no quita que pueda aplicarse también a Entidades.
9.1.4.10. Diseños Declarativos
No importa qué tan guiado por el modelo sea nuestro diseño, siempre terminaremos
escribiendo métodos o procedimientos para producir el efecto de las interacciones
conceptuales, y siempre gastaremos tiempo en escribir código repetitivo que no agregue significado o comportamiento.
El Diseño Declarativo es una forma de escribir un sistema, o parte de un sistema, como
si se tratara de una especificación ejecutable, una muy precisa descripción de
propiedades que controlan el software. A nivel de código, esto puede ser construido de dos maneras:
A través de un mecanismo de reflexión, en tiempo de ejecución
A través de generación automática de código, en tiempo de compilación,
produciendo código convencional basado en la declaración
Este enfoque permite a otro desarrollador tomar la declaración como un valor literal,
como una garantía absoluta.
Generar un programa ejecutable a partir de una declaración de propiedades del modelo
es una especie de Santo Grial para un diseño guiado por el modelo (Model-Driven
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 214
Design), pero Evans asegura que en la práctica pueden presentarse problemas. Dos de
los problemas que plantea son bastantes comunes e incluso a mí me ha tocado la desgracia de experimentarlos:
Un lenguaje declarativo nunca va a expresar lo suficiente como para hacer
TODAS las cosas que son necesarias. Entonces llega la hora de tocar ―a mano‖
el código generado. Entonces llegan los dolores de cabeza, porque a menudo las porciones de código auto-generadas son muy difíciles de extender
El ciclo iterativo de desarrollo se hace casi imposible de seguir, ya que muchas
veces agregar código ―a mano‖ en código que fue auto-generado, provoca que la
herramienta no pueda volver a regenerar el código, que al regenerar el código se
pierda lo escrito ―a mano‖, o que el programa se destruya por completo. En otras
palabras: las técnicas de generación de código hacen que perdamos control.
La programación orientada a reglas con un motor de inferencia, como puede ser JBoss
Drools, es otro enfoque prometedor de Diseños Declarativos. Sin embargo, a pesar de
que la programación orientada a reglas es declarativa en principio, muchos sistemas
tienen lo que se llaman predicados de control que permiten agregar configuraciones de
rendimiento. Este código de control introduce efectos secundarios, por lo tanto el
comportamiento ya no está completamente dictado por las reglas declarativas, sino que hay que tener en cuenta "otros detalles" a la hora de introducir modificaciones.
Aunque Evans no lo menciona, también creemos que la programación orientada o
procesos haciendo uso un motor de workflows, es otro ejemplo de Diseño Declarativo
muy interesante.
Tenemos mucho más ejemplos de programación declarativa embebida en la
programación imperativa de hoy. Basta con citar muchas herramientas comunes como
los ORMs (Hibernate, TopLink, etc.), los frameworks MVC para las capas de
presentación, las herramientas de inyección de dependencia provistas por Spring, EJB3
o tantas otras especificaciones y/o implementaciones. Este tipo de frameworks trabajan
con mecanismos de reflexión. Muchas de ellas son muy estables, cumplen
funcionalidades específicas y alivian al programador de mucho código repetitivo y
propenso a errores.
9.1.4.11. Domain-Specific Language
Los lenguajes específicos de dominio son la expresión máxima de Domain-Driven
Design. Los DSL son lenguajes creados para resolver un problema particular de
dominio. Pueden ser declarativos o no, no es necesario que lo sean. Ejemplos existen
muchos: SQL es un DSL, un lenguaje que sirve para la comunicación con un motor de
base de datos, SMI es otro DSL, un subconjunto adaptado de ASN.1, que sirve para
definir árboles MIB en el protocolo SNMP de administración de redes, otro ejemplo de
DSL puede ser GPSS, un viejo lenguaje declarativo de simulación creado por IBM,
donde no se programa de forma imperativa mediante instrucciones, sino mediante
bloques declarativos que especifican lo que las transacciones (objetos transitorios)
tienen que hacer en un modelo simulado.
Nosotros también podemos crear nuestro propio DSL, si la complejidad del dominio lo
amerita; podemos crear un DSL para construir aplicaciones bancarias, un DSL para
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 215
construir aplicaciones para empresas de transporte de larga distancia, y todo lo que nos
podamos imaginar. Estos lenguajes podrían ser interpretados con un intérprete
programado en algún lenguaje imperativo (usando un parser y mecanismos de reflexión)
o podrían ser "compilados" escupiendo código auto-generado (el código que se genere podría ser imperativo: Java, C++, lo que sea).
La ventaja de diseñar un DSL es que podemos programar de forma extremadamente
expresiva, haciendo que los términos del lenguaje ubicuo pasen a formar parte de los
tipos de datos y de las expresiones que se pueden escribir en el programa de forma
nativa. Sin embargo, a pesar de que suena muy excitante, hay muchas desventajas
también:
El costo de inversión es muy grande al principio. Hasta que el DSL y el
lenguaje ubicuo estén estables y pueda realmente construirse aplicaciones usándolos puede pasar mucho tiempo
La habilidad (skill) de los desarrolladores tiene que ser muy grande. Deben tener
mucha experiencia en varios lenguajes de programación. Mucha experiencia en
el lenguaje sobre el que estén construyendo el DSL. Mucha experiencia en teoría de lenguajes en general
El desarrollo en general será más complejo. Las refactorizaciones serán más
complicadas. El código que soporta el DSL no será fácil de construir, ni fácil de
interpretar. Los cambios en el equipo de desarrollo podrían ser fatales
9.1.5. Links de Interés
http://www.domaindrivendesign.org/
http://www.infoq.com/presentations/model-to-work-evans
http://www.infoq.com/domain-driven-design
http://www.infoq.com/minibooks/domain-driven-design-quickly
9.2. Scrum
Scrum es un proceso de desarrollo de software iterativo e incremental utilizado
comúnmente en entornos basados en el desarrollo ágil de software. Fue aplicado por
Jeff Sutherland y formalizado por Ken Schwaber. Poco después, Sutherland y Schwaber
se unieron para refinar y extender Scrum.
Scrum no está concebido como método independiente, sino que se promueve como
complemento de otras metodologías, incluyendo XP, MSF o RUP. Enfatiza valores y
prácticas de gestión, sin pronunciarse sobre requerimientos, implementación y demás
técnicas. Se define como un proceso de management y control que implementa técnicas
de control de procesos.
Scrum se basa en los siguientes principios ágiles:
Colaboración estrecha con el cliente
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 216
Predisposición y respuesta al cambio
Prefiere el conocimiento tácito de las personas al explícito de los procesos
Desarrollo incremental con entregas funcionales frecuentes
Comunicación verbal directa entre los implicados en el proyecto
Motivación y responsabilidad de los equipos por la auto-gestión, auto-
organización y compromiso
Simplicidad. Supresión de artefactos innecesarios en la gestión del proyecto
9.2.1. Roles
Product Owner
o Representa a todos los interesados en el producto final
o Financia el proyecto
o Provee los requerimientos del sistema
o Prioriza los features
o Adapta los incrementos de cada Sprint
Scrum Master o Representa el management del proyecto
o Es responsable de velar y difundir los valores y las prácticas de Scrum
o Su tarea principal es remover impedimentos
Equipo de Desarrollo o Típicamente de 5-10 personas
o Multi-funcional
o Los miembros deben ser full-time
o Los equipos son auto-organizativos
o Sólo puede haber cambio de miembros entre los sprints
9.2.2. Ciclo de Vida de Desarrollo
Figura 9.18: Ciclo de Vida de Scrum
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 217
El Sprint es el período de tiempo durante el que se desarrolla un incremento de
funcionalidad. Constituye el núcleo de Scrum, que divide de esta forma el desarrollo de
un proyecto en un conjunto de pequeñas ―carreras‖. La duración máxima de un sprint
es de 30 días. Durante el sprint no se puede modificar el trabajo que se ha acordado en
el Sprint Backlog. Sólo es posible cambiar el curso de un sprint, abortándolo, y sólo lo
puede hacer el Scrum Master si decide que no es viable por algunas de las razones
siguientes:
La tecnología acordada no funciona
Las circunstancias del negocio han cambiado
El equipo ha tenido interferencias
Figura 9.19: Durante el transcurso de un Sprint no debe haber cambios
9.2.3. Artefactos
Product Backlog o Listado con los requerimientos del sistema
o Contiene: features, requerimientos de desarrollo (no funcionales), tareas
investigativas, bugs.
o Es responsabilidad del Product Owner:
Contenido
Priorización
Disponibilidad
o Está dada por una combinación de:
Trabajo basado en funcionalidad
Trabajo basado en tareas
o Es un documento dinámico que incorpora constantemente las
necesidades del sistema; se mantiene durante todo el ciclo de vida (hasta
el retiro del sistema)
Sprint Backlog o Trabajo o tareas determinadas por el equipo para realizar en un sprint y
lograr al final del mismo un incremento de funcionalidad
o Las de mayor duración deben intentar descomponerse en sub-tareas de
ese rango de tiempo
o En Scrum se debe ir registrando los tiempos día a día para poder armar el
gráfico de avance del proyecto
o El equipo agrega tareas cuando lo crea necesario, pudiendo eliminar las
que considere innecesarias, y ajusta estimaciones a medida se avanza
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 218
Burndown Chart
Figura 9.20: Ejemplo de Burndown Chart
El Burndown Chart es una gráfica mostrada públicamente que mide la cantidad de
requisitos en el Backlog del proyecto pendientes al comienzo de cada Sprint. Dibujando
una línea que conecte los puntos de todos los Sprints completados, podremos ver el
progreso del proyecto. Lo normal es que esta línea sea descendente (en casos en que
todo va bien en el sentido de que los requisitos están bien definidos desde el principio y
no varían nunca) hasta llegar al eje horizontal, momento en el cual el proyecto se ha
terminado (no hay más requisitos pendientes de ser completados en el Backlog). Si
durante el proceso se añaden nuevos requisitos la recta tendrá pendiente ascendente en
determinados segmentos, y si se modifican algunos requisitos la pendiente variará o
incluso valdrá cero en algunos tramos.
9.2.4. Reuniones
Spring Planning Meeting: Acude el equipo, el Scrum Master y el Product
Owner.
o El equipo de desarrollo toma el objetivo del Sprint y decide las tareas
necesarias para los ítems del Product Backlog
o El equipo se auto-organiza acerca de cómo alcanzar el objetivo del Sprint
o El Scrum Master NO asigna las tareas a los individuos
o El Scrum Master NO toma decisiones por el equipo
o Se crea el Sprint Backlog de acuerdo a las prioridades de negocio que
establece el Product Owner
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 219
Figura 9.21: Spring Planning Meeting
Daily Meeting: Reunión diaria del equipo con duración máxima de 15 minutos.
o Todos los días en el mismo sitio y a la misma hora
o Se recomienda que sea la primera actividad del día
o Deben acudir todos los miembros del equipo
o Moderada por el Scrum Master, que pregunta a todos los asistentes:
¿Cuál ha sido el trabajo realizado desde la última revisión diaria?
¿Cuál es el trabajo previsto para hoy?
¿Hay algo que necesitas, o que te impide realizar el trabajo
previsto?
o No se permite entrar en divagaciones o salirse del guión
o Sólo habla la persona que informa de su trabajo, el resto escucha y no
hay lugar para otras conversaciones
o Cuando un miembro informa de algo de interés para otros, o necesita
ayuda de otros, estos se reúnen al terminar la revisión diaria
o Las personas externas que estén presentes no pueden intervenir ni
distraer, y el Scrum Master puede limitar el número de personas externas
asistentes si lo considera oportuno
Sprint Review Meeting: Reunión en que participa: Scrum Master, Product
Owner, Equipo, todas las personas implicadas en el proyecto.
o Duración máxima: 4 horas
o Finalidad: presentar al Product Owner y a las demás personas las nuevas
funcionalidades implementadas
o Las funcionalidades no implementadas no se presentan
o En la reunión, los miembros del equipo muestran las nuevas
funcionalidades
o Al final de la reunión se interroga individualmente a todos los asistentes
para recabar impresiones, sugerencias de cambio y mejora, y su
relevancia
o El Product Owner trata con los asistentes y con el equipo las posibles
modificaciones en el Product Backlog
Sprint Retrospective Meeting: Acude el equipo y el Scrum Master, y
opcionalmente el Product Owner.
o Todos los miembros del equipo responden a dos preguntas:
¿Qué cosas fueron bien en el último sprint?
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 220
¿Qué cosas se podrían mejorar?
o El Scrum Master anota todas las respuestas
o El Equipo prioriza las mejoras posibles
o El Scrum Master no proporciona respuestas, sino que ayuda al equipo a
encontrar la mejor forma de trabajar con Scrum
o Las acciones de mejora localizadas que se puedan implementar en el
próximo Sprint deben introducirse en el backlog como elementos no
funcionales
9.2.5. Conclusiones
Scrum es una metodología ágil ideal para modelar proyectos críticos y complejos, en los
que la calidad y velocidad de implementación son fundamentales, pero donde los
requerimientos son vagos o muy cambiantes.
El énfasis de Scrum está en buscar que los proyectos de desarrollo le aporten a las
organizaciones el mayor valor posible a muy corto plazo, con resultados de calidad que
respondan a las necesidades reales del negocio.
A favor, tiene que:
Hace foco en entrega rápida de producto
Existe feedback continuo y frecuente sobre el progreso del desarrollo, gracias a
las reuniones diarias y de revisión de sprint
Da libertad al equipo de trabajo de usar las prácticas de desarrollo que prefieran
En contra, tiene que:
Puede caer en un modelo de codificar y probar, si no se realiza un coaching
El QA está embebido informalmente en muchas partes del ciclo de vida
Establece en el equipo de desarrollo una fuerte aversión a la documentación
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 221
Figura 9.22: Ficha Sinóptica de Scrum a modo de resumen
9.2.6. Fuentes
http://es.wikipedia.org/wiki/Scrum
Apuntes de la materia 75.51 – Técnicas de Producción de Software I. Clase
Scrum. Versión 1.2 – Mayo 2008
Apuntes de la materia 75.46 – Administración y Control de Proyectos
Informáticos II. Clase Scrum. 1er Cuatrimestre 2007
9.3. Introducción a EJB 3.0
9.3.1. ¿Qué es un EJB?
Enterprise Java Beans (EJB) es una plataforma para construir aplicaciones de
negocio portables, reusables y escalables usando el lenguaje de programación Java.
Desde el punto de vista del desarrollador, un EJB es una porción de código que se
ejecuta en un contenedor EJB, que no es más que un ambiente especializado (runtime)
que provee determinados componentes de servicio.
Los EJBs pueden ser vistos como componentes, desde el punto de vista que encapsulan
comportamiento y permite reutilizar porciones de código, pero también pueden ser
vistos como un framework, ya que, desplegados en un contenedor, proveen servicios
para el desarrollo de aplicaciones enterprise, servicios que son invisibles para el
programador y no ensucian la lógica de negocio con funcionalidades trasversales al
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 222
modelo de dominio (a menudo requerimientos no funcionales o aspectos). En la
especificación 3.0, los EJB no son más que POJOs (clases planas comunes y
corrientes de Java) con algunos poderes especiales implícitos, que se activan en
runtime cuando son ejecutados en un contenedor de EJBs.
Figura 9.23: Los EJB son POJOs a los que se le agregan trasversalmente servicios de infraestructura
Los servicios que debe proveer el contenedor de EJBs deben ser especificados por el
programador a través de metadata de configuración que puede escribirse como:
Anotaciones de Java5 intercaladas en el código de las clases.
Descriptores XML (archivos XML separados).
A partir de EJB 3 se puede usar cualquiera de estas dos técnicas. Las técnicas no son
exclusivas, pueden coexistir anotaciones con descriptores XML y, en el caso de
superponerse la metadata, los XML tendrán prioridad y podrán sobreescribir las
anotaciones.
Algunos ejemplos de los contenedores más populares que hay actualmente en el
mercado son: Glassfish, de Sun Microsystems, JBoss Application Server, de Red Hat,
BEA Weblogic Server y Oracle Application Server, ambos de Oracle y WebSphere de
IBM.
Una anotación transforma un simple POJO en un EJB.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 223
Figura 9.24: Una anotación transforma a un simple POJO en un EJB
9.3.2. Tipos de EJBs
Existen tres tipos de EJBs:
Session Beans: en una aplicación enterprise típica, dividida en cuatro grandes
capas o layers (presentación, lógica de negocio (business logic), persistencia y
base de datos), los Session Beans viven en la lógica de negocio. Hay dos grandes
tipos de Session Beans: Stateless y Stateful, el primero no conserva el estado de
ninguno de sus atributos de la invocación de un método a otro y el segundo
conserva el estado a lo largo de toda una sesión. Los Session Beans Stateless son
los únicos que pueden exponerse como web services.
Message-Driven Beans (MDBs): también viven en la lógica de negocio y los
servicios que proveen son parecidos a los Session Beans, con la diferencia de
que los MDBs son usados para invocar métodos de forma asincrónica. Cuando
se produce la invocación de un método de un MDB desde un cliente, la llamada
no bloquea el código del cliente y el mismo puede seguir con su ejecución, sin
tener que esperar indefinidamente por la respuesta del servidor. Los MDBs
encapsulan el popular servicio de mensajería de Java, JMS. Hay una analogía
muy interesante en el libro que dice que los MDBs son a JMS lo que JDBC es
a SQL.
Entities: los entities viven en la capa de persistencia y son los EJBs que manejan
la Java Persistence API (JPA), también parte de la especificación de EJB 3.0.
Los entities son POJOs con cierta metadata que permite a la capa de persistencia
mapear los atributos de la clase a las tablas de la base de datos y sus relaciones.
Los Session Beans son invocados por el cliente con el propósito de ejecutar operaciones
de negocio específicas, como por ejemplo podría ser chequear la historia crediticia del
cliente de un banco. El nombre sesión implica que la instancia del bean estará
disponible durante una unidad de trabajo (Unit of Work19
) y no sobrevivirá a una caída
del servidor. Un bean de sesión sirve para modelar cualquier funcionalidad lógica
de una aplicación.
Los MDBs también procesan lógica de negocio, pero un cliente nunca invoca a un
método de un MDB directamente. El sistema de mensajería asincrónica propone la
utilización de una capa intermedia en la comunicación entre el productor y el
consumidor del mensaje. En EJB 3, esta capa se llama MOM (Message-oriented
19 http://martinfowler.com/eaaCatalog/unitOfWork.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 224
middleware). Básicamente la MOM es un software que permite funcionar como
servidor de mensajería, reteniendo los mensajes del productor y enviándolos
posteriormente al consumidor en el momento en que esté disponible para recibirlo. (Es
un funcionamiento similar al de un servidor de correo electrónico.) Algunos ejemplos
típicos de servidores de mensajería son WebSphere MQ de IBM, SonicMQ, Advanced
Queueing de Oracle y TIBCO.
9.3.3. Entities y la Java Persistence API
Debido al auge de los frameworks ORM (Hibernate, TopLink, etc.), Sun tuvo que
replantear su complicada y anti-natural especificación de persistencia, que tantos
dolores de cabeza les daba a los programadores que usaban EJB 2, al extremo que optó
por reescribirla casi por completo. Así nació JPA.
JPA persiste automáticamente los objetos Java usando la técnica de ORM (mapeo
objeto-relacional). Los ORM del mercado se han adaptado a esta especificación y, hoy
en día, cualquier framework de persistencia ORM soporta JPA.
El estándar JPA define:
La configuración ORM mediante metadata que mapea entidades a tablas
relacionales.
La interface EntityManager, que define una API estándar para realizar las
operaciones de persistencia (CRUD) de las entidades.
El Java Persistence Query Language (JPQL), para consultas y lecturas de datos
de aplicación persistidos (algo así como un SQL orientado a objetos).
En general, los contenedores proveen su ORM. Por ejemplo, JBoss provee Hibernate,
Glassfish provee TopLink. JPA puede funcionar independientemente del resto de los
componentes de EJB 3 y hasta puede ser usado en una aplicación desktop común y
corriente, una aplicación Java SE.
Los entities son los objetos Java que se persisten en la base de datos. Mientras que los
Session Beans son los verbos del sistema, las entidades son los sustantivos.
9.3.4. ¿Qué es un contenedor de EJBs?
Así como cuando compilamos una clase simple de Java, necesitamos una Java Virtual
Machine (JVM) para ejecutarla, necesitamos un contenedor de EJBs para ejecutar
los Session Beans y los MDBs.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 225
Figura 9.25: Contenedor Java EE
Un contenedor Java EE es un servidor de aplicaciones que es capaz de ejecutar EJBs,
puede servir como web container y además puede incluir otras APIS y servicios, como
por ejemplo el de persistencia. Algunos servidores de aplicaciones pueden proveer
solamente un contenedor web, como es el caso de Apache Tomcat, o sólo proveer
servicios de persistencia, como es el caso de Hibernate. Un servidor de aplicaciones
como JBoss trae un servidor Apache Tomcat y un servidor Hibernate, que se ejecutan
dentro de forma transparente.
9.3.5. ¿Qué servicios proveen los EJBs?
Integración: Proveen una forma de acoplar en tiempo de ejecución diferentes
componentes, mediante simple configuración de anotaciones o XMLs. El
acoplamiento se puede hacer mediante Inyección de Dependencia (DI) o
usando JNDI, como se hacía en EJB 2. La integración es un servicio que
proveen los beans de sesión y los MDBs.
Pooling: El contenedor de EJBs crea para componentes EJB un pool de
instancias que es compartido por los diferentes clientes. Aunque cada cliente ve
como si recibiera siempre instancias diferentes de los EJB, el contenedor está
constantemente reusando objetos para optimizar memoria. El pooling es un
servicio que se aplica a los Stateless Session Beans y a los MDBs.
Thread-safely: El programador puede escribir componentes del lado del
servidor como si estuviera trabajando en una aplicación sencilla con un solo
thread (hilo). El contenedor se encarga de que los EJBs tengan el soporte
adecuado para una aplicación multi-usuario (como son en general las
aplicaciones enterprise) de forma transparente, asegurando el acceso seguro,
consistente y performante. Aplica a los beans de sesión y a los MDBs.
Administración de Estados: El contenedor de EJBs almacena y maneja el
estado de un Stateful Session Bean de forma transparente, lo que significa que el
programador puede mantener el estado de los miembros de una clase como si
estuviera desarrollando una aplicación desktop ordinaria. El contenedor maneja
los detalles de las sesiones.
Mensajería: Mediante los MDBs es posible desacoplar por completo dos
componentes para que se comuniquen de forma asincrónica, sin reparar
demasiado en los mecanismos de la JMS API que los MDBs encapsulan.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 226
Transacciones: EJB soporta el manejo de transacciones declarativas que
permiten agregar comportamiento transaccional a un componente simplemente
usando anotaciones o XMLs de configuración. Esto significa que cuando un
método de un EJB (Session Bean o MDB) se completa normalmente, el
contenedor se encargará de commitear la transacción y efectivizar los cambios
que se realizaron en los datos de forma permanente. Si algo fallara durante la
ejecución del método (una excepción o cualquier otro problema), la transacción
haría un rollback y es como si el método jamás se hubiera invocado.
Seguridad: EJB soporta integración con la Java Authentication and
Authorization Service (JAAS) API, haciendo casi transparente el manejo
transversal de la seguridad. Aplica a todos los Session Beans.
Interceptors: EJB introduce un framework liviano y simple para AOP
(programación orientada a aspectos). No es tan robusto y completo como otros,
pero es lo suficientemente útil para que sea utilizado por los demás servicios del
contenedor para brindarnos de forma invisible los crosscutting concerns de
seguridad, transacciones, thread-safely. Además, nosotros, como
programadores, podemos agregar nuevos aspectos como logging o auditoria y
demás de forma configurable.
Acceso Remoto: Es posible acceder de forma remota a distintos EJBs de forma
sencilla, simplemente mediante la Inyección de Dependencia. El procedimiento
para inyectar un componente local o uno remoto es exactamente el mismo,
abstrayéndonos de las complicaciones específicas de RMI o similares. Este
servicio aplica únicamente a los Session Beans.
Web Services: Un Stateless Session Bean puede publicar sus métodos como
web services mediante una sencilla anotación.
Persistencia: EJB 3 provee la especificación JPA para el mapeo de objetos
(Entities) a tablas.
Catching and Performance: JPA provee de forma transparente un importante
número de servicios que permiten usar un caché de entidades en memoria y una
lectura y escritura sobre la base de datos altamente performante.
9.3.6. HelloUser Example
El ejemplo provisto por el libro EJB 3 in Action cuenta con una simple interfaz llamada
HelloUser con un único método sayHello. Luego, se muestra una clase que implementa
esa interface, HelloUserBean, y que además, mediante una simple anotación,
@Stateless, se le indica al contenedor que HelloUserBean es un Stateless Seasion Bean.
A continuación, del lado del cliente, se muestra el código para inyectar el bean en un
atributo privado llamado helloUser, del tipo HelloUser. En un método del cliente
llamado hello(), se invoca el método sayHello() del bean de sesión (notar que sayHello()
es un método que se ejecuta del lado del servidor, por ende la salida no se verá en la
consola del cliente, sino en la consola del servidor, que a menudo es un archivo de log
del servidor de aplicaciones).
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 227
Para inyectar de forma transparente el bean de sesión en el objeto del tipo HelloUser, se
usa la anotación @EJB. Otra opción podría haber sido la única que había en EJB 2:
localizar el componente mediante JNDI.
9.3.7. Código del Lado del Servidor
package ejb3inaction.example;
public interface HelloUser {
public void sayHello(String name);
}
package ejb3inaction.example;
import javax.ejb.Stateless;
@Stateless
public class HelloUserBean implement HelloUser {
public void sayHello(String name) {
System.out.println("Hello " + name + " welcome to EJB 3!");
}
}
9.3.8. Código del Lado del Cliente ...
@EJB
private HelloUser helloUser;
void hello() {
helloUser.sayHello("Curious George");
}
...
9.3.9. Inyección de Dependencia
La Inyección de Dependencia (DI) es un concepto (o patrón) de arquitectura que está
fuertemente emparentado con la Inversión de Control (IoC). Básicamente la DI se
especializa en inyectar objetos en una clase, en lugar de ser la propia clase quien cree
el objeto. En EJB 3 es el contenedor de EJBs quien inyecta en cada objeto los objetos
necesarios según las relaciones plasmadas en los descriptores de despliegue o en las
anotaciones.
Para el que le interese conocer más de este patrón, hay un artículo muy pero muy
interesante de Martin Fowler que se llama: ―Inversion of Control Containers and the
Dependency Injection pattern20”. Fowler categoriza los distintos tipos de DI y
ejemplifica cada uno con código de distintos frameworks. Cuando Fowler escribió este
fascinante artículo, todavía no existía la especificación de EJB 3, por lo tanto no hay
ninguna mención a esta forma de inyectar beans mediante anotaciones, pero igual vale
la pena leerlo.
Uno de los grandes avances de EJB 3 es que nos permite reemplazar los descriptores
XML de despliegue, en extremo verbosos y aburridos, por metadata annotations
inmersas en el código (esto no se pudo lograr hasta que no salió la característica de
annotations con Java5). En un ejemplo mostrado anteriormente, la inyección se llevó a
20 http://martinfowler.com/articles/injection.html
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 228
cabo en el código del cliente. Mediante la anotación @EJB, se inyectó un objeto del
tipo HelloUser en el atributo helloUser de la clase del cliente:
@EJB
private HelloUser helloUser;
Recordemos que HelloUser era una interface, por ende no se puede instanciar sin una
implementación. El milagro en realidad sucedió cuando, en un código cualquiera de la
clase del cliente, pudimos utilizar el objeto helloUser sin enfrentarnos a un
NullPointerException, a pesar de no haber alocado memoria (new) en ninguna
parte del código.
void hello() {
____helloUser.sayHello("Curious George");
}
El secreto está en la Inyección de Dependencia. La anotación @EJB, que parece tan
inocente, es una orden directa al contenedor de EJBs para que cree una instancia de
HelloUser con la implementación proporcionada del lado del servidor, que recordemos
era ésta:
@Stateless
public class HelloUserBean implement HelloUser {
public void sayHello(String name) {
System.out.println("Hello " + name + " welcome to EJB 3!");
}
}
¿Para qué sirve la DI entonces? En su forma más pura, la DI sirve para desacoplar
completamente una interface de su implementación, por lo que podríamos cambiar
de implementación en tiempo de ejecución. Noten que en ninguna parte del código
del cliente es necesario utilizar la implementación HelloUserBean. Gracias al
polimorfismo podemos usar su interface HelloUser sin tener conocimiento de
HelloUserBean y, gracias a la DI, podemos olvidarnos del new HelloUserBean() que
es lo único de lo que el polimorfismo no permite abstraernos.
En este caso, además, tenemos el adicional de que la DI reemplaza el terriblemente
rutinario código de JNDI lookup, que los programadores de EJB 2 conocen mejor que
yo. Una aplicación tradicional J2EE usa JNDI como mecanismo para que un
componente pueda acceder a otro. El problema con JNDI es que acopla fuertemente el
código del cliente con el código del servidor, con todas las desventajas que esto implica
en el desarrollo y el testing.
Como ya dijimos, el objetivo principal de DI es hacer que los componentes estén lo
menos acoplados posible. Cuando se usa JNDI, es responsabilidad del cliente buscar y
obtener la referencia al objeto. La DI es exactamente lo opuesto a JNDI: es
responsabilidad del contenedor inyectar un objeto basado en una dependencia
declarada.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 229
Figura 9.26: JNDI v.s DI (Inyección de dependencia)
9.3.10. Ejemplo de la aplicación ActionBazaar
El ejemplo del capítulo 2 de "EJB 3 in Action" es muchísimo más completo e
interesante. Trata sobre una aplicación llamada ActionBazaar, que no es más que un
simple sitio de subastas como eBay.
Figura 9.27: Proceso de subastar
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 230
Figura 9.26: Arquitectura de ActionBazaar, el ejemplo de EJB 3 in Action
En el ejemplo, se utilizan cuatro beans: dos Session Beans (PlaceBidBean y
PlaceOrderBean) y un Message-Driven Bean (MDB) (OrderBillingMDB), que viven en
la capa de lógica del negocio, y dos Entities, que viven en la capa de persistencia.
Además, de los dos Session Beans, uno es un Stateless Bean (PlaceBidBean) y el otro
es un Stateful Bean (PlaceOrderBean).
9.3.11. PlaceBinBean: un stateless bean
Los beans de sesión sirven para modelar procesos de negocio o acciones,
especialmente los procesos y acciones percibidos por el usuario. Los stateless session
beans, en particular, se usan para modelar acciones o procesos que pueden hacerse de
una sola vez, que no necesitan guardar su estado.
En el gráfico de la sección anterior, vemos que PlaceBidBean es invocado desde la
interfaz de usuario mediante el servicio addBid. Add Bid será un método del bean de
sesión, que persistirá una oferta a través de Bid Entity.
@Local // Marks EJB business interface as local
public interface PlaceBid {
public Bid addBid(Bid bid);
}
...
@Stateless // Marks POJO as stateless session bean
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 231
public class PlaceBidBean implements PlaceBid {
...
public PlaceBidBean() {}
public Bid addBid(Bid bid) {
return save(bid);
}
}
PlaceBid puede ser llamado, por ejemplo, desde un JSP o un servlet. En el libro usan un
servlet llamado PlaceBidServlet para invocar el servicio de addBid:
public class PlaceBidServlet extends HttpServlet {
@EJB // Injects instance of PlaceBid EJB
private PlaceBid placeBid;
public void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// Se leen los datos que vienen en el request
int bidderId =
Integer.parseInt(request.getParameter("bidder_id"));
int itemId =
Integer.parseInt(request.getParameter("item_id"));
double bidAmount =
Double.parseDouble(request.getParameter("bid_amount"));
// Se crea la oferta y se setean los atributos
Bid bid = new Bid();
bid.setBidderID(bidderID);
bid.setItemID(itemID);
bid.setBidAmount(bidAmount);
// Se invoca el addBid del Bean de Sesión
// Notar que jamás necesitamos
// hacer un new de placeBid,
// El contenedor ya lo hizo por nosotros.
placeBid.addBid(bid);
...
}
}
9.3.12. PlaceOrderBean: un stateful bean
En el código anterior, cada llamada a addBid desde el servlet termina en la creación de
una nueva oferta (Bid). En ningún momento el cliente se preocupa por el estado interno
del bean, simplemente porque sabe que el estado de los atributos internos del bean
nunca va a ser conservado (ni le interesa). El cliente ve como si cada llamada a un
método del bean de sesión fuera ejecutado por una instancia distinta. Por eso, los
Stateless Beans son utilizados para completar una acción en una única llamada.
Pero a veces necesitamos guardar ciertos datos, a veces necesitamos mantener una
sesión. La aplicación de ActionBazaar usa un Stateful Session Bean para ejecutar el
proceso de realizar el pedido, a través del bean PlaceOrderBean.
El proceso de realizar una orden o pedido es un proceso demasiado complejo para
ejecutarlo en un solo paso. Hay todo un workflow involucrado que abarca desde agregar
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 232
items a una orden hasta confirmar la misma orden, que se ve representado en el
siguiente esquema:
Figura 9.27: Proceso de realizar Pedidos
Se necesita interacción con el usuario en cada uno de los pasos. Se necesita mantener
abierta una sesión con datos temporarios que se conserven de una invocación a otra
mientras dure el proceso. Con un Stateful Bean, los datos que el usuario ingresa en cada
paso pueden mantenerse temporariamente en el bean hasta completar el workflow de
pedido.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 233
Cada uno de los pasos representados en el dibujo será implementado como un método
de PlaceOrderBean, que serán invocados secuencialmente desde el cliente.
Definimos la interface remota PlaceOrder:
@Remote // Defines remote business interface
public interface PlaceOrder {
void setBidderId(Long bidderId);
void addItem(Long itemId);
void setShippingInfo(ShippingInfo shippingInfo);
void setBillingInfo(BillingInfo billingInfo);
Long confirmOrder();
}
Luego, implementamos la interface y anotamos la implementación como un bean de
sesión stateful:
@Stateful // Marks POJO as statefull
public class PlaceOrderBean implements PlaceOrder {
// This four attributes
// defines stateful instance variables
private Long bidderID;
private List items;
private ShippingInfo shippingInfo;
private BillingInfo billingInfo;
public PlaceOrderBean () {
items = new ArrayList();
}
public void setBidderID(Long bidderId) {
this.bidderId = bidderId;
}
public void addItem(Long itemId) {
items.add(itemId);
}
public void setShippingInfo(ShippingInfo shippingInfo) {
this.shippingInfo = shippingInfo;
}
public void setBillingInfo(BillingInfo billingInfo) {
this.billingInfo = billingInfo;
}
@Remove // Contains remove method
public Long confirmOrder() {
Order order = new Order();
order.setBidderId(bidderId);
order.setItems(items);
order.setShippingInfo(shippingInfo);
order.setBillingInfo(billingInfo);
saveOrder(order);
billOrder(order);
return order.getOrderId();
}
...
}
Como estuvimos viendo hasta ahora, el bean no es más que un POJO con la anotación
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 234
de @Stateful al comienzo. Es interesante notar que todos los atributos definidos al
comienzo son los que el usuario irá seteando a lo largo de la sesión hasta llegar al
último método, y el más importante, que es el que crea una orden, la persiste y la
confirma.
La anotación @Remove marca el final del workflow modelado por el stateful bean. Es
una forma de indicarle al contenedor de EJBs que tras ejecutar este método ya no
necesita mantener la sesión del bean. Es un error muy grave no utilizar esta anotación en
un stateful bean, ya que si nos la olvidamos, el contenedor quedará manteniendo el
estado de las variables y la instancia del bean hasta que la sesión expire por medio de un
timeout, lo que nos lleva a un desperdicio de preciosos recursos del servidor y una
ralentización bastante seria de la aplicación.
El código del cliente no vale la pena incluirlo (recuerden que pueden ver el código
completo descargándolo de la página del libro), ya que la DI se hace de la misma forma
que ya estuvimos viendo y, salvo la invocación de los demás métodos que pertenecen al
workflow, que no son más que simples invocaciones, no hay nada interesante en él. Lo
verdaderamente interesante es que el código del cliente de un Stateful Bean y un
Stateless Bean o de un bean local y un bean remoto es exactamente igual! Al cliente
le da igual si el bean es remoto o si es local, ya que EJB 3 encapsula todo el manejo de
RMI.
9.3.13. OrderBillingMDB: Un Message-Driven Bean
Así como un bean de sesión procesa request de negocio, directos del cliente, los MDBs
procesan mensajes indirectos. En los sistemas enterprise, la mensajería tiene numerosos
usos, por ejemplo:
Integración de sistemas
Procesamiento asincrónico
Comunicación entre sistemas distribuidos
Para implementar una mensajería asincrónica, es necesario utilizar un intermediario
entre el emisor del mensaje y el receptor. En JavaEE ese mediador se llama message-
oriented middleware (MOM). Ejemplos comerciales de MOM en el mercado son:
MQSeries de IBM o SonicMQ de Progress Software. EJB 3.0 estandariza esta capa
intermedia de mensajería mediante el uso de los MDBs, que de alguna forma, sirven
para encapsular el aburrido código de la API de Java Messaging Service (JMS).
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 235
Figura 9.28: Message-Driven Bean
El libro muestra la diferencia entre un código que usa directamente JMS y otro que usa
un MDB, mediante un código que deja al descubierto la diferencia de cantidad, claridad
y facilidad entre uno y otro (sale ganando el segundo, por supuesto). No es un tema que
interese tratar por el momento. El tema de mensajería en JavaEE es tan complejo que,
en todo caso, merece una explicación por separado. Al que le interese ver la
implementación de un MDB, puede buscar en el código el bean OrderBillingMDB que
implementa la interfaz MessageListener, para poder hacer uso de JMS a través del
framework de EJB y además para poder implementar el método onMessage, que es
donde se arma el mensaje propiamente dicho y se le adjuntan los objetos que se desean
enviar. Además se usa la anotación @MessageDriven como anotador de la clase, que ya
se imaginarán para qué sirve.
9.3.14. Persistiendo las Entidades Bid y Order a través de JPA
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 236
Figura 9.29: Persistiendo un BidObject
Gracias a Dios, en EJB 3, JPA no implementa el modelo de contenedores (como sí lo
hacía en las versiones anteriores), sino que utiliza un paradigma de API, similar a
JDBC, JavaMail o JMS. La interface EntityManager define la API de persistencia
mientras que las entidades JPA especifican cómo se debe realizar el mapeo entre los
datos de la aplicación y los registros de las tablas relacionales.
Veamos por ejemplo cómo sería la entidad Bid con las anotaciones correspondientes a
JPA:
@Entity // Marks POJO as entity
@Table(name="BIDS") // Specifies table mapping
public class Bid implements Serializable {
private Long bidID;
private Long itemID;
private Long bidderID;
private Double bidAmount;
private Date bidDate;
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 237
@Id // Containes entity ID
@GeneratedValue(strategy=GenerationType.AUTO)
// Specifies column mappings
@Column(name="BID_ID")
public Long getBidID() {
return bidID;
}
public void setBidID(Long bidID) {
this.bidID = bidID;
}
@Column(name="ITEM_ID")
public Long getItemID() {
return itemID;
}
public void setItemID(Long itemID) {
this.itemID = itemID;
}
@Column(name="BIDDER_ID")
public Long getBidderID() {
return bidderID;
}
public void setBidderID(Long bidderID) {
this.bidderID = bidderID;
}
@Column(name="BID_AMOUNT")
public Double getBidAmount() {
return bidAmount;
}
public void setBidAmount(Double bidAmount) {
this.bidAmount = bidAmount;
}
@Column(name="BID_DATE")
public Date getBidDate() {
return bidDate;
}
public void setBidDate(Date bidDate) {
this.bidDate = bidDate;
}
}
Es notable el poder de esta Entity. Es notable que Bid no es más que un POJO común y
corriente, que no requiere ninguna interface, ni requiere heredar de ninguna clase rara.
La anotación @Table sirve para mapear la clase a la tabla BIDS de la base de datos;
@Column para mapear atributos a campos. El código es en verdad muy sencillo, y JPA
no es para nada intrusivo.
Cuando mostré el código de los beans, al principio del ejemplo, obvié deliberadamente
el método save. Recordemos que, por ejemplo, el addBid de PlaceBidBean invocaba a
save para persistir la Bid recibida por parámetro. Veamos ahora esa parte de código:
@Stateless
public class PlaceBidBean implements PlaceBid {
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 238
// Injects instance of EntityManager
@PersistenceContext(unitName="actionBazaar")
private EntityManager entityManager;
...
private Bid save(Bid bid) {
// Persists entity instance
entityManager.persist(bid);
return bid;
}
}
La persistencia se realiza a través del EntityManager que es inyectado por el contenedor
de EJBs. El EntityManager puede ser visto como un "intérprete" entre el mundo de la
orientación a objetos y el mundo de tablas relacionales. El EntityManager lee las
anotaciones de la entidad que vimos unas líneas más arriba y, una vez que entiende
cómo debe guardar el objeto en la base, cómo debe mapear el objeto en un registro de
una tabla, lo hace. El EntityManager es inyectado en el bean PlaceBid a través de la
anotación @PersistenceContext. Una unidad de persistencia es un grupo de entidades
empaquetadas juntas en un módulo de aplicación. El atributo unitName de la anotación
hace referencia a esa unidad de persistencia.
Cuando el EntityManager persiste una entidad, en realidad lo que está haciendo es
generar SQL dinámico, SQL on the fly, el SQL que es capaz de leer el DBMS de la base
de datos que fue configurada en el ORM. La llamada:
entityManager.persist(bid);
Podría generar un código SQL de este estilo:
INSERT INTO BIDS (BID_ID, BID_DATE, BIDDER_ID, BID_AMOUNT, ITEM_ID)
VALUES (52, NULL, 60, 20000.50, 100)
Dependiendo de los valores de los atributos del objeto enviado por parámetro.
9.3.15. Conclusión
EJB 3 es una especificación abierta de Sun Microsystem. Para utilizar EJBs
necesitaremos un contenedor de EJB que implemente la especificación como Glassfish
del mismo Sun o JBoss de Red Hat. El uso de EJBs en una aplicación enterprise nos
abstrae de muchos crosscutting concerns como pueden ser integración, pooling,
mensajería, transacciones, seguridad, dependencias, etc.
La especificación 3 de EJB presenta grandes ventajas frente a la 2, como el uso de
anotaciones, en lugar de descriptores XML verbosos (que pueden seguir utilizándose y,
de hecho, cuando no es posible volver a tocar un código, siguen siendo indispensables),
un modelo de programación más liviano y menos intrusivo, una especificación de
persistencia mucho más flexible (basada en los ORM que ya existían en el mercado) y
el uso de inyección de dependencia en lugar del uso directo de JNDI lookup.
EJB 3 In Action es un muy buen libro, claro y completo, que es una referencia obligada
para aquel que trabaje a diario con EJB 3.
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 239
9.4. Información consultada
9.4.1. Tecnología
"http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html" - Best Practices for
Exception Handling – O’Reilly Media
"http://www.odi.ch/prog/design/datetime.php" - Date and time in Java
"http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html" - Enums
"http://commons.apache.org/lang/api-
2.3/org/apache/commons/lang/time/DateUtils.html" - DateUtils (Lang 2.3 API)
"http://neuroph.sourceforge.net/" - Java Neural Network Framework Neuroph
"http://www.dosideas.com/base-de-datos/712-no-se-recomienda-borrar-datos.html" -
No se recomienda borrar datos
"http://docs.jboss.org/hibernate/stable/core/reference/en/html/queryhql.html" -
Chapter 14. HQL: The Hibernate Query Language
"http://www.dosideas.com/java/414-transacciones-con-spring-framework-y-ejb-
30.html" - Transacciones con Spring Framework y EJB 3.0
"http://java.sun.com/developer/technicalArticles/ALT/Reflection/" - Using Java
Reflection
"http://javabeans.asia/2008/06/09/drools_stop_executing_current_agenda_group_and_al
l_rules.html" - Drools - Stop executing current agenda group and all rules - Java Beans
dot Asia
"http://www.developer.com/java/ent/print.php/10933_3821101_2" - Rev Up the Drools
5 Java Rule Engine — Developer.com
"http://www.developer.com/java/ent/print.php/10933_3821101_1" - Rev Up the Drools
5 Java Rule Engine — Developer.com
"http://www.fondosdepantalla.biz/wallpaper/Mapa-del-Mundo/" - Mapa del Mundo :
Fondos de pantalla, Imagenes, Wallpapers
"http://lists.jboss.org/pipermail/rules-users/2009-May/008906.html" - [rules-users]
Debugging Drools when/then using breakpoints
"http://legacy.drools.codehaus.org/Working+Memory#WorkingMemory-fireAllRules" -
Drools - Working Memory
"http://www.webservicex.net/CurrencyConvertor.asmx" - CurrencyConvertor Web
Service
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 240
"http://maven.apache.org/general.html#encoding-warning" - Maven - Frequently Asked
Technical Questions
"http://es.wikipedia.org/wiki/ISO-8859-1" - ISO 8859-1 - Wikipedia, la enciclopedia
libre
"http://es.wikipedia.org/wiki/Unicode" - Unicode - Wikipedia, la enciclopedia libre
"http://es.wikipedia.org/wiki/UTF-8" - UTF-8 - Wikipedia, la enciclopedia libre
"http://en.wikipedia.org/wiki/ISO/IEC_8859-1" - ISO/IEC 8859-1 - Wikipedia, the free
encyclopedia
"http://www.w3schools.com/tags/ref_entities.asp" - HTML ISO-8859-1 Reference
"http://www.jboss.org/file-
access/default/members/jbossrichfaces/freezone/docs/development/userguide/en/html/ri
ch_calendar.html" - 6.28. < rich:calendar >
"http://fmpp.sourceforge.net/datetimepattern.html" - FMPP - Date and Time Patterns
"http://docs.jboss.org/jbpm/v3.2/userguide/html_single/" - JBoss jBPM - Workflow in
Java
"http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsbpel" - OASIS
Web Services Business Process Execution Language (WSBPEL) TC
"http://eclipse.org/bpel/" - BPEL Project home
"http://jboss.org/jbossjbpm/bpel/" - jboss.org: community driven
"https://jira.jboss.org/jira/browse/EJBTHREE-1926" - [#EJBTHREE-1926] EJBTimer
Restart Issue : Dropped/Failed Timer Execution - JBoss Issue Tracker
"http://www.xmission.com/~goodhill/dates/deltaDates.html" - java.util.Date Difference
In Days
"http://office.microsoft.com/es-es/help/HP815503843082.aspx" - Forma Línea de vida
de objeto - Ayuda y procedimientos - Microsoft Office Online
"http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Version_4_.28random.29"
- Universally Unique Identifier - Wikipedia, the free encyclopedia
"http://maven.apache.org/plugins/maven-war-plugin/inplace-mojo.html" - Maven WAR
Plugin - war:inplace
"http://livedemo.exadel.com/richfaces-demo/richfaces/gmap.jsf?c=gmap" - RichFaces -
Open Source Rich JSF Components - Google Map Component
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 241
9.4.2. Negocio
9.4.2.1. General
"http://www.fly.faa.gov/flyfaa/usmap.jsp" - Flight Delay Information - Air Traffic
Control System Command Center
"http://flightaware.com/" - FlightAware - Free Flight Tracker / IFR Flight Status / Flight
Tracking / Flight Planning
"http://www.turbus.com/commerce/inicio.jsp#" - TurBus. Venta de pasajes a todo Chile
- Buses interurbanos - la principal compañía de transportes de pasajeros en Chile
"http://priclub.directferries.com/ferry/terms.aspx?stdc=DF10S" - Direct Ferries - Haga
reservas para ferries a Inglaterra, Portsmouth y Plymouth.
"http://answers.google.com/answers/threadview?id=48121" - Google Answers: What is
the amount of fuel used in
"http://www.aduanaargentina.com/ac.php" - Contenedores aéreos
"http://es.wikipedia.org/wiki/Plan_de_vuelo" - Plan de vuelo - Wikipedia, la
enciclopedia libre
"http://www.colaero.com/logbook_form.php" - Colaero Logbook
"http://www.amadeus.com/airlineIT/index.html" - Airline IT solutions
"http://www.amadeus.com/airlines/airlines.html" - Amadeus Airlines
9.4.2.2. Empleados
"http://es.wikipedia.org/wiki/Tripulaci%C3%B3n_(barcos)" - Tripulación (barcos) -
Wikipedia, la enciclopedia libre
"http://en.wikipedia.org/wiki/First_officer" - First officer - Wikipedia, the free
encyclopedia
"http://en.wikipedia.org/wiki/Flight_attendant" - Flight attendant - Wikipedia, the free
encyclopedia
"http://en.wikipedia.org/wiki/Deadheading_(aviation)" - Deadheading (aviation) -
Wikipedia, the free encyclopedia
"http://en.wikipedia.org/wiki/Flight_engineer" - Flight engineer - Wikipedia, the free
encyclopedia
"http://es.answers.yahoo.com/question/index?qid=20080114203149AAsAMUT" -
¿cuánto gana una azafata de aviones en Argentina? - Yahoo! Respuestas
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 242
"http://espanol.answers.yahoo.com/question/index?qid=20070331120042AA5pIgL" -
Cuanto gana un piloto de aerolinea comercial( austral, aerolineas, etc) en la Argentina? -
Yahoo! Respuestas
"http://ar.answers.yahoo.com/question/index?qid=20090707183819AAXAvrJ" - En
Argentina, los pilotos de avion ganan bien? Cuanto ganan? Depende de las aerolineas? -
Yahoo! Argentina Respuestas Respuestas
"http://www.todoexpertos.com/categorias/ciencias-e-ingenieria/ingenieria-
aeronautica/respuestas/2083495/sueldo-de-un-tecnico-de-mantenimiento" - Ingeniería
Aeronáutica - Sueldo de un técnico de mantenimiento?
"http://es.wikipedia.org/wiki/Piloto" - Piloto - Wikipedia, la enciclopedia libre
9.4.2.3. Licencias
"http://dcaa.slv.dk:8000/icaodocs/Annex%201%20-%20Personnel%20Licensing/" –
ICAO Personnel Licensing
"http://www.icao.int/icao/en/trivia/peltrgFAQ.htm#1" - ICAO | FLS | FAQs
"http://en.wikipedia.org/wiki/Pilot_licensing_and_certification" - Pilot licensing and
certification - Wikipedia, the free encyclopedia
"http://en.wikipedia.org/wiki/Private_Pilot_License" - Private Pilot License -
Wikipedia, the free encyclopedia
"http://en.wikipedia.org/wiki/Airline_Transport_Pilot_License" - Airline Transport Pilot
License - Wikipedia, the free encyclopedia
"http://en.wikipedia.org/wiki/Commercial_Pilot_Licence" - Commercial Pilot Licence -
Wikipedia, the free enciclopedia
9.4.2.4. Clientes
"http://en.wikipedia.org/wiki/Machine-readable_passport" - Machine-readable passport
- Wikipedia, the free encyclopedia
"http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3" - ISO 3166-1 alpha-3 - Wikipedia,
the free encyclopedia
"http://en.wikipedia.org/wiki/Social_Security_number" - Social Security number -
Wikipedia, the free encyclopedia
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 243
9.4.2.5. Viajes
"http://rfinder.asalink.net/" - RouteFinder - Flight planning tools for PC flight
simulation
"http://www.andesmar.com/shop/View.asp?choice=1&itemid=128&lang=es" -
Andesmar Argentina > Pasajes de bus, Pasajes de Colectivo, Pasajes de Micro
"http://www.staralliance.com/es/travellers/index.html" - Viajeros - Star Alliance
"http://www.plataforma10.com/" - Plataforma 10
"http://en.wikipedia.org/wiki/Record_locator" - Record locator - Wikipedia, the free
encyclopedia
"http://www.aa.com/aa/pubcontent/es/ofertasDeViaje/condiciones/condicionesQX7AR3
.jsp" - Términos y Condiciones De La Tarifa
"https://www.aacargo.com/shipping/fuelsurcharge.jhtml" - American Airlines Cargo -
International Air Cargo Services - Fuel Surcharge Details
"http://www.aa.com/aa/i18nForward.do?p=/businessPrograms/cargo.jsp" - American
Airlines - Servicio de Carga Aérea
"https://www.aa.com/aa/i18nForward.do?p=/utility/FAQs/reservations_FAQ.jsp" -
Preguntas Frecuentes - Reservaciones
"https://www.aa.com/aa/i18nForward.do?p=/utility/FAQs/travelInformation_FAQ.jsp#
Check-In Information" - Travel Information FAQs
"http://www.aerofertas.com.ar/TKT_Descripcion.htm" - www.Aerofertas.com.ar - EL
PASAJE AEREO -
"http://www.aa.com/aa/pubcontent/es/utility/FAQs/reservations_FAQ.jsp#s10q9" -
Preguntas Frecuentes - Reservaciones
"http://www.aa.com/aa/viewPromotionDetails.do?itemDescriptor=PromotionContent&f
ileName=news_CargosEquipajeRegistrado.xml&type=HomePagePromotion&anchorLo
cation=MCLA_Home_Page&url=news_CargosEquipajeRegistrado.xml&_locale=es_A
R&repositoryName=PromotionContentRepository&repositoryId=16122588&reportedT
itle=Cambios+importantes+en+los+cargos+al+equipaje&reportedPos=1" - American
Airlines - Cambios en los cargos al equipaje registrado
"http://www.speedbirdclub.com/es/all-news/commercial-policies/condicarr/Winchang/"
- British Airways’ Speedbird Club: Política Comercial - Cambios de Programación
Invierno 2008
"http://www.speedbirdclub.com/es/all-news/commercial-
policies/condicarr/summerchange/" - British Airways’ Speedbird Club: Politica
Comercial - Cambio en la programación de vuelos para el verano 09
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 244
"http://www.unitedespanol.com/core/espanol/SI/commitment/disclosure.html" - United
Airlines - 10.Divulgar nuestras políticas de cancelación, reglas del programa de viajeros
frecuentes, configuración de nuestros aviones y actualizaciones en los itinerarios
"http://www.unitedespanol.com/core/espanol/SI/commitment/delays.html" - United
Airlines - 2. Mantener a nuestros clientes al tanto de demoras, cancelaciones y
operaciones irregulares
"http://nacc.upc.es/tierra/node16.html#SECTION00733100000000000000" - Distancia
a lo largo de un círculo máximo
"http://www.aa.com/pubcontent/es/utility/FAQs/reservations_FAQ.jsp#s10q9" -
Preguntas Frecuentes - Reservaciones
"http://es.wikipedia.org/wiki/Cuaderno_de_bit%C3%A1cora" - Cuaderno de bitácora -
Wikipedia, la enciclopedia libre
"http://es.wikipedia.org/wiki/Diario_de_navegaci%C3%B3n" - Diario de navegación -
Wikipedia, la enciclopedia libre
"http://skyvector.com/" - Flight Planning and Aeronautical Charts at SkyVector.com
"http://www.azworldairports.com/airports/a2740jfk.cfm" - A-Z World Airports Online -
Country Index - United States airports - New York - John F Kennedy International
Airport (JFK/KJFK)
"http://www.azworldairports.com/airports/a1210gig.cfm" - A-Z World Airports Online
- Country Index - Brazil airports - Rio de Janeiro-Galeão - Antonio Carlos Jobim
International Airport (GIG/SBGL)
"http://es.wikipedia.org/wiki/Check-in" - Check-in - Wikipedia, la enciclopedia libre
"http://es.wikipedia.org/wiki/Tarjeta_de_embarque" - Tarjeta de embarque - Wikipedia,
la enciclopedia libre
"http://en.wikipedia.org/wiki/Boarding_pass" - Boarding pass - Wikipedia, the free
encyclopedia
"https://www.aa.com/reservation/flightCheckInViewReservationsAccess.do?anchorEve
nt=false" - Airline Flight Check-In And Flight Check In From American Airlines |
AA.com
"https://www.aa.com/reservation/oneWaySearchAccess.do?anchorEvent=false" - One-
Way Airline Tickets | One-Way Flights | One-Way Airfare | AA.com
"http://en.wikipedia.org/wiki/Airline_ticket" - Airline ticket - Wikipedia, the free
encyclopedia
"http://es.wikipedia.org/wiki/Equipaje" - Equipaje - Wikipedia, la enciclopedia libre
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 245
"http://www.frequentflier.com/" - FrequentFlier.com - Helping frequent flyers earn
more miles and travel awards through frequent flyer program participation
"http://www.alitalia.com/AR_ES/footer/faq/millemiglia/notcreditedmiles.htm" - Alitalia
- FAQ - Programa MilleMiglia
9.4.2.6. Unidades
"http://www.airliners.net/aircraft-data/" - Aircraft & Aircraft Carrier Data | Airliners.net
"http://www.viarural.com.uy/agroindustria/camiones/volvo/omnibus-volvo-b10m.htm"
- CAMIONES - OMNIBUS VOLVO B10M EDC
"http://www.rkviajes.com/buquebus/flota.html" - BUQUEBUS - Flota de Barcos R & K
Viajes Internacionales
"http://www.renfe.es/fichastrenes/index.html" - Renfe Fichas de Trenes
"http://ccapilot.blogspot.com/2008/01/tip-02-cuanto-combustible.html" - Flying Tips:
TIP 02: Cuanto Combustible?
"http://www.howstuffworks.com/question192.htm" – HowStuffWorks ―How much fuel
does an international plane use for a trip?‖
"http://www.boeing.com/commercial/747family/pf/pf_facts.html" - Boeing:
Commercial Airplanes - 747 Fun Facts
"http://www.boeing.com/commercial/747family/pf/pf_400_prod.html" - Boeing:
Commercial Airplanes -- 747 -- 747-400 Technical Characteristics
"http://en.wikipedia.org/wiki/Tare_weight" - Tare weight - Wikipedia, the free
encyclopedia
"http://www.iata.org/whatwedo/economics/fuel_monitor/index.htm" - Jet Fuel Price
Monitor
"http://en.wikipedia.org/wiki/Jet_fuel" - Jet fuel - Wikipedia, the free encyclopedia
"http://en.wikipedia.org/wiki/Aviation_fuel" - Aviation fuel - Wikipedia, the free
encyclopedia
"http://www.taringa.net/posts/info/1838347/Airbus-A380-vs-Boeing-747_400.html" -
Taringa! - Airbus A380 vs Boeing 747/400
"http://www.risingup.com/planespecs/" - Aircraft Performance Database
"http://science.howstuffworks.com/a3803.htm" - HowStuffWorks ―Boeing 747 vs.
A380‖
SISTRANS – Trabajo Profesional
Pablo Linares y Adrián Paredes Página 246
"http://www.boeing.com/commercial/airports/747.htm" - Boeing: Commercial
Airplanes - Commercial Aviation Services - Flight Operations - Airport Technology -
747 Airplane Characteristics for Airport Planning
"http://www.boeing.com/commercial/airports/737.htm" - Boeing: Commercial
Airplanes - Commercial Aviation Services - Flight Operations Support - Airport
Technology - 737 Airplane Characteristics for Airport Planning
"http://www.b737.org.uk/aircraftsystems.htm" - Illustrated Technical Information
Covering Vol 2
"http://www.airfleets.net/home/" - Airfleets Airline Fleet, plane, airport, photos : Boeing
Airbus Embraer Atr Fokker Dash
"http://www.airliners.net/photo/Singapore-Airlines-(Airbus/Airbus-A380-
841/0958946/L/" - Photos: Airbus A380-841 Aircraft Pictures | Airliners.net
"http://www.boeing.com/commercial/airports/faq.html" - Boeing: Commercial
Airplanes -- Commercial Aviation Services -- Flight Operations Support -- Frequently
Asked Questions (FAQs)
"http://www.howstuffworks.com/question192.htm#" - HowStuffWorks ―How much fuel
does an international plane use for a trip‖
"http://www.airliners.net/aircraft-data/stats.main?id=29" - Airbus A380 | Airliners.net