Qué es la Arquitectura

Para intentar apartarnos de una discusión eterna, podemos estar de acuerdo con esta definición:

La arquitectura de software de un sistema es el grupo de estructuras necesarias para razonar sobre el sistema, que abarca elementos de software, relaciones entre los mismos y las propiedades de ambos. (Bas13; p. 4)

Para más información sobre qué es arquitectura, ver [ISO/IEC/IEEE 42010:2011, Systems and software engineering — Architecture description][1], [Who needs an architect][2], [Software Architecture in Practice, by Bass, Clements, Kazman][3], [Enterprise Application Architecture, by Fowler et al][4].

Arquitectura Evolutiva

En el mundo actual, no podemos encajonar nuestra arquitectura a “eso que es difícil de cambiar”. Especialmente en los proyectos actuales inspirados por la metodología Agile, los requerimientos (funcionales y no-funcionales) y los atributos de calidad cambian rápidamente. Y deberían cambiar más rápido que en los proyectos tipo Waterfall.

Una solución para estas restricciones es usar arquitecturas evolutivas.

Una arquitectura evolutiva consiste de tres aspectos principales: cambio incremental, fitness functions, acoplamiento apropiado (For17, ch 1). Contiene dos características críticas: cambio incremental y cambio guiado a través de múltiples dimensiones (For17, ch 1). .

Dimensiones Arquitectónicas múltiples

  • Técnica
  • Información
  • Seguridad
  • Operacional/Sistema

Atributos de Calidad o “-ilidades”

En ingeniería de sistemas, los atributos de calidad son requerimientos no-funcionales realizados para evaluar el rendimiento de un sistema. Se llaman “-ilidades” (-ilities) debido al sufijo que la mayoría de estos términos comparten. Son normalmente Requisitos Arquitectónicamente Significantes (Architecturally Significant Requirements) que requieren de la atención de los arquitectos “List of system quality attributes”, de https://en.wikipedia.org/wiki/List_of_system_quality_attributes

-ilidades son otra forma de llamar los atributos de calidad

En For13, se menciona la lista de “-ilidades”, y añaden una nueva: “evolucionabilidad”. Este atributo de calidad está ya presente en los sistemas genéticos:

Evolucionabilidad se define como la capacidad de un sistema de evolución adaptativa. Evolucionabilidad es la habilidad de una población de organismos de no solamente generar diversidad genética, sino generar diversidad genética adaptativa, y así evolucionar a través de la selección natural.
“Evolucionabilidad”, de https://es.wikipedia.org/wiki/Evolucionabilidad

En un sentido literal, si los sistemas se crean en la mente de los desarrolladores 1, la evolución debería ocurrir a partir del segundo (y posteriores) sistema que diseñen. Esto está relacionado con el “Sindrome del Segundo Sistema” explicado en Bro95, ensayo “The second-system effect” 2. Más información [aquí][5]

Este no es el significado de “evolucionabilidad” referenciado. En Arquitectura Evolutiva, evolucionabilidad es una “[…] meta-característica, una envoltura arquitectónica que protege las demás características arquitectónicas” (de For13, ch 1). Es similar a la “calidad” variable derivada en [Iron Triangle / Project Management Triangle][6]. En este caso no está meramente derivada, pero también guía las decisiones en otros atributos de calidad.

Cambio Incremental

El Cambio Incremental se refiere a los equipos que construyen software de forma incremental, y su deployment. Esto es parte de Application Lifecycle Management (ALM). Lo primero se puede cubrir mediante prácticas de Extreme Programming (XP), y lo segundo mediante prácticas de Continuous Delivery (CD).

En un entorno Agile, posponemos las decisiones difíciles hasta el último momento. Esto permite una máxima acumulación de conocimiento. Producimos pequeños incrementos en propiedades de producto, que recolectarán feedback de los usuarios lo más temprano posible. Optimizamos el sistema para mantener un coste de cambio reducido. Utilizando un sistema que es fácil de cambiar no es solo un lujo, sino que nos permite movernos rápidamente.

En el entorno startup actual3, se necesita el cambio incremental más que nunca, ya que nos permite realizar cambios de forma rápida y segura. En compañías de tamaño medio, el cambio incremental permite entregar los mismos cambios de forma más veloz. Y en organizaciones grandes, el cambio incremental permite realizar cosas que no eran ni planteables antes.

Fitness Functions

Si nuestra arquitectura debe lidiar con los cambios, entonces estamos intentando refactorizar la arquitectura para que se adapte a nuevos requerimientos. Se sabe que la refactorización requiere tests. Estos tests para los atributos de calidad se conocen como fitness functions.

Quizás la más famosa sea la unit test suite: comprueba la adherencia a un comportamiento esperado.

Una definición:

Una fitness function arquitectónica proporciona una evaluación objetiva de integridad de algunas características arquitectónicas.
For13, ch 2

Una fitness function arquitectónica comprueba de forma objetiva un atributo de calidad arquitectónico. Ejemplo: unit test suite comprueba que el software coincida las expectativas de negocio en cuanto a características. Otro ejemplo: un test que compruebe que no existan dependencias circulares. Este test es atómico, automatizado, estático. Otro ejemplo: el build cycle time está por debajo del doble del build time medio. Este test es holístico, automatizado, estático.

Las fitness functions se pueden caracterizar a través de distintos ejes o categorías4:

  • Atómica vs Holística: “Las fitness functions Atómicas se ejecutan contra un contexto singular y ejercitan un aspecto particular de la arquitectura”. “Las fitness functions Holísticas se ejecutan contra un contexto compartido y ejercitan una combinación de aspectos arquitectónicos como seguridad y escalabilidad”. Ejemplo: la prueba unitaria comprueba el sistema de forma atómica. La prueba de humo en producción comprueba el sistema de forma holística.

  • Triggered vs Continuo: “Las Triggered fitness functions se ejecutan basadas en un evento particular, como puede ser un programador ejecutando una prueba unitaria, una deployment pipeline ejecutando pruebas unitarias o un QA realizando un testing exploratorio”. “Los tests continuos no se ejecutan de forma programada, y en su lugar ejecutan verificaciones constantes de aspectos arquitectónicos como la velocidad de transacción”. Ejemplo: unas pruebas unitarias se disparan en un nuevo commit. El site sigue activo en un test continuo, ejecutado cada x minutos/segundos.

  • Estático vs Dinámico: “Las fitness functions estáticas tienen un resultado fijado, como puede ser aprobado/fallado en un test unitario binario”. “Las fitness functions dinámicas confían en una definición cambiante basada en contexto extra”. Ejemplo: la unit test suite es estática. Contar el número de TODOs (to do comments) en la fuente es dinámico, donde marcas un máximo (actual) y disminuye la cuenta a medida que pasa el tiempo. No permites que nuevos TODOs entren en el código.

  • Automatizado vs Manual: “fitness functions en un entorno automatizado: integración continua, deployment pipelines, […]”. Ejemplo: la unit test suite debería estar automatizada. Comprobar la experiencia de usuario (UX) de una interfaz puede ser manual.

  • Intencional vs Emergente: Intencionales son “fitness functions al comienzo del proyecto mientras se dilucidan las características de la arquitectura”. Emergentes son “algunas fitness functions emergerán durante el desarrollo del sistema”.

  • Domain-specific: “Algunas arquitecturas tienen preocupaciones específicas, como seguridad especial o requerimientos regulatorios”. Ejemplo: no se ha logueado ninguna información de tarjeta de crédito en el sistema, para cumplir con las regulaciones y auditorías PCI.

  • Temporal: “construir un componente temporal para evaluar fitness”. Ejemplo: “ break upon upgrade test” (una fitness function que se ejecuta cuando las dependencias de un proyecto cambian). (todo esto está explicado en For13, ch 2)

Estas fitness functions tienen un ciclo de vida: 1. Detectadas / Introducidas 2. Revisadas 3. Retiradas / Obsoletas

Introduciendo una nueva fitness function: puede que el sistema ya soporte el requerimiento deseado, por lo tanto puede ser un mecanismo anti-regresión o documentación de que este requerimiento es importante para nosotros. En caso que el sistema no soporte la fitness function, el sistema aún no está listo. Este indicador puede servir como hito para el siguiente paso o como bloqueador para la siguiente entrega.

Recordar que estas fitness functions no solo se detectan por el equipo de producción, también las introducen. Muchas veces los stakeholders no pueden expresar los requerimientos de forma adecuada (tanto en formato problema como solución), por lo tanto es necesario que ayudemos a diagnosticar/proponer requerimientos, tanto desde un punto de vista técnico como de negocio.

Para revisar una función de negocio, reflexionar sobre si es aún aplicable. Debe satisfacer las dimensiones arquitectónicas. Si/cuando deja de satisfacer estas dimensiones, reflexionar sobre si la función es aún aplicable o se debería modificar.

Para volver obsoleta una fitness function, elimina todos los rastros de esta función de la documentación, código, procesos, etc… Asegúrate de que el requerimiento ya no existe o se ha visto satisfecho por otros métodos (otras funciones fitness). No es para nada trivial la forma en que las funciones se suplantan unas a otras (debido a los cuadrantes/ejes a los que pertenecen), así que se acostumbra a necesitar documentación.

En general, estas fitness functions nos dicen de forma objetiva si una solución satisface nuestros requerimientos. Se deben mantener como cualquier otro proceso/solución. Esto implica un coste, que se debe pagar.

Acoplamiento Apropiado

La arquitectura evolutiva defienden un acoplamiento apropiado entre componentes (lógicos/físicos/quanta5).

En el libro For13, se describen varios estilos arquitectónicos basados en su evolucionabilidad: de Big Ball of Mud, a Monolitos (ver más abajo), Arquitectura Orientada a Servicios y Arquitectura dirigida por eventos. Los monolitos se consideran un solo deployment que se puede dividir de múltiples formas:

  • Desestructurada: esencialmente, clases independientes coordinándose. Clases vagamente relacionadas. Lack of cohesion
  • Layered: cada capa representa una capacidad técnica.
  • Modular: cada módulo representa una funcionalidad de negocio con aislamiento bien definido entre módulos. Normalmente una API (no necesariamente REST)
  • Microkernel: una arquitectura plug-in.

Tu contexto es un factor decisivo a la hora de elegir como acoplar los módulos de tu arquitectura.

Dado que el ‘software es un proceso de aprendizaje’ (Brandolini),a medida que aprendas en tu dominio puede que necesites modificar la forma en que las piezas están acopladas.

¿Cuándo tiene sentido? – Conclusión

Las arquitecturas evolutivas tienen sentido cuando quieres añadir “evolucionabilidad” a tu software. Principalmente en la fase de Expansión del [3X Model][7].

No tiene tanto sentido añadir evolucionabilidad a tu software cuando estás intentando encontrar el encaje producto-mercado. O cuando ya tienes un negocio establecido y los requerimientos son más estables/cambian más lentamente. Sea cual sea el tamaño de tu negocio, apártate del Quick & Dirty para que tu software sea mantenible.

Las arquitecturas evolutivas sugieren hornear la evolucionabilidad en tu arquitectura. Recuerda las funciones fitness, el acoplamiento apropiado y el cambio incremental.

Referencias

Links

  • http://nealford.com/books/buildingevolutionaryarchitectures.html
  • http://evolutionaryarchitecture.com/

  1. Lo que significa que todos están involucrados en esto, incluyendo pero no únicamente los desarrolladores de software, arquitectos y stakeholders de negocio. 

  2. “El segundo sistema que un arquitecto diseña es el más peligroso de todos los que nunca hará, dado que tenderá a incorporar todos los agregados que él mismo generó pero no pudo agregar (debido a inherentes restricciones de tiempo) a su primer sistema. Por tanto, cuando se embarca en un segundo sistema, un ingeniero debería tener presente su natural tendencia a sobrecargarlo.” Fuente: https://es.wikipedia.org/wiki/El_M%C3%ADtico_Hombre-Mes#El_efecto_Segundo-Sistema 

  3. En el entorno startup, estas prácticas normalmente no se aplican, bajo la ilusión del quick & dirty. Muchos, de forma errónea, ponen el foco en las siguientes dos semanas de sprint. 

  4. El texto entre “comillas” se ha copiado de For13, capítulo 2 

  5. Quanta se describen como unidades de deployment.Plural. Singular es quantum.