lunes, 20 de mayo de 2013

Sobre Contenedores y Componentes

En estas últimas semanas me plantearon la duda de cuáles son los mejores diagramas para revelar la arquitectura de una aplicación.

Con esta interrogante llegué al libro Software Architecture for Developers, que propone la técnica de modelado de diagramas C4 (o las cuatro C: Contexto, Contenedores, Componentes y Clases).

Contexto, Contenedores, Componentes, Elementos


Simon Brown, autor del libro y también del blog Coding the Architecture, explica que todo sistema debe funcionar dentro de un contexto, donde tiene que interactuar con otros sistemas de IT, y esencialmente puede ser modelado como un conjunto de contenedores, o entornos de ejecución, en los cuales se ejecutan componentes de software. A partir de esta definición tan simple podemos llamar contenedores a piezas de software como contenedores de EJBs, Servlets, beans de Spring, entidades, beans CDI, etc; hasta incluso otras piezas no tan evidentes: máquinas virtuales, procesos de un sistema operativo, hilos o navegadores web. Todo dependerá de la granularidad que necesitemos expresar y de lo que se intente modelar.


Del párrafo anterior se desprende que los componentes son aquellas piezas de software que vivirán dentro de un contenedor. Habitualmente un contenedor maneja el ciclo de vida de sus componentes. En el caso de los EJBs, por ejemplo, o de los beans de Spring, el programador cliente del contenedor no tiene la responsabilidad de crear y/o destruir componentes; simplemente se los pide al contenedor cuando los necesita, o deja que el contenedor los inyecte dentro de otros componentes. Sin embargo, no todos los contenedores funcionan así. En el caso de una Java Virtual Machine, el programador cliente puede crear threads y ponerlos a funcionar. Otro caso mixto puede ser el de las entidades JPA, que a veces son creadas por el programador cliente y otras, cuando se recuperan de una base de datos, son creadas por el contenedor.

A su vez, un componente podría implementarse como una agregación de elementos. Por ejemplo: un EJB podría estar formado por dos interfaces (una local y una remota) y una clase Java. Según cómo esté modelando una arquitectura, podría conceptualizar un componente como algo más parecido a un módulo, y tener un componente llamado "Venta de Pasajes", por ejemplo, que sea una agregación de componentes EJBs, compuesto a su vez por varias interfaces y clases Java.

En el libro, Simon Brown no usa la palabra Elemento sino Clase, definiendo que un componente está compuesto por clases. Aquí prefiero ser más genérico, ya que podríamos tener elementos de cualquier tipo, no sólo clases de un lenguaje orientado a objetos; un componente podría tener archivos de configuración, páginas HTML, librerías, etc.

Considerando el cuarteto de contexto, contenedores, componentes y elementos, podremos modelar diagramas de distintos niveles de abstracción, empezando por el nivel más alto, el del contexto, donde veremos al sistema como una caja negra que interactúa con el mundo exterior, y sumergiéndonos dentro de ese sistema para observar los contenedores por los que está compuesto, los componentes que habitan dentro de esos contenedores, y por último, los elementos fundamentales con los que se construye cada componente.

Diagramas de Contexto


Este diagrama es muy parecido al viejo y querido diagrama de contexto de análisis estructurado. Me viene a la mente el nivel 0 de los Diagramas de Flujo de Datos (DFD) de Edward Yourdon, donde se dibujaba al sistema y su relación con las Entidades Externas. Con la diferencia de que esta vez las Entidades Externas pueden ser Usuarios o Sistemas, y las flechas pueden simbolizar cualquier cosa (no sólo flujo de datos como en DFD) siempre y cuando se las etiquete haciendo explícito su significado.

En Flickr se puede ver algunos ejemplos de diagramas de contexto creados por Simon Brown.

Por mi parte yo también he creado algunos diagramas. En mi caso he tomado como ejemplo un proyecto en el que he participado en el pasado de un Administrador de Órdenes de Trabajo.


En el diagrama podemos ver que este administrador es usado por tres tipos de usuarios: operadores que cargan horas en tareas, clientes que crean órdenes, y usuarios administradores que modifican datos, presupuestan órdenes, crean tareas, asignan operadores a tareas y siguen el porcentaje de avance de las mismas. Básicamente, el Administrador de Órdenes de Trabajo administra el ciclo de vida de las órdenes.

Preguntas que responde este tipo de diagramas:
  • ¿Qué es el sistema de software que estamos construyendo?
  • ¿Quién lo está usando?
  • ¿Cómo encaja en el ambiente de IT existente?
Los elementos que interactúan con el sistema pueden ser:
  • Usuarios
  • Sistemas Externos
¿Para qué sirven los diagramas de contexto entonces?
  • Hacen explícito el contexto, eliminando suposiciones.
  • Muestran a alto nivel qué se está agregando al ambiente de IT existente.
  • Son diagramas de alto nivel que personas técnicas y no-técnicas pueden usar como punto de partida para discusiones.
  • Proveen un punto de partida para identificar los actores con los que potencialmente se necesitará interactuar, así como los sistemas con los que tendremos que interfacear.
¿A qué tipo de audiencia van dirigidos estos diagramas?
  • Personas técnicas y no-técnicas, dentro y fuera del equipo de desarrollo del proyecto.

Diagramas de Contenedores


Zambullámosnos en el sistema. Veamos qué contenedores hay dentro.


En el caso del ejemplo usamos tecnología Oracle; Weblogic 10.3.6 para ser exactos. Tenemos un contenedor de ADF, uno de EJB 3.0, tenemos librerías, una base de datos, navegadores web (así que hablamos de una aplicación web; en la cajita de Web Browser se puede ver que se especifica la lista de navegadores soportados), y tenemos flechas en las que se definen los protocolos de comunicación entre contenedores.

En Flickr pueden ver ejemplos del autor.

Preguntas que responde este tipo de diagramas:
  • ¿Cuáles son las decisiones de tecnología de alto nivel?
  • ¿Cómo se comunican los contenedores entre sí?
  • Como desarrollador, ¿dónde necesito escribir código?
Los elementos que podemos encontrar en estos diagramas son:
  • Contenedores (ciudadanos de primera clase)
  • Se puede incluir algunos conceptos del contexto, como usuarios y sistemas externos, para enriquecer el diagrama (si se incluyen, es una buena idea remarcar explícitamente los límites del sistema, como en un diagrama de contexto)
Para cada contenedor, la información que podemos especificar es:
  • Nombre lógico (Ej: Base de Clientes, Navegador de Puesto de Trabajo, etc)
  • Tecnología elegida (Apache Tomcat 7, Oracle 11g)
  • Responsabilidades: una lista a muy alto nivel (para un contenedor de EJB, por ejemplo, su principal responsabilidad sería la de ejecutar la lógica de negocio; para un contenedor de Servlets, componer las páginas web)
Típicamente la comunicación inter-contenedor es comunicación inter-procesos. En el caso de mi ejemplo, entre el servidor de aplicaciones Weblogic y el navegador Web hay una comunicación remota entre dos máquinas distintas.

Simon Brown recomienda etiquetar las flechas, incluyendo información útil como:
  • El propósito de la interacción (Ej: leer/escribir datos desde, enviar reportes a)
  • Método de comunicación (Ej: Web Services, REST, RMI, JMS)
  • Estilo de comunicación (Ej: sincrónico, asincrónico, batched, 2PC)
  • Protocolos y números de puerto (Ej: HTTP, HTTPS, SOAP/HTTP, SMTP, FTP)
¿Para qué sirven los diagramas de contenedores entonces?
  • Hacen explícitas las decisiones de tecnología de alto nivel.
  • Muestran dónde hay relaciones entre contenedores y cómo se comunican.
  • Proveen un framework en el que ubicar componentes (todos los componentes deben tener un hogar).
  • Proveen el enlace, a menudo extraviado, entre los diagramas de contexto de muy alto nivel y lo que habitualmente deriva en un desordenado diagrama de componentes mostrando todos los componentes lógicos que constituyen el sistema.
¿A qué tipo de audiencia van dirigidos estos diagramas?
  • Personas técnicas, dentro y fuera del equipo de desarrollo del proyecto, incluyendo a gente de operaciones y soporte.

Diagramas de Componentes


Sigamos bajando de nivel. Aquí podríamos crear un diagrama para cada contenedor, o combinar vistas con varios diagramas. Va a depender mucho del sistema y de lo que se quiera destacar.

En mi ejemplo elegí tres contenedores:
  • El contenedor de ADF
  • El contenedor de EJB
  • La base de datos de Work Order
También marqué los límites del sistema y dibujé la Base Externa para que sea explícita la interacción que tiene con algunos componentes.


Notemos que cuanto más mezclamos la vista de contenedores con la vista de componentes, vamos a obtener un diagrama parecido a lo que podría ser un Diagrama de Despliegue de UML.

Otro contenedor que podría haber elegido para modelar es el de las librerías. A nivel de componentes aquí podríamos ver cada una de las librerías y las relaciones entre sí, con lo cual podríamos tener un interesante mapa de dependencias.

En el Flickr de Brown podemos encontrar más ejemplos.

Preguntas que responde este tipo de diagramas:
  • ¿Por qué componentes/servicios está formado el sistema?
  • ¿Es claro cómo funciona el sistema a alto nivel?
  • ¿Todos los componentes/servicios tienen hogar?
Los elementos que podemos encontrar en estos diagramas son:
  • Componentes (ciudadanos de primera clase)
  • Se puede incluir algunos conceptos de otros diagramas, como contenedores, usuarios o sistemas externos
Para cada componente, la información que podemos especificar es:
  • Nombre lógico (Ej: Importador, Calculador de Riesgo, etc)
  • Tecnología elegida (POJO, EJB, Windows Communication Foundation Service)
  • Responsabilidades: una lista a muy alto nivel (pueden ser las operaciones más importantes u oraciones breves)
¿Para qué sirven los diagramas de componentes entonces?
  • Muestran la descomposición del sistema a alto nivel en componentes/servicios con distintas responsabilidades.
  • Muestran dónde están las relaciones y dependencias entre componentes.
  • Proveen un framework para la estimación a alto nivel del desarrollo de software y la entrega puede ser desglosada.
¿A qué tipo de audiencia van dirigidos estos diagramas?
  • Personas técnicas dentro del equipo de desarrollo del proyecto.

Diagramas de Elementos


Aquí es donde nos sumergimos tanto en el sistema que casi llegamos al código. Un diagrama de elementos podría ser un diagrama de clases, por ejemplo, en el que podríamos agrupar las clases por componentes, los cúmulos de clases, las agregaciones, las relaciones.

Una herramienta común de ingeniería inversa podría ayudarnos con estos diagramas, ya que en principio no se necesita demasiada inteligencia para realizarlos. Es poca la información para filtrar.

Si tomara el contenedor de librerías, por ejemplo, pondría la lupa en una de las librerías y podría encontrarme con un diagrama de clases. Si la librería fuera el modelo de dominio, aquí entraría en juego el modelo de objetos de negocio, que en mi caso se trata de un modelo anémico pero que, en otro caso, podría contar con operaciones y lógica de negocio.

Algunos Tips para la Efectividad de los Diagramas C4


  • Títulos: Los títulos deberían ser cortos y significativos. Si los diagramas deben ser leídos en un orden específico asegúrese de numerarlos claramente.
  • Etiquetas: En lo posible evitar acrónimos (sino utilizar glosario), a excepción de decisiones tecnológicas como JMS, EJB, POJO, WCF, etc.
  • Formas: Si se usa distintas formas (por ejemplo: cilindros para las bases de datos), asegúrese de incluir una explicación de qué representa cada una.
  • Responsabilidades: Una manera simple de agregar una capa adicional de información a un diagrama de arquitectura. Deben mantenerse cortas y usar fuente pequeña.
  • Líneas: Asegúrese de ser consistente con los estilos de líneas (sólido, punteado, discontinua, etc) y con las flechas (¿apuntan en la dirección de dependencia o indican la dirección en la cual los datos fluyen normalmente?). ¡Hay que tener cuidado con las líneas que tienen flechas en ambos extremos!
  • Color: Los colores pueden ser usados para proveer diferenciación entre elementos del diagrama o para asegurar un énfasis particular en algunos de ellos. Provea referencia de qué están representando los colores.
  • Bordes: Agregar bordes (líneas dobles, coloreadas, punteadas, etc) alrededor de elementos del diagrama puede ser un modo genial de hacer énfasis o agrupar elementos relacionados. Etiquete los bordes. Haga explícito su significado.
  • Disposición: Notas adhesivas o fichas pueden ayudar con la flexibilidad, funcionando como sustitutos de cajas dibujadas en un pizarrón u hoja. Si usted está usando una técnica del estilo de Clase-Responsabilidad-Colaboración para identificar candidatos a clases/componentes/servicios. Puede utilizar las flechas resultantes para comenzar a crear sus diagramas de diseño.
  • Orientación: No hay una orientación correcta. Algunos estilos de arquitectura (como aplicaciones web de 3 capas) suelen dibujarse de arriba hacia abajo sólo por convención. Podemos prestarle atención a la orientación cuando queremos destacar algún componente o contenedor, ubicándolo en el centro, por ejemplo.
  • Claves o Referencias: Asegúrese de que todo el mundo puede entender los diagramas mediante referencias. Incluso las convenciones más obvias pueden ser malinterpretadas por personas con diferente background y experiencia. ¿Qué significan las Formas? ¿Qué significan las Líneas? ¿Qué significan los Colores? ¿Qué significan los Bordes? ¿Qué significan los Acrónimos?
  • Componentes Compartidos: Si usted va a implementar un componente compartido que será desplegado en un número de diferentes contenedores, asegúrese de que el diagrama refleja esto. Repita las veces que sea necesario el componente para incluirlo en cada contenedor que debe desplegarse y etiquételo como un componente compartido con una anotación, estereotipo o símbolo.
  • Los diagramas deben reflejar la realidad: ¿Es como realmente se va a codificar, se está codificando o se codificó?

Cuestiones Adicionales (a modo de conclusión)


Una vez concluido el post, hay una serie de interrogantes que se me plantean; algunas tan complejas que podrían ser tratadas en otros artículos:
  • ¿Qué otros diagramas de arquitectura podrían complementar a los C4? Claramente estos diagramas son vistas estáticas de un sistema. Pero, ¿son puros? ¿Podemos estar representando aspectos dinámicos en los significados de las flechas? ¿Son necesarias las vistas dinámicas para un estilo de arquitectura tan conocido como el modelo de 3 capas, o cliente-servidor, o SOA? Diagramas de Secuencia o de Colaboración entre contenedores y componentes podrían agregar información relevante. O quizá Diagramas de Estados para ciertos elementos o componentes. Aunque aquí entramos en la segunda interrogante que es...
  • ¿Dónde termina la Arquitectura y dónde empieza el Diseño? Simon Brown dice que la Arquitectura es el Gran Cuadro, es la estructura y la visión de un sistema. También dice que todas las decisiones son de diseño y cuando hablamos de decisiones importantes, decisiones que afectan al sistema completo, hablamos de Arquitectura de Software. Hay por ahí una definición bastante simple de Arquitectura que dice que la Arquitectura son todas aquellas decisiones que, una vez tomadas, son muy difíciles y caras de revertir. La elección de un Estilo de Arquitectura , por ejemplo, es prácticamente irreversible: cambiar de un modelo de 3 capas a un modelo SOA casi implicaría construir el sistema de nuevo. En particular a mí me gusta pensar en la metáfora del esqueleto; la Arquitectura es el esqueleto, son los cimientos, y el Diseño y el Código es la carne que rellena ese esqueleto. La elección de los paquetes de dominio, de un Patrón de Diseño, son decisiones de Diseño, a menudo sólo afectan a un módulo o a una capa de la Arquitectura. La elección de un contenedor, de un Patrón de Arquitectura, del mecanismo de comunicación entre componentes, claramente son decisiones de Arquitectura.
  • ¿Dónde encaja el modelo de datos? Los datos son una información que está ausente en los diagramas C4 que incluí en este post. Podemos intuir la dirección en que se mueven. Indagando acerca de los nombres de los componentes, podemos deducir qué entidades vamos a necesitar, qué campos van a viajar. Pero no tenemos ningún DER, ni ningún diagrama de clases. Aunque ya mencioné este punto, quiero volver a destacarlo a modo de conclusión: las clases y los datos a menudo podrán encontrarse dentro de los componentes. En el caso del Administrador de Órdenes, el contenedor de librerías tiene una librería que es el Modelo de Dominio. En el diagrama de contenedores pueden notar cómo este Modelo puede ser compartido por el contenedor de ADF y el contenedor de EJB. Y el modelo seguramente viaje en forma de sentencias SQL hacia las bases relacionales y como objetos serializados hacia los motores HTML y JavaScript de los navegadores. Cuánto más adentro de un componente nos encontremos, más metidos en el diseño estaremos, y también más cerca del código fuente.