Capítulo 1. ¿Qué ocurre cuandono hay "buenas prácticas"?

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

¿Por qué un tecnólogo, como un arquitecto de software, presenta una conferencia o escribe un libro? Porque han descubierto lo que coloquialmente se conoce como "buenas prácticas", un término tan manido que quienes lo pronuncian experimentan cada vez más reacciones en contra. Independientemente del término, los tecnólogos escriben libros cuando han descubierto una solución novedosa a un problema general y quieren difundirla a un público más amplio.

Pero, ¿qué ocurre con ese vasto conjunto de problemas que no tienen buenas soluciones? Existen clases enteras de problemas en la arquitectura del software que no tienen soluciones buenas en general, sino que presentan un conjunto desordenado de compensaciones contra otro conjunto (casi) igual de desordenado.

Los desarrolladores de software adquieren habilidades extraordinarias para buscar en Internet soluciones a un problema actual. Por ejemplo, si necesitan averiguar cómo configurar una herramienta concreta en su entorno, el uso experto de Google encuentra la respuesta.

Pero eso no es cierto para los arquitectos.

Para los arquitectos, muchos problemas presentan retos únicos porque combinan el entorno y las circunstancias exactas de su organización: ¿qué posibilidades hay de que alguien se haya encontrado exactamente con este escenario y lo haya publicado en un blog o en Stack Overflow?

Es posible que los arquitectos se hayan preguntado por qué existen tan pocos libros sobre arquitectura en comparación con temas técnicos como marcos de trabajo, API, etc. Los arquitectos rara vez experimentan problemas comunes, pero luchan constantemente con la toma de decisiones en situaciones novedosas. Para los arquitectos, cada problema es un copo de nieve. En muchos casos, el problema es novedoso no sólo dentro de una organización concreta, sino en todo el mundo. ¡No existen libros ni sesiones de conferencias para esos problemas!

Los arquitectos no deben buscar constantemente soluciones milagrosas a sus problemas; son tan raras ahora como en 1986, cuando Fred Brooks acuñó el término:

No hay un solo avance, ni en tecnología ni en técnica de gestión, que por sí solo prometa siquiera una mejora de un orden de magnitud [diez veces] en una década en productividad, en fiabilidad, en simplicidad.

Fred Brooks de "Sin bala de plata"

Dado que prácticamente todos los problemas presentan retos novedosos, el verdadero trabajo de un arquitecto reside en su capacidad para determinar y evaluar objetivamente el conjunto de compensaciones a ambos lados de una decisión trascendental para resolverla lo mejor posible. Los autores no hablan de "mejores soluciones" (ni en este libro ni en el mundo real) porque "mejor" implica que un arquitecto ha conseguido maximizar todos los posibles factores en competencia dentro del diseño. En su lugar, nuestro consejo irónico es el siguiente:

Consejo

No intentes encontrar el mejor diseño en arquitectura de software; en lugar de eso, esfuérzate por conseguir la combinación menos mala de compensaciones.

A menudo, el mejor diseño que puede crear un arquitecto es el conjunto menos malo de compensaciones: ninguna característica de la arquitectura destaca como lo haría por sí sola, sino que el equilibrio de todas las características de la arquitectura que compiten entre sí fomenta el éxito del proyecto.

Lo que nos lleva a preguntarnos "¿Cómo puede un arquitecto encontrar la combinación menos mala de compensaciones (y documentarlas eficazmente)?". Este libro trata principalmente sobre la toma de decisiones, permitiendo a los arquitectos tomar mejores decisiones cuando se enfrentan asituaciones novedosas.

¿Por qué "Las partes difíciles"?

¿Por qué hemos llamado a este libro Arquitectura de Software: Las Partes Duras? En realidad, el "duro" del título cumple una doble función. En primer lugar, duro connota difícil, y los arquitectos se enfrentan constantemente a problemas difíciles a los que, literalmente (y en sentido figurado), nadie se ha enfrentado antes, que implican numerosas decisiones tecnológicas con implicaciones a largo plazo superpuestas al entorno interpersonal y político en el que la decisión debe tener lugar.

En segundo lugar, lo duro connota solidez:al igual que en la separación entre hardware y software, lo duro debe cambiar mucho menos porque proporciona los cimientos de lo blando. Del mismo modo, los arquitectos hablan de la distinción entre arquitectura y diseño, donde la primera es estructural y la segunda se cambia más fácilmente. Así pues, en este libro hablamos de las partes fundacionales de la arquitectura.

La propia definición de arquitectura de software ha proporcionado muchas horas de conversación improductiva entre sus profesionales. Una definición irónica favorita es que "la arquitectura de software es lo que es difícil cambiar después". De eso trata nuestro libro.

Dar consejos atemporales sobre arquitectura de software

El ecosistema de desarrollo de software cambia y crece constante y caóticamente. Los temas que estaban de moda hace unos años han sido subsumidos por el ecosistema y han desaparecido o han sido sustituidos por algo diferente o mejor. Por ejemplo, hace 10 años, el estilo de arquitectura predominante en las grandes empresas era la arquitectura orientada a servicios y basada en la orquestación. Ahora, prácticamente ya nadie construye con ese estilo de arquitectura (por razones que iremos descubriendo por el camino); el estilo favorito actual para muchos sistemas distribuidos son los microservicios. ¿Cómo y por qué se ha producido esta transición?

Cuando los arquitectos observan un estilo concreto (especialmente uno histórico), deben tener en cuenta las limitaciones existentes que llevaron a que esa arquitectura se convirtiera en dominante. En aquella época, muchas empresas se estaban fusionando para convertirse en empresas, con todos los problemas de integración que conlleva esa transición. Además, el código abierto no era una opción viable (a menudo por motivos políticos más que técnicos) para las grandes empresas. Así pues, los arquitectos hicieron hincapié en los recursos compartidos y la orquestación centralizada comosolución.

Sin embargo, en los años intermedios, el código abierto y Linux se convirtieron en alternativas viables, haciendo que los sistemas operativos fueran comercialmente libres. Sin embargo, el verdadero punto de inflexión se produjo cuando Linux pasó a ser libre desde el punto de vista operativo con la llegada de herramientas como Puppet y Chef, que permitieron a los equipos de desarrollo programar sus entornos como parte de una construcción automatizada. Una vez que llegó esa capacidad, fomentó una revolución arquitectónica con microservicios y la infraestructura rápidamente emergente de contenedores y herramientas de orquestación como Kubernetes.

Esto ilustra que el ecosistema de desarrollo de software se expande y evoluciona de formas totalmente inesperadas. Una nueva capacidad lleva a otra, que inesperadamente crea nuevas capacidades. Con el paso del tiempo, el ecosistema se sustituye por completo, pieza a pieza.

Esto plantea un viejo problema a los autores de libros sobre tecnología en general y arquitectura de software en particular: ¿cómo podemos escribir algo que no sea viejo inmediatamente?

En este libro no nos centramos en la tecnología ni en otros detalles de implementación. Más bien nos centramos en cómo toman decisiones los arquitectos y en cómo sopesar objetivamente las compensaciones cuando se les presentan situaciones novedosas. Utilizamos escenarios y ejemplos contemporáneos para proporcionar detalles y contexto, pero los principios subyacentes se centran en el análisis de las compensaciones y la toma de decisiones cuando nos enfrentamos a problemas nuevos.

La importancia de los datos en la arquitectura

Los datos son algo precioso y durarán más que los propios sistemas.

Tim Berners-Lee

Para muchos en arquitectura, los datos lo son todo. Toda empresa que construya cualquier sistema debe ocuparse de los datos, ya que suelen vivir mucho más tiempo que los sistemas o la arquitectura, y requieren una reflexión y un diseño diligentes. Sin embargo, muchos de los instintos de los arquitectos de datos de construir sistemas estrechamente acoplados crean conflictos en las arquitecturas distribuidas modernas. Por ejemplo, los arquitectos y los DBA deben garantizar que los datos empresariales sobrevivan a la desintegración de los sistemas monolíticos y que la empresa pueda seguir obteniendo valor de sus datos independientemente de las ondulaciones de la arquitectura.

Se ha dicho que los datos son el activo más importante de una empresa. Las empresas quieren extraer valor de los datos que tienen y están encontrando nuevas formas de implementar los datos en la toma de decisiones. Todas las partes de la empresa se basan ahora en los datos, desde el servicio a los clientes existentes hasta la captación de nuevos clientes, el aumento de la retención de clientes, la mejora de los productos, la predicción de ventas y otras tendencias. Esta dependencia de los datos significa que toda la arquitectura de software está al servicio de los datos, garantizando que los datos correctos estén disponibles y puedan ser utilizados por todas las partes de la empresa.

Los autores construyeron muchos sistemas distribuidos hace unas décadas, cuando se popularizaron, pero la toma de decisiones en los microservicios modernos parece más difícil, y queríamos averiguar por qué. Al final nos dimos cuenta de que, en los primeros tiempos de la arquitectura distribuida, la mayoría de las veces seguíamos persistiendo los datos en una única base de datos relacional. Sin embargo, en los microservicios y la adhesión filosófica a un contexto delimitado del Diseño Orientado al Dominio, como forma de limitar el alcance del acoplamiento de los detalles de implementación, los datos han pasado a ser una preocupación arquitectónica, junto con la transaccionalidad. Muchas de las partes difíciles de la arquitectura moderna se derivan de las tensiones entre las preocupaciones por los datos y la arquitectura, que desenredamos tanto en la Parte I como en la Parte II.

Una distinción importante que tratamos en varios capítulos es la separación entre datos operativos y analíticos:

Datos operativos

Datos utilizados para el funcionamiento de la empresa, incluyendo ventas, datos transaccionales, inventario, etc. Estos datos son con los que funciona la empresa: si algo interrumpe estos datos, la organización no puede funcionar durante mucho tiempo. Este tipo de datos se define como Procesamiento Transaccional Online (OLTP), que suele implicar la inserción, actualización y eliminación de datos en una base de datos.

Datos analíticos

Datos utilizados por los científicos de datos y otros analistas empresariales para predicciones, tendencias y otros tipos de inteligencia empresarial. Estos datos no suelen ser transaccionales y a menudo no son relacionales: pueden estar en una base de datos gráfica o en instantáneas en un formato distinto al de su forma transaccional original. Estos datos no son críticos para el funcionamiento diario, sino para la dirección y las decisiones estratégicas a largo plazo.

A lo largo del libro cubrimos el impacto de los datos tanto operativos como analíticos.

Registros de decisiones arquitectónicas

Una de las formas más eficaces de documentar las decisiones de arquitectura es mediante los Registros de Decisiones de Arquitectura( ADR ). Los ADR fueron evangelizados por primera vez por Michael Nygard en una entrada de blog y posteriormente marcados como "adoptar" en el Radar Tecnológico de Thoughtworks. Un ADR consiste en un breve archivo de texto (normalmente de una o dos páginas) que describe una decisión de arquitectura concreta. Aunque las ADR pueden escribirse utilizando texto sin formato, normalmente se escriben en algún tipo de formato de documento de texto como AsciiDoc o Markdown. Alternativamente, una ADR también puede escribirse utilizando una plantilla de página wiki. Dedicamos un capítulo entero a las ADR en nuestro libro anterior, Fundamentos de la Arquitectura de Software (O'Reilly).

Utilizaremos las ADR para documentar varias decisiones de arquitectura tomadas a lo largo del libro. Para cada decisión de arquitectura, utilizaremos el siguiente formato de ADR, suponiendo que cada ADR se aprueba:

ADR: Una frase nominal corta que contiene la decisión sobre la arquitectura

Contexto
En este apartado del ADR añadiremos una breve descripción del problema, de una o dos frases, y enumeraremos las soluciones alternativas.

Decisión
En esta sección expondremos la decisión sobre la arquitectura y proporcionaremos una justificación detallada de la misma.

Consecuencias
En este apartado del ADR describiremos las consecuencias que puedan derivarse de la aplicación de la decisión, y también hablaremos de las compensaciones que se tuvieron en cuenta.

En el Apéndice B encontrarás una lista de todos los Registros de Decisiones Arquitectónicas creados en este libro.

Documentar una decisión es importante para un arquitecto, pero gobernar el uso adecuado de la decisión es un tema aparte. Afortunadamente, las prácticas modernas de ingeniería permiten automatizar muchas preocupaciones comunes de gobierno mediante el uso defunciones de adecuación de la arquitectura.

Funciones de adecuación de la arquitectura

Una vez que un arquitecto ha identificado la relación entre los componentes y la ha codificado en un diseño, ¿cómo puede asegurarse de que los ejecutores se atendrán a ese diseño? En términos más generales, ¿cómo pueden los arquitectos garantizar que los principios de diseño que definen se hagan realidad si no son ellos quienes los implementan?

Estas cuestiones se engloban bajo el epígrafe de gobernanza de la arquitectura, que se aplica a cualquier supervisión organizada de uno o más aspectos del desarrollo de software. Como este libro trata principalmente de la estructura de la arquitectura, en muchos lugares abordamos cómo automatizar el diseño y los principios de calidad mediante funciones de adecuación.

El desarrollo de software ha evolucionado lentamente a lo largo del tiempo para adaptar prácticas de ingeniería únicas. En los primeros tiempos del desarrollo de software, se solía aplicar una metáfora de fabricación a las prácticas de software, tanto a gran escala (como el proceso de desarrollo en cascada) como a pequeña escala (prácticas de integración en proyectos). A principios de los 90, un replanteamiento de las prácticas de ingeniería de desarrollo de software, liderado por Kent Beck y los demás ingenieros del proyecto C3, denominado Programación eXtrema (XP), ilustró la importancia de la retroalimentación incremental y la automatización como facilitadores clave de la productividad del desarrollo de software. A principios de la década de 2000, las mismas lecciones se aplicaron a la intersección del desarrollo de software y las operaciones, dando lugar al nuevo papel de DevOps y automatizando muchas tareas operativas que antes eran manuales. Al igual que antes, la automatización permite a los equipos ir más rápido porque no tienen que preocuparse de que las cosas se rompan sin una buena retroalimentación. Así pues, la automatización y la retroalimentación se han convertido en principios fundamentales para un desarrollo eficaz del software.

Considera los entornos y situaciones que conducen a avances en la automatización. En la era anterior a la integración continua, la mayoría de los proyectos de software incluían una larga fase de integración. Se esperaba que cada desarrollador trabajara con cierto nivel de aislamiento de los demás, para luego integrar todo el código al final en una fase de integración. Los vestigios de esta práctica aún perduran en las herramientas de control de versiones que fuerzan la ramificación e impiden la integración continua. No es sorprendente que existiera una fuerte correlación entre el tamaño del proyecto y el dolor de la fase de integración. Al ser pioneros en la integración continua, el equipo XP ilustró el valor de la retroalimentación rápida y continua.

La revolución DevOps siguió un curso similar. A medida que Linux y otros programas de código abierto se convirtieron en "suficientemente buenos" para las empresas, junto con la aparición de herramientas que permitían la definición programática de (eventualmente) máquinas virtuales, el personal de operaciones se dio cuenta de que podía automatizar la definición de máquinas y muchas otras tareas repetitivas.

En ambos casos, los avances de la tecnología y los conocimientos permitieron automatizar un trabajo recurrente del que se encargaba una función costosa, lo que describe el estado actual de la gobernanza de la arquitectura en la mayoría de las organizaciones. Por ejemplo, si un arquitecto elige un estilo de arquitectura o un medio de comunicación concreto, ¿cómo puede asegurarse de que un desarrollador lo implemente correctamente? Cuando se hace manualmente, los arquitectos realizan revisiones del código o quizás celebran juntas de revisión de la arquitectura para evaluar el estado de la gobernanza. Sin embargo, al igual que ocurre al configurar manualmente los ordenadores en las operaciones, los detalles importantes pueden caer fácilmente en revisiones superficiales.

Utilizar funciones de aptitud

En el libro de 2017 Building Evolutionary Architectures (O'Reilly), los autores (Neal Ford, Rebecca Parsons y Patrick Kua) definieron el concepto de función de aptitud arquitectónica: cualquier mecanismo que realice una evaluación objetiva de la integridad de alguna característica de la arquitectura o de una combinación de características de la arquitectura. He aquí un desglose punto por punto de esa definición:

Cualquier mecanismo

Los arquitectos pueden utilizar una amplia variedad de herramientas para implementar funciones de adecuación; mostraremos numerosos ejemplos a lo largo del libro. Por ejemplo, existen bibliotecas de pruebas dedicadas para probar la estructura de la arquitectura, los arquitectos pueden utilizar monitores para probar las características operativas de la arquitectura, como el rendimiento o la escalabilidad, y los marcos de ingeniería del caos prueban la fiabilidad y la resistencia.

Evaluación objetiva de la integridad

Un factor clave para la gobernanza automatizada reside en las definiciones objetivas de las características de la arquitectura. Por ejemplo, un arquitecto no puede especificar que quiere un sitio web de "alto rendimiento"; debe proporcionar un valor de objeto que pueda medirse mediante una prueba, un monitoreo u otra función de adecuación.

Los arquitectos deben tener cuidado con las características compuestas de la arquitectura: que no son objetivamente mensurables, pero que en realidad son compuestos de otras cosas mensurables. Por ejemplo, la "agilidad" no es mensurable, pero si un arquitecto empieza a desgranar el amplio término agilidad, el objetivo es que los equipos sean capaces de responder con rapidez y confianza al cambio, ya sea en el ecosistema o en el dominio. Así, un arquitecto puede encontrar características mensurables que contribuyen a la agilidad: capacidad de implementación, capacidad de prueba, tiempo de ciclo, etc. A menudo, la falta de capacidad para medir una característica de la arquitectura indica una definición demasiado vaga. Si los arquitectos se esfuerzan por conseguir propiedades medibles, les permite automatizar la aplicación de la función de adecuación.

Alguna característica de arquitectura o combinación de características de arquitectura

Esta característica describe los dos ámbitos de las funciones de aptitud:

Atómica

Estas funciones de aptitud manejan una única característica de la arquitectura de forma aislada. Por ejemplo, una función de adecuación que comprueba los ciclos de los componentes dentro de una base de código tiene un alcance atómico.

Holístico

Las funciones de aptitudholística validan una combinación de características de arquitectura. Una característica complicada de las características de la arquitectura es la sinergia que a veces presentan con otras características de la arquitectura. Por ejemplo, si un arquitecto quiere mejorar la seguridad, es muy probable que afecte al rendimiento. Del mismo modo, la escalabilidad y la elasticidad a veces están reñidas: soportar un gran número de usuarios simultáneos puede dificultar la gestión de ráfagas repentinas. Las funciones de adecuación holística ejercitan una combinación de características de arquitectura entrelazadas para garantizar que el efecto combinado no afectará negativamente a la arquitectura.

Un arquitecto implementa funciones de adecuación para crear protecciones ante cambios inesperados en las características de la arquitectura. En el mundo del desarrollo ágil de software, los desarrolladores implementan pruebas unitarias, funcionales y de aceptación del usuario para validar distintas dimensiones del diseño del dominio. Sin embargo, hasta ahora no existía ningún mecanismo similar para validar la parte del diseño relativa a las características de la arquitectura. De hecho, la separación entre funciones de aptitud y pruebas unitarias proporciona una buena pauta de alcance para los arquitectos. Las funciones de aptitud validan las características de la arquitectura, no los criterios del dominio; las pruebas unitarias hacen lo contrario. Así, un arquitecto puede decidir si es necesaria una función de aptitud o una prueba unitaria planteándose la pregunta "¿Se necesita algún conocimiento del dominio para ejecutar esta prueba?". Si la respuesta es "sí", entonces es adecuada una prueba de unidad/función/aceptación del usuario; si es "no", entonces se necesita una función de adecuación.

Por ejemplo, cuando los arquitectos hablan de elasticidad, se refieren a la capacidad de la aplicación para soportar una repentina oleada de usuarios. Fíjate en que el arquitecto no necesita conocer ningún detalle sobre el dominio: puede ser un sitio de comercio electrónico, un juego en línea o cualquier otra cosa. Así pues, la elasticidad es una preocupación arquitectónica y está dentro del alcance de una función de adecuación. Si, por el contrario, el arquitecto quisiera validar las partes correctas de una dirección postal, eso se cubre mediante una prueba tradicional. Por supuesto, esta separación no es puramente binaria: algunas funciones de aptitud tocarán el dominio y viceversa, pero los distintos objetivos proporcionan una buena forma de separarlos mentalmente.

He aquí un par de ejemplos para que el concepto sea menos abstracto.

Un objetivo común de los arquitectos es mantener una buena integridad estructural interna en el código base. Sin embargo, fuerzas malévolas actúan contra las buenas intenciones del arquitecto en muchas plataformas. Por ejemplo, al codificar en cualquier entorno de desarrollo Java o .NET popular, en cuanto un programador hace referencia a una clase que aún no se ha importado, el IDE presenta un cuadro de diálogo que pregunta al programador si desea importar automáticamente la referencia. Esto ocurre tan a menudo que la mayoría de los programadores adquieren el hábito de rechazar el cuadro de diálogo de importación automática como un acto reflejo.

Sin embargo, importar arbitrariamente clases o componentes entre sí supone un desastre para la modularidad. Por ejemplo, la Figura 1-1 ilustra un antipatrón especialmente perjudicial que los arquitectos aspiran a evitar.

cyclic dependencies illustration
Figura 1-1. Dependencias cíclicas entre componentes

En este antipatrón, cada componente hace referencia a algo en los demás. Tener una red de componentes como ésta perjudica a la modularidad, porque un desarrollador no puede reutilizar un solo componente sin llevar también consigo a los demás. Y, por supuesto, si los demás componentes están acoplados a otros componentes, la arquitectura tiende cada vez más hacia el antipatrón de la Gran Bola de Barro. ¿Cómo pueden los arquitectos gobernar este comportamiento sin mirar constantemente por encima del hombro a los desarrolladores de gatillo fácil? Las revisiones del código ayudan, pero se producen demasiado tarde en el ciclo de desarrollo para ser eficaces. Si un arquitecto permite que un equipo de desarrollo importe desenfrenadamente a través de la base de código durante una semana hasta la revisión del código, ya se ha producido un daño grave en la base de código.

La solución a este problema es escribir una función de adecuación para evitar los ciclos de los componentes, como se muestra en el Ejemplo 1-1.

Ejemplo 1-1. Función de aptitud para detectar ciclos de componentes
public class CycleTest {
    private JDepend jdepend;

    @BeforeEach
    void init() {
	  jdepend = new JDepend();
	  jdepend.addDirectory("/path/to/project/persistence/classes");
	  jdepend.addDirectory("/path/to/project/web/classes");
	  jdepend.addDirectory("/path/to/project/thirdpartyjars");
    }

    @Test
    void testAllPackages() {
	  Collection packages = jdepend.analyze();
	  assertEquals("Cycles exist", false, jdepend.containsCycles());
    }
}

En el código, un arquitecto utiliza la herramienta de métricas JDepend para comprobar las dependencias entre paquetes. La herramienta entiende la estructura de los paquetes Java y falla la prueba si existe algún ciclo. Un arquitecto puede cablear esta prueba en la construcción continua de un proyecto y dejar de preocuparse por la introducción accidental de ciclos por parte de desarrolladores desencadenados. Este es un gran ejemplo de una función de adecuaciónque protege las prácticas importantes, más que las urgentes, del desarrollo de software: es una preocupación importante para los arquitectos, pero tiene poco impacto en la codificación diaria.

El Ejemplo 1-1 muestra una función de fitness de muy bajo nivel, centrada en el código. Muchas herramientas populares de higiene del código (como SonarQube) implementan muchas funciones de aptitud comunes de forma llave en mano. Sin embargo, los arquitectos también pueden querer validar la macroestructura de la arquitectura, así como la microestructura. Al diseñar una arquitectura por capas como la de Figura 1-2, el arquitecto define las capas para garantizar la separación de preocupaciones.

layered architecture
Figura 1-2. Arquitectura tradicional por capas

Sin embargo, ¿cómo puede garantizar el arquitecto que los desarrolladores respetarán estas capas? Algunos desarrolladores pueden no comprender la importancia de los patrones, mientras que otros pueden adoptar una actitud de "mejor pedir perdón que permiso" debido a alguna preocupación local primordial, como el rendimiento. Pero permitir que los implementadores erosionen las razones de la arquitectura perjudica la salud de ésta a largo plazo.

ArchUnit permite a los arquitectos abordar este problema mediante una función de adecuación, que se muestra en el Ejemplo 1-2.

Ejemplo 1-2. Función de aptitud ArchUnit para gobernar las capas
layeredArchitecture()
    .layer("Controller").definedBy("..controller..")
    .layer("Service").definedBy("..service..")
    .layer("Persistence").definedBy("..persistence..")

    .whereLayer("Controller").mayNotBeAccessedByAnyLayer()
    .whereLayer("Service").mayOnlyBeAccessedByLayers("Controller")
    .whereLayer("Persistence").mayOnlyBeAccessedByLayers("Service")

En el Ejemplo 1-2, el arquitecto define la relación deseable entre capas y escribe una función de aptitud de verificación para gobernarla. Esto permite al arquitecto establecer principios de arquitectura fuera de los diagramas y otros artefactos informativos, y verificarlos de forma continua.

Una herramienta similar en el espacio .NET, NetArchTest, permite realizar pruebas similares para esa plataforma. En el Ejemplo 1-3 aparece una verificación de capas en C#.

Ejemplo 1-3. NetArchTest para dependencias de capa
// Classes in the presentation should not directly reference repositories
var result = Types.InCurrentDomain()
    .That()
    .ResideInNamespace("NetArchTest.SampleLibrary.Presentation")
    .ShouldNot()
    .HaveDependencyOn("NetArchTest.SampleLibrary.Data")
    .GetResult()
    .IsSuccessful;

Siguen apareciendo herramientas en este espacio con grados de sofisticación cada vez mayores. Seguiremos destacando muchas de estas técnicas a medida que ilustremos las funciones de adecuación junto a muchas de nuestras soluciones.

Encontrar un resultado objetivo para una función de adecuación es fundamental. Sin embargo, objetivo no implica estático. Algunas funciones de aptitud tendrán valores de retorno no contextuales, como verdadero/falso o un valor numérico como un umbral de rendimiento. Sin embargo, otras funciones de adecuación (consideradas dinámicas) devuelven un valor basado en algún contexto. Por ejemplo, al medir la escalabilidad, los arquitectos miden el número de usuarios concurrentes y también suelen medir el rendimiento para cada usuario. A menudo, los arquitectos diseñan los sistemas de modo que, a medida que aumenta el número de usuarios, el rendimiento por usuario disminuye ligeramente, pero sin despeñarse. Así, para estos sistemas, los arquitectos diseñan funciones de adecuación del rendimiento que tienen en cuenta el número de usuarios simultáneos. Siempre que la medida de una característica de la arquitectura sea objetiva, los arquitectos podrán probarla.

Aunque la mayoría de las funciones de adecuación deben automatizarse y ejecutarse continuamente, algunas serán necesariamente manuales. Una función de adecuación manual requiere que una persona se encargue de la validación. Por ejemplo, para los sistemas con información legal sensible, un abogado puede tener que revisar los cambios en las partes críticas para garantizar la legalidad, lo que no puede automatizarse. La mayoría de las canalizaciones de implementación admiten etapas manuales, lo que permite a los equipos dar cabida a funciones de adecuación manuales. Lo ideal es que se ejecuten tan a menudo como sea razonablemente posible: una validación que no se ejecuta no puede validar nada. Los equipos ejecutan las funciones de adecuación bajo demanda (raramente) o como parte de un flujo de trabajo de integración continua (lo máshabitual). Para aprovechar plenamente las ventajas de validaciones como las funciones de idoneidad, deben ejecutarse continuamente.

La continuidad es importante, como se ilustra en este ejemplo de gobernanza a nivel empresarial mediante funciones de aptitud. Considera el siguiente escenario: ¿qué hace una empresa cuando se descubre un exploit de día cero en uno de los marcos o bibliotecas de desarrollo que utiliza la empresa? Si es como la mayoría de las empresas, los expertos en seguridad rastrean los proyectos para encontrar la versión infractora del marco y asegurarse de que se actualiza, pero ese proceso rara vez se automatiza, sino que depende de muchos pasos manuales. No se trata de una cuestión abstracta; este escenario exacto afectó a una importante institución financiera descrita en La filtración de datos de Equifax. Al igual que la gobernanza de la arquitectura descrita anteriormente, los procesos manuales son propensos a errores y permiten que se escapen los detalles.

Imagina un mundo alternativo en el que cada proyecto ejecuta una canalización de implementación, y el equipo de seguridad tiene un "hueco" en la canalización de implementación de cada equipo en el que puede desplegar funciones de adecuación. La mayoría de las veces, se tratará de comprobaciones mundanas de salvaguardias, como evitar que los desarrolladores almacenen contraseñas en bases de datos y tareas de gobierno habituales similares. Sin embargo, cuando aparece un exploit de día cero, disponer del mismo mecanismo en todas partes permite al equipo de seguridad insertar una prueba en cada proyecto que comprueba un determinado framework y número de versión; si encuentra la versión peligrosa, falla la compilación y notifica al equipo de seguridad. Los equipos configuran canalizaciones de implementación para que se activen ante cualquier cambio en el ecosistema: código, esquema de base de datos, configuración de la implementación y funciones de adecuación. Esto permite a las empresas automatizar universalmente importantes tareas de gobierno.

Las funciones de aptitud ofrecen muchas ventajas a los arquitectos, entre las que destaca la posibilidad de volver a programar. Una de las quejas universales de los arquitectos es que ya no codifican mucho, ¡pero las funciones de aptitud a menudo son código! Al construir una especificación ejecutable de la arquitectura, que cualquiera puede validar en cualquier momento ejecutando la compilación del proyecto, los arquitectos deben comprender bien el sistema y su evolución continua, lo que se solapa con el objetivo central de mantenerse al día con el código del proyecto a medida que crece.

Por muy potentes que sean las funciones de adecuación, los arquitectos deben evitar utilizarlas en exceso. Los arquitectos no deben formar una cábala y retirarse a una torre de marfil para construir un conjunto imposiblemente complejo y entrelazado de funciones de adecuación que lo único que hacen es frustrar a los desarrolladores y a los equipos. Por el contrario, es una forma de que los arquitectos construyan una lista ejecutable de principios importantes pero no urgentes en los proyectos de software. Muchos proyectos se ahogan en la urgencia, dejando escapar algunos principios importantes. Esta es la causa frecuente de la deuda técnica: "Sabemos que esto es malo, pero ya lo arreglaremos más tarde", y el más tarde nunca llega. Al codificar las reglas sobre la calidad del código, la estructura y otras salvaguardas contra la decadencia en funciones de aptitud que se ejecutan continuamente, los arquitectos construyen una lista de comprobación de la calidad que los desarrolladores no pueden saltarse.

Hace unos años, el excelente libro The Checklist Manifesto de Atul Gawande (Picador) destacaba el uso de listas de comprobación por parte de profesionales como cirujanos, pilotos de líneas aéreas y otros campos que suelen utilizar (a veces por obligación) listas de comprobación como parte de su trabajo. No es porque no conozcan su trabajo o sean especialmente olvidadizos; cuando los profesionales realizan la misma tarea una y otra vez, resulta fácil engañarse cuando se la saltan accidentalmente, y las listas de comprobación lo evitan. Las funciones de adecuación representan una lista de comprobación de principios importantes definidos por los arquitectos y ejecutados como parte de la construcción para asegurarse de que los desarrolladores no se los saltan accidentalmente (o a propósito, debido a fuerzas externas como la presión del calendario).

Utilizamos funciones de aptitud a lo largo del libro cuando surge la oportunidad de ilustrar el gobierno de una solución arquitectónica, así como el diseño inicial.

Arquitectura frente a Diseño: Simplificar las definiciones

Un área de lucha constante para los arquitectos es mantener la arquitectura y el diseño como actividades separadas pero relacionadas. Aunque no queremos entrar en la interminable discusión sobre esta distinción, en este libro nos esforzamos por mantenernos firmemente en el lado de la arquitectura de ese espectro por varias razones.

En primer lugar, los arquitectos deben comprender los principios subyacentes de la arquitectura para tomar decisiones eficaces. Por ejemplo, la decisión entre comunicación síncrona o asíncrona tiene una serie de ventajas y desventajas antes de que los arquitectos incorporen los detalles de implementación. En el libro Fundamentos de la arquitectura del software, los autores acuñaron la segunda ley de la arquitectura del software: el porqué es más importante que el cómo. Aunque, en última instancia, los arquitectos deben entender cómo implementar las soluciones, primero deben comprender por qué una opción tiene mejores compensaciones que otra.

En segundo lugar, al centrarnos en los conceptos de arquitectura, podemos evitar las numerosas implementaciones de esos conceptos. Los arquitectos pueden implementar la comunicación asíncrona de diversas formas; nosotros nos centramos en por qué un arquitecto elegiría la comunicación asíncrona y dejamos los detalles de implementación para otro lugar.

En tercer lugar, si empezamos por el camino de implementar todas las variedades de opciones que mostramos, éste sería el libro más largo jamás escrito. Centrarnos en los principios de la arquitectura nos permite mantener las cosas lo más genéricas posible.

Para mantener los temas lo más basados posible en la arquitectura, utilizamos las definiciones más sencillas posibles para los conceptos clave. Por ejemplo, el acoplamiento en arquitectura puede llenar libros enteros (y lo ha hecho). Para ello, utilizamos las siguientes definiciones sencillas, casi simplistas:

Servicio

En términos coloquiales, un servicio es una colección cohesionada de funcionalidad desplegada como un ejecutable independiente. La mayoría de los conceptos que tratamos sobre los servicios se aplican en general a las arquitecturas distribuidas, y en concreto a las arquitecturas de microservicios.

En los términos que definimos en el Capítulo 2, un servicio forma parte de un cuanto de arquitectura, que incluye otras definiciones de acoplamiento estático y dinámico entre servicios y otros cuantos.

Acoplamiento

Dos artefactos (incluidos los servicios) están acoplados si un cambio en uno puede requerir un cambio en el otro para mantener una funcionalidad adecuada.

Componente

Un bloque de construcción arquitectónico de la aplicación que realiza algún tipo de función empresarial o de infraestructura, que suele manifestarse a través de una estructura de paquetes (Java), un espacio de nombres (C#) o una agrupación física de archivos de código fuente dentro de algún tipo de estructura de directorios. Por ejemplo, el componente Historial de Pedidos podría implementarse a través de un conjunto de archivos de clase ubicados en el espacio de nombres app.business.order.history.

Comunicación sincrónica

Dos artefactos se comunican sincrónicamente si el que llama debe esperar la respuesta antes de continuar.

Comunicación asíncrona

Dos artefactos se comunican de forma asíncrona si el llamante no espera la respuesta de antes de continuar. Opcionalmente, el llamante puede ser notificado por el receptor a través de un canal separado cuando la solicitud haya finalizado.

Coordinación orquestada

Un flujo de trabajo está orquestado si incluye un servicio cuya responsabilidad principal es coordinar el flujo de trabajo.

Coordinación coreografiada

Un flujo de trabajo es coreografiado cuando carece de orquestador; más bien, los servicios del flujo de trabajo comparten las responsabilidades de coordinación del flujo de trabajo.

Atomicidad

Un flujo de trabajo es atómico si todas sus partes mantienen un estado coherente en todo momento; lo contrario está representado por el espectro de la coherencia eventual, tratado en el Capítulo 6.

Contrato

Utilizamos el término contrato en sentido amplio para definir la interfaz entre dos partes de software, que puede abarcar llamadas a métodos o funciones, llamadas remotas a arquitecturas de integración, dependencias, etc. Dondequiera que se unan dos piezas de software, hay un contrato implicado.

La arquitectura de software es abstracta por naturaleza: no podemos saber qué combinación única de plataformas, tecnologías, software comercial y demás vertiginoso abanico de posibilidades pueden tener nuestros lectores, salvo que no hay dos exactamente iguales. Abarcamos muchas ideas abstractas, pero debemos fundamentarlas con algunos detalles de implementación para hacerlas concretas. Para ello, necesitamos un problema con el que ilustrar los conceptos de arquitectura, lo que nos lleva al Escuadrón Sysops.

Presentación de la Saga Sysops Squad

saga

Una larga historia de logros heroicos.

Diccionario Oxford de Inglés

En este libro hablamos de varias sagas, tanto literales como figurativas. Los arquitectos han cooptado el término saga para describir el comportamiento transaccional en las arquitecturas distribuidas (que tratamos en detalle en el Capítulo 12). Sin embargo, las discusiones sobre arquitectura tienden a volverse abstractas, especialmente cuando se consideran problemas abstractos como las partes duras de la arquitectura. Para ayudar a resolver este problema y proporcionar algo de contexto del mundo real para las soluciones que discutimos, iniciamos una saga literal sobre el Escuadrón de Sysops.

Utilizamos la saga Sysops Squad en cada capítulo para ilustrar las técnicas y compensaciones descritas en este libro. Aunque muchos libros sobre arquitectura de software cubren nuevos esfuerzos de desarrollo, muchos problemas del mundo real existen dentro de sistemas existentes. Por tanto, nuestra historia comienza con la arquitectura existente de Sysops Squad que aquí destacamos.

Penultimate Electronics es un gran gigante de la electrónica que tiene numerosas tiendas minoristas en todo el país. Cuando los clientes compran ordenadores, televisores, equipos de música y otros equipos electrónicos, pueden optar por contratar un plan de asistencia. Cuando surgen problemas, expertos en tecnología a disposición del cliente (el Escuadrón de Sysops) acuden a su domicilio (u oficina de trabajo) para solucionar los problemas del aparato electrónico.

Los cuatro usuarios principales de la aplicación de venta de entradas Sysops Squad son los siguientes:

Administrador

El administrador mantiene los usuarios internos del sistema, incluida la lista de expertos y su correspondiente conjunto de habilidades, ubicación y disponibilidad. El administrador también gestiona todo el proceso de facturación para los clientes que utilizan el sistema, y mantiene los datos estáticos de referencia (como los productos admitidos, los pares nombre-valor en el sistema, etc.).

Cliente

El cliente se registra en el servicio Sysops Squad y mantiene su perfil de cliente, contratos de asistencia e información de facturación. Los clientes introducen tickets de problemas en el sistema, y también rellenan encuestas una vez finalizado el trabajo.

Experto en Escuadrón Sysops

A los expertos se les asignan tickets de problemas y arreglan los problemas basándose en el ticket. También interactúan con la base de conocimientos para buscar soluciones a los problemas de los clientes e introducir notas sobre las reparaciones.

Director

El gestor realiza un seguimiento de las operaciones de los tickets de problemas y recibe informes operativos y analíticos sobre el sistema general de tickets de problemas de Sysops Squad.

Flujo de trabajo sin emisión de billetes

Los flujos de trabajo no relacionados con los tickets incluyen las acciones que realizan los administradores, los gestores de y los clientes que no están relacionadas con un ticket de problema. Estos flujos de trabajo se describen a continuación:

  1. Los expertos de Sysops Squad se añaden y mantienen en el sistema a través de un administrador, que introduce su ubicación, disponibilidad y habilidades.

  2. Los clientes se registran en el sistema Sysops Squad y disponen de varios planes de asistencia en función de los productos que hayan adquirido.

  3. A los clientes se les factura automáticamente cada mes en función de la información de la tarjeta de crédito contenida en su perfil. Los clientes pueden ver el historial de facturación y los extractos a través del sistema.

  4. Los gestores solicitan y reciben diversos informes operativos y analíticos, como informes financieros, informes de rendimiento de expertos e informes de venta de entradas.

Flujo de trabajo de la gestión de incidencias

El flujo de trabajo de los tickets comienza cuando un cliente introduce un ticket de problema en el sistema, y termina cuando el cliente completa la encuesta una vez realizada la reparación. Este flujo de trabajo se describe a continuación:

  1. Los clientes que han contratado el plan de asistencia introducen un ticket de problema utilizando el sitio web de Sysops Squad.

  2. Una vez introducido un ticket de problema en el sistema, éste determina qué experto del Escuadrón Sysops sería el más adecuado para el trabajo en función de sus habilidades, ubicación actual, área de servicio y disponibilidad.

  3. Una vez asignado, el ticket de problema se carga en una aplicación móvil personalizada en el dispositivo móvil del experto de Sysops Squad. También se notifica al experto mediante un mensaje de texto que tiene un nuevo ticket de problema.

  4. Se notifica al cliente mediante un mensaje de texto SMS o un correo electrónico (según sus preferencias de perfil) que el experto está de camino.

  5. El experto utiliza la aplicación móvil personalizada en su teléfono para recuperar la información y la ubicación del ticket. El experto de Sysops Squad también puede acceder a una base de conocimientos a través de la aplicación móvil para averiguar qué se ha hecho en el pasado para solucionar el problema.

  6. Una vez que el experto soluciona el problema, marca el ticket como "completo". El experto del escuadrón de sysops puede entonces añadir información sobre el problema y reparar la base de conocimientos.

  7. Una vez que el sistema recibe la notificación de que el ticket está completo, envía un correo electrónico al cliente con un enlace a una encuesta, que éste rellena.

  8. El sistema recibe la encuesta cumplimentada del cliente y registra la información de la encuesta.

Un mal escenario

Las cosas no han ido bien últimamente con la aplicación de tickets de problemas Sysops Squad. El sistema actual de tickets de problemas es una gran aplicación monolítica que se desarrolló hace muchos años. Los clientes se están quejando de que los consultores nunca aparecen porque se pierden los tickets, y a menudo aparece el consultor equivocado para arreglar algo de lo que no sabe nada. Los clientes también se han quejado de que el sistema no siempre está disponible para introducir nuevos tickets de problemas.

El cambio también es difícil y arriesgado en este gran monolito. Siempre que se hace un cambio, suele llevar demasiado tiempo y suele romperse algo más. Debido a los problemas de fiabilidad, el sistema Sysops Squad se "congela" o se bloquea con frecuencia, lo que provoca que toda la funcionalidad de la aplicación no esté disponible entre cinco minutos y dos horas mientras se identifica el problema y se reinicia la aplicación.

Si no se hace algo pronto, Penultimate Electronics se verá obligada a abandonar la muy lucrativa línea de negocio de contratos de soporte y despedir a todos los administradores, expertos, gestores y personal de desarrollo informático de Sysops Squad, incluidos los arquitectos.

Componentes arquitectónicos del Escuadrón Sysops

El sistema monolítico de la aplicación Sysops Squad se encarga de la gestión de tickets, los informes operativos de, el registro de clientes y la facturación, así como de funciones administrativas generales como el mantenimiento de usuarios, el inicio de sesión y el mantenimiento de habilidades y perfiles de expertos. La Figura 1-3 y la correspondiente Tabla 1-1 ilustran y describen los componentes de la aplicación monolítica existente (la parte ss. del espacio de nombres especifica el contexto de la aplicación Escuadrón Sysops).

Sysops Squad Components
Figura 1-3. Componentes de la aplicación existente Sysops Squad
Tabla 1-1. Componentes existentes del Escuadrón Sysops
Componente Espacio de nombres Responsabilidad

Iniciar sesión

ss.login

Lógica de inicio de sesión y seguridad de usuarios y clientes internos

Pago de la factura

ss.billing.payment

Facturación mensual del cliente e información de la tarjeta de crédito del cliente

Historial de facturación

ss.billing.history

Historial de pagos y extractos de facturación anteriores

Notificación al cliente

ss.customer.notification

Notificar al cliente la facturación, información general

Perfil del cliente

ss.customer.profile

Mantener el perfil del cliente, registro de clientes

Perfil del experto

ss.expert.profile

Mantén el perfil del experto (nombre, ubicación, habilidades, etc.)

KB mantenimiento

ss.kb.maintenance

Mantener y ver elementos en la base de conocimientos

Búsqueda KB

ss.kb.search

Motor de consulta para buscar en la base de conocimientos

Informar

ss.reporting

Todos los informes (expertos, entradas, financieros)

Billete

ss.ticket

Creación de entradas, mantenimiento, finalización, código común

Asignar billete

ss.ticket.assign

Busca un experto y asigna el ticket

Notificar billete

ss.ticket.notify

Avisa al cliente de que el experto está de camino

Ruta del billete

ss.ticket.route

Envía el ticket a la app del dispositivo móvil del experto

Contrato de apoyo

ss.supportcontract

Contratos de apoyo a los clientes, productos del plan

Encuesta

ss.survey

Mantener las encuestas, capturar y registrar los resultados de las encuestas

Notificar encuesta

ss.survey.notify

Enviar correo electrónico de encuesta al cliente

Plantillas de encuestas

ss.survey.templates

Mantener varias encuestas basadas en el tipo de servicio

Mantenimiento del usuario

ss.users

Mantener usuarios y roles internos

Estos componentes se utilizarán en los capítulos siguientes para ilustrar diversas técnicas y compensaciones a la hora de dividir las aplicaciones enarquitecturas distribuidas.

Modelo de datos del Escuadrón Sysops

La aplicación Sysops Squad, con sus diversos componentes enumerados en la Tabla 1-1 , utiliza un único esquema en la base de datos para alojar todas sus tablas y el código de base de datos relacionado. La base de datos se utiliza para persistir clientes, usuarios, contratos, facturación, pagos, base de conocimientos y encuestas a clientes; las tablas se enumeran en la Tabla 1-2, y el modelo ER se ilustra en la Figura 1-4.

Sysops Squad data model
Figura 1-4. Modelo de datos de la aplicación existente Sysops Squad
Tabla 1-2. Tablas existentes de la base de datos del Escuadrón Sysops
Tabla Responsabilidad

Cliente

Entidades que necesitan apoyo de los Sysops

Notificación_cliente

Preferencias de notificación para los clientes

Encuesta

Una encuesta para la satisfacción del cliente post-servicio

Pregunta

Preguntas de una encuesta

Pregunta_de_la_encuesta

Se asigna una pregunta a la encuesta

Encuesta_Administrada

La pregunta de la encuesta se asigna al cliente

Respuesta_encuesta

Respuesta de un cliente a la encuesta

Facturación

Información de facturación del contrato de asistencia

Contrato

Un contrato de asistencia entre una entidad y los Sysops

Método de pago

Métodos de pago admitidos para realizar el pago

Pago

Pagos procesados por facturaciones

Usuario_SysOps

Los distintos usuarios en Sysops

Perfil

Información del perfil de los usuarios Sysops

Perfil_de_experto

Perfiles de expertos

Experiencia

Diversos conocimientos en Sysops

Ubicación

Localidades atendidas por el experto

Artículo

Artículos para la base de conocimientos

Etiqueta

Etiquetas de los artículos

Palabra clave

Palabra clave para un artículo

Etiqueta_artículo

Etiquetas asociadas a los artículos

Palabra_clave_del_artículo

Tabla de unión de palabras clave y artículos

Billete

Tickets de soporte planteados por los clientes

Tipo_ticket

Diferentes tipos de billetes

Historia_de_los_billetes

La historia de los tickets de soporte

El modelo de datos de Sysops es un modelo de datos estándar de tercera forma normal, con sólo unos pocos procedimientos almacenados o desencadenadores. Sin embargo, existe un buen número de vistas que utiliza principalmente el componente Informes. A medida que el equipo de arquitectura intente dividir la aplicación y avanzar hacia una arquitectura distribuida, tendrá que trabajar con el equipo de la base de datos para realizar las tareas a nivel de base de datos. Esta configuración de tablas y vistas de la base de datos se utilizará a lo largo del libro para discutir diversas técnicas y compensaciones para llevar a cabo la tarea de descomponer la base de datos.

Get Arquitectura de software: Las partes difíciles now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.