ARQUITECTURA
ARQUITECTURA
Fundamentos de
Software
Arquitectura
Un enfoque de ingeniería
Neal y Mark no son solo arquitectos de software excepcionales, sino también profesores
excepcionales. Con Fundamentos de arquitectura de software, han logrado condensar
el extenso tema de la arquitectura en un trabajo conciso que refleja sus décadas de
experiencia. Ya sea que sea nuevo en el puesto o que haya ejercido la arquitectura durante
muchos años, este libro lo ayudará a ser mejor en su trabajo.
Ojalá hubieran escrito esto antes en mi carrera.
—Nathaniel Schutta, arquitecto como servicio, ntschutta.io
Mark y Neal realmente captan consejos del mundo real para que los tecnólogos impulsen la
excelencia arquitectónica. Lo logran identificando características arquitectónicas comunes
y las compensaciones necesarias para impulsar el éxito.
Fundamentos de la arquitectura de
software por Mark Richards y Neal Ford
Copyright © 2020 Mark Richards, Neal Ford. Todos los derechos reservados.
Publicado por O'Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472.
Los libros de O'Reilly se pueden comprar con fines educativos, comerciales o promocionales. También hay ediciones en línea disponibles
para la mayoría de los títulos (http://oreilly.com). Para obtener más información, comuníquese con nuestro departamento de ventas
corporativo/institucional: 8009989938 o corporate@oreilly.com.
El logotipo de O'Reilly es una marca registrada de O'Reilly Media, Inc. Fundamentals of Soware Architecture, la imagen de portada y la
imagen comercial relacionada son marcas comerciales de O'Reilly Media, Inc.
Las opiniones expresadas en este trabajo son las de los autores y no representan las del editor.
Si bien el editor y los autores han hecho todo lo posible para garantizar que la información y las instrucciones contenidas en este trabajo
sean precisas, el editor y los autores no se hacen responsables de errores u omisiones, incluida, entre otras, la responsabilidad por daños
que resulten del uso o la confianza depositada en este trabajo. El uso de la información y las instrucciones contenidas en este trabajo se
realiza bajo su propio riesgo. Si algún ejemplo de código u otra tecnología que este trabajo contiene o describe está sujeto a licencias de
código abierto o a los derechos de propiedad intelectual de terceros, es su responsabilidad asegurarse de que su uso cumpla con dichas
licencias o derechos.
9781492043454
[LSCH]
Machine Translated by Google
Tabla de contenido
1. Introducción. ... 1
Definición de arquitectura de software 3
Expectativas de un arquitecto 8
Tomar decisiones de arquitectura 9
Analizar continuamente la arquitectura 9
Mantenerse actualizado con las últimas 10
tendencias Garantizar el cumplimiento de 10
las decisiones Exposición y experiencia 11
diversas Tener conocimiento del dominio 11
empresarial Poseer habilidades 12
interpersonales Comprender y navegar 12
por la política Intersección de la arquitectura y… 13
Prácticas de ingeniería 14
Operaciones/DevOps 17
Proceso 18
Datos 19
Leyes de la arquitectura de software 19
Parte I. Fundamentos
v
Machine Translated by Google
Análisis de compensaciones 30
3. Modularidad. ...
Definición 38
Medición de la modularidad 40
Cohesión 40
Enganche 44
De módulos a componentes 53
Características explícitas 70
Características implícitas 73
Medidas operativas 78
Medidas estructurales 79
Medidas de proceso 81
Funciones de gobernanza y aptitud 82
| Tabla de contenidos
nosotros
Machine Translated by Google
particionamiento 108
Arquitectura cuántica Redux: ¿Cómo elegir entre arquitectura monolítica y arquitectura cuántica?
Arquitecturas distribuidas 115
9. Fundamentos. ...
Patrones fundamentales 119
Tubería 144
Filtros 144
Ejemplo 145
Registro 157
Contratos 158
SolicitudRespuesta 204
Cómo elegir entre un modelo basado en solicitudes y uno basado en eventos 206
Taxonomía 236
Servicios 236
empresariales 237
de orquestación… y 239
Topología 246
Repartido 247
Contexto delimitado 247
Índice de contenidos | ix
Machine Translated by Google
Granularidad 248
Aislamiento de datos 249
caso de monolito modular distribuido con micronúcleo: se va, se va, se fue 274
Ejemplo 294
x | Tabla de contenidos
Machine Translated by Google
Consenso 304
Disponibilidad 310
Elasticidad 312
Seguridad 313
Presentación 321
Invisibilidad 324
Índice de contenidos | xi
Machine Translated by Google
Resumen 363
Índice. ...
Axioma
Una declaración o proposición que se considera establecida, aceptada o evidentemente
verdadera.
Los matemáticos crean teorías basadas en axiomas, suposiciones sobre cosas que son indiscutiblemente
ciertas. Los arquitectos de software también construyen teorías sobre axiomas, pero el mundo del software
es, bueno, más complicado que las matemáticas: las cosas fundamentales siguen cambiando a un ritmo
rápido, incluidos los axiomas en los que basamos nuestras teorías.
El ecosistema de desarrollo de software existe en un estado constante de equilibrio dinámico: si bien existe
en un estado equilibrado en un momento dado, exhibe un comportamiento dinámico a largo plazo. Un gran
ejemplo moderno de la naturaleza de este ecosistema sigue el ascenso de la contenedorización y los
cambios que la acompañan: herramientas como Kubernetes. Hace una década no existían, pero ahora
existen conferencias de software enteras para dar servicio a sus usuarios. El ecosistema del software
cambia caóticamente: un pequeño cambio provoca otro pequeño cambio; cuando se repite cientos de veces,
genera un nuevo ecosistema.
Los arquitectos tienen la importante responsabilidad de cuestionar los supuestos y axiomas que quedaron
de épocas anteriores. Muchos de los libros sobre arquitectura de software se escribieron en una época que
apenas se parece al mundo actual. De hecho, los autores creen que debemos cuestionar los axiomas
fundamentales de manera regular, a la luz de las mejores prácticas de ingeniería, los ecosistemas operativos,
los procesos de desarrollo de software, todo lo que compone el desordenado y dinámico equilibrio en el que
arquitectos y desarrolladores trabajan cada día.
Los observadores atentos de la arquitectura de software a lo largo del tiempo fueron testigos de una
evolución de las capacidades. Comenzando con las prácticas de ingeniería de la Programación Extrema,
Continuando con la entrega continua, la revolución de DevOps, los microservicios, la contenedorización y
ahora los recursos basados en la nube, todas estas innovaciones llevaron a nuevas capacidades y
compensaciones. A medida que las capacidades cambiaron, también lo hicieron las perspectivas de los
arquitectos sobre la industria. Durante muchos años, la definición irónica de la arquitectura de software fue "el material
xiii
Machine Translated by Google
"Eso es difícil de cambiar más adelante". Más tarde, apareció el estilo de arquitectura de microservicios, donde el
cambio es una consideración de diseño de primera clase.
Cada nueva era requiere nuevas prácticas, herramientas, mediciones, patrones y una serie de otros cambios. Este
libro analiza la arquitectura de software desde una perspectiva moderna, teniendo en cuenta todas las innovaciones
de la última década, junto con algunas métricas y medidas nuevas adaptadas a las nuevas estructuras y
perspectivas actuales.
El subtítulo de nuestro libro es “Un enfoque de ingeniería”. Los desarrolladores llevan mucho tiempo deseando
que el desarrollo de software pase de ser una actividad artesanal, en la que artesanos cualificados pueden crear
obras únicas, a una disciplina de ingeniería, que implica repetibilidad, rigor y análisis eficaz. Si bien la ingeniería
de software todavía está por detrás de otros tipos de disciplinas de ingeniería en muchos órdenes de magnitud
(para ser justos, el software es una disciplina muy joven en comparación con la mayoría de los otros tipos de
ingeniería), los arquitectos han realizado enormes mejoras, que analizaremos. En particular, las prácticas
modernas de ingeniería ágil han permitido grandes avances en los tipos de sistemas que diseñan los arquitectos.
También abordamos la cuestión de suma importancia del análisis de compensaciones. Como desarrollador de
software, es fácil enamorarse de una tecnología o un enfoque en particular.
Pero los arquitectos siempre deben evaluar con seriedad lo bueno, lo malo y lo feo de cada opción, y prácticamente
nada en el mundo real ofrece opciones binarias convenientes: todo es una cuestión de disyuntivas. Dada esta
perspectiva pragmática, nos esforzamos por eliminar los juicios de valor sobre la tecnología y, en cambio, nos
centramos en analizar las disyuntivas para dotar a nuestros lectores de una mirada analítica sobre las opciones
tecnológicas.
Este libro no convertirá a alguien en arquitecto de software de la noche a la mañana: es un campo lleno de matices
y con muchas facetas. Queremos ofrecer a los arquitectos actuales y emergentes una buena visión general
moderna de la arquitectura de software y sus muchos aspectos, desde la estructura hasta las habilidades blandas.
Si bien este libro cubre patrones bien conocidos, adoptamos un nuevo enfoque, apoyándonos en lecciones
aprendidas, herramientas, prácticas de ingeniería y otros aportes. Tomamos muchos axiomas existentes en la
arquitectura de software y los repensamos a la luz del ecosistema actual, y diseñamos arquitecturas teniendo en
cuenta el panorama moderno.
Cursiva
Indica nuevos términos, URL, direcciones de correo electrónico, nombres de archivos y extensiones de archivos.
Ancho constante
Se utiliza para listados de programas, así como dentro de párrafos para hacer referencia a elementos del
programa, como nombres de variables o funciones, bases de datos, tipos de datos, variables de entorno,
declaraciones y palabras clave.
Muestra texto que debe reemplazarse con valores proporcionados por el usuario o por valores
determinados por el contexto.
El material complementario (ejemplos de código, ejercicios, etc.) está disponible para descargar en http://
fundamentalsofsowarearchitecture.com.
Si tiene una pregunta técnica o un problema al utilizar los ejemplos de código, envíe un correo
electrónico a bookquestions@oreilly.com.
Este libro está aquí para ayudarle a hacer su trabajo. En general, si se ofrece código de ejemplo
con este libro, puede usarlo en sus programas y documentación. No necesita ponerse en
contacto con nosotros para solicitar permiso a menos que esté reproduciendo una parte
importante del código. Por ejemplo, escribir un programa que utilice varios fragmentos de código
de este libro no requiere permiso. Vender o distribuir ejemplos de los libros de O'Reilly sí requiere
permiso. Responder a una pregunta citando este libro y citando código de ejemplo no requiere
permiso. Incorporar una cantidad significativa de código de ejemplo de este libro en la
documentación de su producto sí requiere permiso.
Agradecemos la atribución, aunque por lo general no la exigimos. Una atribución suele incluir el
título, el autor, el editor y el ISBN. Por ejemplo: “Fundamentals of So ware Architecture de
Mark Richards y Neal Ford (O'Reilly). Copyright 2020 Mark Richards, Neal Ford,
9781492043454”.
Si considera que su uso de ejemplos de código no se ajusta al uso justo o al permiso otorgado anteriormente,
no dude en contactarnos a permissions@oreilly.com.
Nuestra red única de expertos e innovadores comparte sus conocimientos y experiencia a través de libros,
artículos y nuestra plataforma de aprendizaje en línea. La plataforma de aprendizaje en línea de O'Reilly le
brinda acceso a pedido a cursos de capacitación en vivo, rutas de aprendizaje en profundidad, entornos de
codificación interactivos y una vasta colección de textos y videos de O'Reilly y más de 200 editoriales. Para
obtener más información, visite http://oreilly.com .
Cómo contactarnos
Por favor, dirija sus comentarios y preguntas sobre este libro al editor:
Contamos con una página web para este libro, donde enumeramos erratas, ejemplos y cualquier información
adicional. Puede acceder a esta página en https://oreil.ly/fundamentalsofsowarearchitecture .
Envíe un correo electrónico a bookquestions@oreilly.com para comentar o hacer preguntas técnicas sobre
este libro.
YouTube: http://www.youtube.com/oreillymedia
Expresiones de gratitud
Mark y Neal quieren agradecer a todas las personas que asistieron a nuestras clases, talleres,
sesiones de conferencias, reuniones de grupos de usuarios, así como a todas las demás personas
que escucharon versiones de este material y nos brindaron comentarios invaluables. También nos
gustaría agradecer al equipo editorial de O'Reilly, que hizo que esta experiencia fuera tan sencilla
como escribir un libro. También nos gustaría agradecer al director de No Stuff Just Fluff, Jay
Zimmerman, por crear una serie de conferencias que permite que crezca y se difunda un buen
contenido técnico, y a todos los demás oradores cuyos comentarios y hombros empapados de
lágrimas apreciamos. También nos gustaría agradecer a algunos oasis aleatorios de grupos que
preservan la cordura y generan ideas, que tienen nombres como Pasty Geeks y Hacker B&B.
CAPÍTULO 1
Introducción
El puesto de “arquitecto de software” aparece en los primeros puestos de numerosas listas de los mejores
empleos del mundo. Sin embargo, cuando los lectores observan los demás empleos de esas listas (como el de
enfermero o director financiero), hay una clara trayectoria profesional para ellos. ¿Por qué no hay una trayectoria
para los arquitectos de software?
En primer lugar, la industria no tiene una buena definición de la arquitectura de software en sí. Cuando
impartimos clases básicas, los estudiantes a menudo piden una definición concisa de lo que hace un arquitecto
de software, y nos hemos negado rotundamente a darla. Y no somos los únicos. En su famoso informe técnico
“¿Quién necesita un arquitecto?” Martin Fowler se negó famosamente a intentar definirlo, recurriendo en cambio
a la famosa cita:
Cuando nos presionaron, creamos el mapa mental que se muestra en la Figura 11, que lamentablemente está
incompleto pero es indicativo del alcance de la arquitectura de software. De hecho, ofreceremos nuestra
definición de arquitectura de software en breve.
En segundo lugar, como se ilustra en el mapa mental, el papel del arquitecto de software incorpora una enorme
cantidad y alcance de responsabilidad que continúa expandiéndose. Hace una década, los arquitectos de
software se ocupaban únicamente de los aspectos puramente técnicos de la arquitectura, como la modularidad,
los componentes y los patrones. Desde entonces, debido a los nuevos estilos arquitectónicos que aprovechan
una gama más amplia de capacidades (como los microservicios), el papel del arquitecto de software se ha
expandido. Cubrimos las muchas intersecciones de la arquitectura y el resto de la organización en “Intersección
de la arquitectura y…” en la página 13.
1
Machine Translated by Google
En cuarto lugar, gran parte del material sobre arquitectura de software tiene sólo relevancia histórica.
Los lectores de la página de Wikipedia no dejarán de notar la desconcertante variedad de acrónimos
y referencias cruzadas a todo un universo de conocimiento. Sin embargo, muchos de estos acrónimos
representan intentos obsoletos o fallidos. Incluso soluciones que eran perfectamente válidas hace
unos años no pueden funcionar ahora porque el contexto ha cambiado. La historia de la arquitectura
de software está llena de cosas que los arquitectos han intentado, sólo para darse cuenta de los
efectos secundarios perjudiciales. Cubrimos muchas de esas lecciones en este libro.
2 | Capítulo 1: Introducción
Machine Translated by Google
¿Por qué un libro sobre los fundamentos de la arquitectura de software ahora? El ámbito de la
arquitectura de software no es la única parte del mundo del desarrollo que cambia constantemente.
Nuevas tecnologías, técnicas, capacidades... De hecho, es más fácil encontrar cosas que no han
cambiado en la última década que enumerar todos los cambios. Los arquitectos de software deben
tomar decisiones dentro de este ecosistema en constante cambio. Como todo cambia, incluso las bases
sobre las que tomamos decisiones, los arquitectos deberían reexaminar algunos axiomas fundamentales
que sirvieron de base a los escritos anteriores sobre arquitectura de software. Por ejemplo, los libros
anteriores sobre arquitectura de software no consideran el impacto de DevOps porque no existía cuando
se escribieron estos libros.
Al estudiar arquitectura, los lectores deben tener en cuenta que, como ocurre con gran parte del arte,
sólo se puede entender en contexto. Muchas de las decisiones que tomaron los arquitectos se basaron
en las realidades del entorno en el que se encontraban. Por ejemplo, uno de los principales objetivos
de la arquitectura de finales del siglo XX incluía hacer el uso más eficiente de los recursos compartidos,
porque toda la infraestructura de la época era cara y comercial: sistemas operativos, servidores de
aplicaciones, servidores de bases de datos, etc. Imaginemos que en 2002 entramos en un centro de
datos y le decimos al jefe de operaciones: “Oye, tengo una gran idea para un estilo revolucionario de
arquitectura, donde cada servicio se ejecuta en su propia maquinaria aislada, con su propia base de
datos dedicada (lo que describe lo que ahora conocemos como microservicios). Entonces, eso significa
que necesitaré 50 licencias para Windows, otras 30 licencias para servidores de aplicaciones y al
menos 50 licencias para servidores de bases de datos”. En 2002, intentar construir una arquitectura
como la de los microservicios sería inconcebiblemente caro. Sin embargo, con la llegada del código
abierto durante los años intermedios, junto con las prácticas de ingeniería actualizadas a través de la
revolución DevOps, podemos construir razonablemente una arquitectura como la descrita. Los lectores
deben tener en cuenta que todas las arquitecturas son un producto de su
contexto.
La figura 12 ilustra una forma de pensar en la arquitectura de software. En esta definición, la
arquitectura de software consiste en la estructura del sistema (indicada por las líneas negras
gruesas que sostienen la arquitectura), combinada con las características de la arquitectura (“
ilidades”) que el sistema debe soportar, las decisiones de arquitectura y, por último, los principios
de diseño.
4 | Capítulo 1: Introducción
Machine Translated by Google
La estructura del sistema, como se ilustra en la Figura 13, se refiere al tipo de estilo (o estilos) de
arquitectura en el que se implementa el sistema (como microservicios, capas o microkernel). Describir
una arquitectura únicamente por la estructura no la explica por completo. Por ejemplo, supongamos que
se le pide a un arquitecto que describa una arquitectura y ese arquitecto responde "es una arquitectura
de microservicios". Aquí, el arquitecto solo está hablando de la estructura del sistema, pero no de la
arquitectura del sistema. También es necesario conocer las características de la arquitectura, las
decisiones de arquitectura y los principios de diseño para comprender completamente la arquitectura del
sistema.
Las características de la arquitectura son otra dimensión de la definición de la arquitectura del software
(véase la Figura 14). Las características de la arquitectura definen los criterios de éxito de un sistema,
que generalmente son ortogonales a la funcionalidad del sistema. Observe que todas las características
enumeradas no requieren conocimiento de la funcionalidad del sistema, pero son necesarias para que el
sistema funcione correctamente. Las características de la arquitectura son tan importantes que hemos
dedicado varios capítulos de este libro a comprenderlas y definirlas.
Figura 14. Las características de la arquitectura se refieren a las “ilidades” que el sistema debe
soportar
El siguiente factor que define la arquitectura del software son las decisiones de arquitectura. Las
decisiones de arquitectura definen las reglas sobre cómo debe construirse un sistema. Por ejemplo, un
arquitecto puede tomar una decisión de arquitectura según la cual solo las capas de negocios y servicios
dentro de una arquitectura en capas pueden acceder a la base de datos (consulte la Figura 15), lo que
restringe la capacidad de la capa de presentación para realizar llamadas directas a la base de datos. Las
decisiones de arquitectura forman las restricciones del sistema y dirigen a los equipos de desarrollo sobre
lo que está permitido y lo que no.
6 | Capítulo 1: Introducción
Machine Translated by Google
Figura 15. Las decisiones de arquitectura son reglas para construir sistemas
Si una decisión de arquitectura particular no se puede implementar en una parte del sistema debido
a alguna condición u otra restricción, esa decisión (o regla) se puede romper a través de algo llamado
una variación. La mayoría de las organizaciones tienen modelos de variación que son utilizados por
un comité de revisión de arquitectura (ARB) o arquitecto jefe. Esos modelos formalizan el proceso
para buscar una variación a un estándar particular o decisión de arquitectura. Una excepción a una
decisión de arquitectura particular es analizada por el ARB (o arquitecto jefe si no existe ARB) y es
aprobada o rechazada en función de justificaciones y compensaciones.
El último factor en la definición de arquitectura son los principios de diseño. Un principio de diseño se
diferencia de una decisión de arquitectura en que un principio de diseño es una guía en lugar de una
regla estricta. Por ejemplo, el principio de diseño ilustrado en la Figura 16 establece que los equipos
de desarrollo deben aprovechar la mensajería asincrónica entre servicios dentro de una arquitectura
de microservicios para aumentar el rendimiento. Una decisión de arquitectura (regla) nunca podría
cubrir todas las condiciones y opciones para la comunicación entre servicios, por lo que un principio
de diseño se puede utilizar para proporcionar una guía para el método preferido (en este caso,
mensajería asincrónica) para permitir que el desarrollador elija un protocolo de comunicación más
apropiado (como REST o gRPC) dada una circunstancia específica.
Figura 16. Los principios de diseño son pautas para construir sistemas.
Expectativas de un arquitecto
Definir el rol de un arquitecto de software presenta tanta dificultad como definir la arquitectura de software.
Puede abarcar desde un programador experto hasta definir la dirección técnica estratégica de la empresa.
En lugar de perder el tiempo en la tonta tarea de definir el rol, recomendamos centrarse en las expectativas
de un arquitecto.
8 | Capítulo 1: Introducción
Machine Translated by Google
La primera clave para la eficacia y el éxito en el rol de arquitecto de software depende de comprender
y practicar cada una de estas expectativas.
Se espera que un arquitecto defina las decisiones de arquitectura y los principios de diseño utilizados
para guiar las decisiones tecnológicas dentro del equipo, el departamento o en toda la empresa.
Guía es la palabra clave en esta primera expectativa. Un arquitecto debería guiar en lugar de
especificar opciones tecnológicas. Por ejemplo, un arquitecto podría tomar la decisión de usar React.js
para el desarrollo frontend. En este caso, el arquitecto está tomando una decisión técnica en lugar de
una decisión arquitectónica o un principio de diseño que ayudará al equipo de desarrollo a tomar
decisiones. En cambio, un arquitecto debería instruir a los equipos de desarrollo para que usen un
marco basado en reactivos para el desarrollo web frontend, guiando así al equipo de desarrollo en la
elección entre Angular, Elm, React.js, Vue o cualquiera de los otros marcos web basados en reactivos.
Esta expectativa de un arquitecto se refiere a la vitalidad de la arquitectura, que evalúa cuán viable
es hoy la arquitectura que se definió hace tres o más años, dados los cambios tanto en los negocios
como en la tecnología. En nuestra experiencia, no hay suficientes arquitectos que concentren sus
energías en analizar continuamente las arquitecturas existentes. Como resultado, la mayoría de las
arquitecturas experimentan elementos de decadencia estructural, que ocurre cuando los
desarrolladores realizan cambios de codificación o diseño que afectan las características
arquitectónicas requeridas, como el rendimiento, la disponibilidad y la escalabilidad.
Otros aspectos olvidados de esta expectativa que los arquitectos suelen olvidar son los entornos de
prueba y lanzamiento. La agilidad para la modificación del código tiene beneficios obvios, pero si los
equipos tardan semanas en probar los cambios y meses en lanzarlos, los arquitectos no pueden
lograr agilidad en la arquitectura general.
Expectativas de un arquitecto | 9
Machine Translated by Google
Un arquitecto debe analizar de manera integral los cambios en la tecnología y los dominios de los problemas
para determinar la solidez de la arquitectura. Si bien este tipo de consideración rara vez aparece en una
publicación de empleo, los arquitectos deben cumplir con esta expectativa para mantener la relevancia de las
solicitudes.
Se espera que un arquitecto se mantenga actualizado con las últimas tecnologías y tendencias de la industria.
Los desarrolladores deben mantenerse actualizados sobre las últimas tecnologías que utilizan a diario para
seguir siendo relevantes (¡y conservar su trabajo!). Un arquitecto tiene un requisito aún más crítico: mantenerse
actualizado sobre las últimas tendencias técnicas y de la industria. Las decisiones que toma un arquitecto tienden
a ser duraderas y difíciles de cambiar. Comprender y seguir las tendencias clave ayuda al arquitecto a prepararse
para el futuro y tomar la decisión correcta.
Seguir las tendencias y mantenerse al día con ellas es difícil, en particular para un arquitecto de software. En el
Capítulo 24, analizamos diversas técnicas y recursos sobre cómo hacerlo.
Se espera que un arquitecto garantice el cumplimiento de las decisiones arquitectónicas y los principios de diseño.
Garantizar el cumplimiento significa que el arquitecto verifica continuamente que los equipos de desarrollo sigan
las decisiones de arquitectura y los principios de diseño definidos, documentados y comunicados por el arquitecto.
Considere el escenario en el que un arquitecto toma la decisión de restringir el acceso a la base de datos en una
arquitectura en capas solo a las capas de negocios y servicios (y no a la capa de presentación). Esto significa
que la capa de presentación debe pasar por todas las capas de la arquitectura para realizar incluso las llamadas
a la base de datos más simples. Un desarrollador de interfaz de usuario podría estar en desacuerdo con esta
decisión y acceder a la base de datos (o a la capa de persistencia) directamente por razones de rendimiento. Sin
embargo, el arquitecto tomó esa decisión de arquitectura por una razón específica: controlar los cambios. Al
cerrar las capas, se pueden realizar cambios en la base de datos sin afectar la capa de presentación. Al no
garantizar el cumplimiento de las decisiones de arquitectura, pueden ocurrir violaciones como esta, la arquitectura
no cumplirá con las características arquitectónicas requeridas ("ilidades") y la aplicación o el sistema no
funcionará como se espera.
En el Capítulo 6 hablamos más sobre cómo medir el cumplimiento mediante funciones de aptitud automatizadas
y herramientas automatizadas.
10 | Capítulo 1: Introducción
Machine Translated by Google
Se espera que un arquitecto tenga exposición a múltiples y diversos tecnologías, marcos, plataformas
y entornos.
Esta expectativa no significa que un arquitecto deba ser un experto en todos los marcos, plataformas y lenguajes,
sino que debe estar familiarizado al menos con una variedad de tecnologías. La mayoría de los entornos actuales
son heterogéneos y, como mínimo, un arquitecto debe saber cómo interactuar con múltiples sistemas y servicios,
independientemente del lenguaje, la plataforma y la tecnología en que estén escritos esos sistemas o servicios.
Una de las mejores maneras de dominar esta expectativa es que el arquitecto amplíe su zona de
confort. Centrarse únicamente en una única tecnología o plataforma es una opción segura. Un
arquitecto de software eficaz debe buscar activamente oportunidades para adquirir experiencia en
múltiples lenguajes, plataformas y tecnologías. Una buena manera de dominar esta expectativa es
centrarse en la amplitud técnica en lugar de en la profundidad técnica.
La amplitud técnica incluye lo que sabes, pero no a un nivel detallado, combinado con lo que sabes
mucho. Por ejemplo, es mucho más valioso para un arquitecto estar familiarizado con 10 productos
de almacenamiento en caché diferentes y las ventajas y desventajas asociadas a cada uno, en lugar
de ser un experto en solo uno de ellos.
Los arquitectos de software eficaces no solo comprenden la tecnología, sino también el ámbito
empresarial de un problema. Sin conocimientos del ámbito empresarial, es difícil comprender el
problema, los objetivos y los requisitos empresariales, lo que dificulta el diseño de una arquitectura
eficaz que cumpla con los requisitos del negocio. Imagine ser un arquitecto en una gran institución
financiera y no comprender términos financieros comunes, como un índice direccional promedio,
contratos aleatorios, repunte de las tasas o incluso deuda no prioritaria. Sin este conocimiento, un
arquitecto no puede comunicarse con las partes interesadas y los usuarios empresariales y perderá
credibilidad rápidamente.
Los arquitectos más exitosos que conocemos son aquellos que tienen un amplio conocimiento técnico
práctico junto con un sólido conocimiento de un dominio en particular. Estos arquitectos de software
pueden comunicarse de manera efectiva con ejecutivos de alto nivel y usuarios comerciales utilizando
el conocimiento del dominio y el lenguaje que estas partes interesadas conocen y entienden. Esto, a
su vez, crea un alto nivel de confianza en que el arquitecto de software sabe lo que está haciendo y
es competente para crear una arquitectura efectiva y correcta.
Expectativas de un arquitecto | 11
Machine Translated by Google
Para la mayoría de los desarrolladores y arquitectos es difícil esperar que tengan habilidades de
liderazgo e interpersonales excepcionales. Como tecnólogos, a los desarrolladores y arquitectos les
gusta resolver problemas técnicos, no problemas humanos. Sin embargo, como dice Gerald Weinberg
Fue famoso por decir que “no importa lo que te digan, siempre es un problema de personas”. No solo
se espera que un arquitecto proporcione orientación técnica al equipo, sino que también se espera que
lidere a los equipos de desarrollo a través de la implementación de la arquitectura. Las habilidades de
liderazgo son al menos la mitad de lo que se necesita para convertirse en un arquitecto de software
eficaz, independientemente del rol o el título que tenga el arquitecto.
La industria está inundada de arquitectos de software, todos compitiendo por un número limitado de
puestos de arquitectura. Tener fuertes habilidades de liderazgo e interpersonales es una buena manera
para que un arquitecto se diferencie de otros arquitectos y destaque entre la multitud. Hemos conocido
a muchos arquitectos de software que son excelentes tecnólogos pero que son arquitectos ineficaces
debido a la incapacidad de liderar equipos, entrenar y orientar a los desarrolladores y comunicar ideas
y principios de arquitectura de manera efectiva. No hace falta decir que esos arquitectos tienen
dificultades para mantener un puesto o trabajo.
Puede parecer un poco extraño hablar de negociación y de cómo manejarse en la política de oficina
en un libro sobre arquitectura de software. Para ilustrar cuán importantes y necesarias son las
habilidades de negociación, considere el escenario en el que un desarrollador toma la decisión de
aprovechar el patrón de estrategia para reducir la complejidad ciclomática general de un fragmento
particular de código complejo. ¿A quién le importa realmente? Uno podría aplaudir al desarrollador
por usar ese patrón, pero en casi todos los casos el desarrollador no necesita buscar aprobación para
tal decisión.
12 | Capítulo 1: Introducción
Machine Translated by Google
datos de gestión. Si esas aplicaciones ya no pueden acceder directamente a la base de datos, ahora deben
solicitar los datos al sistema CRM, lo que requiere llamadas de acceso remoto a través de REST, SOAP o
algún otro protocolo de acceso remoto.
El punto principal es que casi todas las decisiones que toma un arquitecto serán cuestionadas.
Las decisiones arquitectónicas serán cuestionadas por los propietarios de productos, gerentes de proyectos
y partes interesadas comerciales debido al aumento de los costos o el mayor esfuerzo (tiempo) involucrado.
Las decisiones arquitectónicas también se verán cuestionadas por los desarrolladores que sienten que su
enfoque es mejor. En cualquier caso, el arquitecto debe navegar por la política de la empresa y aplicar
habilidades básicas de negociación para lograr que se aprueben la mayoría de las decisiones. Este hecho
puede ser muy frustrante para un arquitecto de software, porque la mayoría de las decisiones tomadas
como desarrollador no requirieron aprobación o incluso una revisión. Los aspectos de programación como
la estructura del código, el diseño de clases, la selección de patrones de diseño y, a veces, incluso la
elección del lenguaje son parte del arte de la programación. Sin embargo, un arquitecto, ahora capaz de
tomar decisiones amplias e importantes, debe justificar y luchar por casi todas esas decisiones. Las
habilidades de negociación, como las habilidades de liderazgo, son tan críticas y necesarias que hemos
dedicado un capítulo entero en el libro a comprenderlas (ver Capítulo 23).
Intersección de Arquitectura y…
El alcance de la arquitectura de software ha crecido durante la última década para abarcar cada vez más
responsabilidad y perspectiva. Hace una década, la relación típica entre la arquitectura y las operaciones
era contractual y formal, con mucha burocracia. La mayoría de las empresas, tratando de evitar la
complejidad de albergar sus propias operaciones, con frecuencia subcontrataban las operaciones a una
empresa de terceros, con obligaciones contractuales para acuerdos de nivel de servicio, como tiempo de
actividad, escala, capacidad de respuesta y una serie de otras características arquitectónicas importantes.
Ahora, arquitecturas como los microservicios aprovechan libremente las preocupaciones que antes eran
exclusivamente operativas. Por ejemplo, la escala elástica alguna vez se integró con dificultad en las
arquitecturas (consulte el Capítulo 15), mientras que los microservicios la manejaban con menos dificultad
a través de un enlace entre arquitectos y DevOps.
del desarrollo de software contiene lecciones valiosas, tanto buenas como malas. Suponemos que
las capacidades actuales (como la escala elástica) aparecieron un día gracias a algún desarrollador
inteligente, pero esas ideas a menudo nacieron de lecciones difíciles. Pets.com representa un
ejemplo temprano de lecciones difíciles aprendidas. Pets.com apareció en los primeros días de
Internet, con la esperanza de convertirse en el Amazon.com de los suministros para mascotas.
Afortunadamente, tenían un departamento de marketing brillante, que inventó una mascota
convincente: un títere de calcetín con un micrófono que decía cosas irreverentes. La mascota se
convirtió en una superestrella, apareciendo en público en desfiles y eventos deportivos nacionales.
Intersección de la arquitectura y… | 13
Machine Translated by Google
Lo que la empresa necesitaba era una escala elástica: la capacidad de poner en marcha más instancias de
recursos, según fuera necesario. Los proveedores de servicios en la nube ofrecen esta característica como
un producto básico, pero en los primeros tiempos de Internet, las empresas tenían que gestionar su propia
infraestructura y muchas fueron víctimas de un fenómeno inédito hasta entonces: demasiado éxito puede
acabar con el negocio. Pets.com y otras historias de terror similares llevaron a los ingenieros a desarrollar
los marcos de trabajo que hoy disfrutan los arquitectos.
Las siguientes secciones profundizan en algunas de las intersecciones más recientes entre el rol del
arquitecto y otras partes de una organización, destacando nuevas capacidades y responsabilidades
de los arquitectos.
Prácticas de ingeniería
Tradicionalmente, la arquitectura de software estaba separada del proceso de desarrollo utilizado para
crear software. Existen docenas de metodologías populares para crear software, incluidas Waterfall y
muchas variantes de Agile (como Scrum, Extreme Programming, Lean y Crystal), que en su mayoría
no afectan la arquitectura de software.
Sin embargo, en los últimos años, los avances de la ingeniería han hecho que las preocupaciones
sobre los procesos se centren en la arquitectura de software. Es útil separar el proceso de desarrollo
de software de las prácticas de ingeniería. Por proceso, nos referimos a cómo se forman y gestionan
los equipos, cómo se llevan a cabo las reuniones y la organización del flujo de trabajo; se refiere a la
mecánica de cómo las personas se organizan e interactúan. Las prácticas de ingeniería de software,
por otro lado, se refieren a prácticas independientes de los procesos que han demostrado un beneficio
repetible. Por ejemplo, la integración continua es una práctica de ingeniería probada que no depende
de un proceso en particular.
Extrema (XP) Los ejemplos ilustran muy bien la diferencia entre proceso e ingeniería. A principios de los
años 90, un grupo de desarrolladores de software experimentados, liderados por Kent Beck, comenzaron a
cuestionar las docenas de procesos de desarrollo diferentes que eran populares en ese momento. Según
su experiencia, parecía que ninguno de ellos creaba resultados buenos de manera repetible. Uno de los
fundadores de XP dijo que elegir uno de los procesos existentes “no era más garantía de éxito del proyecto
que lanzar una moneda al aire”.
Decidieron repensar cómo crear software y comenzaron el proyecto XP en marzo de 1996. Para orientar su
proceso, rechazaron la sabiduría convencional y
14 | Capítulo 1: Introducción
Machine Translated by Google
centrado en las prácticas que llevaron al éxito del proyecto en el pasado, llevadas al extremo.
Su razonamiento fue que habían visto una correlación en proyectos anteriores entre más pruebas y
mayor calidad. Por lo tanto, el enfoque XP para las pruebas llevó la práctica al extremo: realizar un
desarrollo que primero pruebe, asegurándose de que todo el código se pruebe antes de ingresar a la
base de código.
XP se agrupaba con otros procesos Agile populares que compartían perspectivas similares,
pero era una de las pocas metodologías que incluía prácticas de ingeniería como
automatización, pruebas, integración continua y otras técnicas concretas basadas en la
experiencia. Los esfuerzos por seguir avanzando en el aspecto de ingeniería del desarrollo de
software continuaron con el libro Continuous Delivery (AddisonWesley Professional), una
versión actualizada de muchas prácticas de XP, y dieron sus frutos en el movimiento DevOps.
En muchos sentidos, la revolución de DevOps se produjo cuando las operaciones adoptaron
prácticas de ingeniería originalmente defendidas por XP: automatización, pruebas, fuente
única de verdad declarativa y otras.
Apoyamos firmemente estos avances, que forman los pasos incrementales que eventualmente
convertirán el desarrollo de software en una disciplina de ingeniería adecuada.
Es importante centrarse en las prácticas de ingeniería. En primer lugar, el desarrollo de software carece de
muchas de las características de las disciplinas de ingeniería más maduras. Por ejemplo, los ingenieros
civiles pueden predecir cambios estructurales con mucha más precisión que aspectos igualmente
importantes de la estructura del software. En segundo lugar, uno de los talones de Aquiles del desarrollo
de software es la estimación: ¿cuánto tiempo, cuántos recursos, cuánto dinero? Parte de esta dificultad
radica en prácticas contables anticuadas que no pueden adaptarse a la naturaleza exploratoria del
desarrollo de software, pero otra parte se debe a que tradicionalmente somos malos en la estimación, al
menos en parte debido a incógnitas desconocidas.
Las incógnitas desconocidas son la némesis de los sistemas de software. Muchos proyectos comienzan
con una lista de incógnitas conocidas: cosas que los desarrolladores deben aprender sobre el dominio y la
tecnología que saben que están por venir. Sin embargo, los proyectos también son víctimas de incógnitas
desconocidas: cosas que nadie sabía que iban a surgir pero que han aparecido inesperadamente. Esta es
la razón por la que todos los esfuerzos de software de “Gran Diseño por adelantado” sufren: los arquitectos
no pueden diseñar para incógnitas desconocidas. Para citar a Mark (uno de sus autores):
Todas las arquitecturas se vuelven iterativas debido a incógnitas desconocidas, Agile simplemente
reconoce esto y lo hace antes.
Intersección de la arquitectura y… | 15
Machine Translated by Google
Por lo tanto, si bien el proceso está en su mayor parte separado de la arquitectura, un proceso
iterativo se adapta mejor a la naturaleza de la arquitectura de software. Los equipos que intentan
crear un sistema moderno, como los microservicios, utilizando un proceso anticuado como Waterfall
encontrarán una gran cantidad de fricción en un proceso anticuado que ignora la realidad de cómo se
ensambla el software.
A menudo, el arquitecto también es el líder técnico de los proyectos y, por lo tanto, determina las
prácticas de ingeniería que utiliza el equipo. Así como los arquitectos deben considerar cuidadosamente
el dominio del problema antes de elegir una arquitectura, también deben asegurarse de que el estilo
arquitectónico y las prácticas de ingeniería formen una malla simbiótica. Por ejemplo, una arquitectura
de microservicios supone el aprovisionamiento automatizado de máquinas, la prueba y la
implementación automatizadas y una serie de otras suposiciones. Intentar construir una de estas
arquitecturas con un grupo de operaciones anticuado, procesos manuales y pocas pruebas crea una
enorme fricción y desafíos para el éxito. Así como diferentes dominios de problemas se prestan a
ciertos estilos arquitectónicos, las prácticas de ingeniería tienen el mismo tipo de relación simbiótica.
La evolución del pensamiento que lleva de la Programación Extrema a la Entrega Continua continúa.
Los avances recientes en las prácticas de ingeniería permiten nuevas capacidades dentro de la
arquitectura. El libro más reciente de Neal, Building Evolutionary Architectures (O'Reilly), destaca
nuevas formas de pensar sobre la intersección de las prácticas de ingeniería y la arquitectura, lo que
permite una mejor automatización de la gobernanza arquitectónica. Si bien no resumiremos ese libro
aquí, ofrece una nueva nomenclatura importante y una forma de pensar sobre las características
arquitectónicas que impregnarán gran parte del resto de este libro. El libro de Neal cubre técnicas
para construir arquitecturas que cambian elegantemente con el tiempo. En el Capítulo 4, describimos
la arquitectura como la combinación de requisitos y preocupaciones adicionales, como se ilustra en la
Figura 17.
Figura 17. La arquitectura de un sistema de software consta tanto de los requisitos como de todas
las demás características arquitectónicas.
Como demuestra cualquier experiencia en el mundo del desarrollo de software, nada permanece
estático. Por lo tanto, los arquitectos pueden diseñar un sistema para cumplir con ciertos criterios,
pero ese diseño debe sobrevivir tanto a la implementación (¿cómo pueden los arquitectos asegurarse
de que su diseño se implementa correctamente?) como al cambio inevitable impulsado por el
ecosistema de desarrollo de software. Lo que necesitamos es una arquitectura evolutiva.
16 | Capítulo 1: Introducción
Machine Translated by Google
Building Evolutionary Architectures introduce el concepto de usar funciones de aptitud para proteger (y
gobernar) las características arquitectónicas a medida que se producen cambios a lo largo del tiempo. El
concepto proviene de la computación evolutiva. Al diseñar un algoritmo genético, los desarrolladores
tienen una variedad de técnicas para mutar la solución, evolucionando nuevas soluciones de forma
iterativa. Al diseñar un algoritmo de este tipo para un objetivo específico, los desarrolladores deben medir
el resultado para ver si está más cerca o más lejos de una solución óptima; esa medida es una función de
aptitud. Por ejemplo, si los desarrolladores diseñaran un algoritmo genético para resolver el problema del
viajante de comercio (cuyo objetivo es la ruta más corta entre varias ciudades), la función de aptitud
analizaría la longitud de la ruta.
Building Evolutionary Architectures adopta esta idea para crear funciones de aptitud arquitectónica: una
evaluación de integridad objetiva de algunas características arquitectónicas.
Esta evaluación puede incluir una variedad de mecanismos, como métricas, pruebas unitarias, monitores
e ingeniería del caos. Por ejemplo, un arquitecto puede identificar el tiempo de carga de la página como
una característica importante de la arquitectura. Para permitir que el sistema cambie sin degradar el
rendimiento, la arquitectura crea una función de aptitud como una prueba que mide el tiempo de carga de
la página para cada página y luego ejecuta la prueba como parte de la integración continua para el
proyecto. De este modo, los arquitectos siempre conocen el estado de las partes críticas de la arquitectura
porque tienen un mecanismo de verificación en forma de funciones de aptitud para cada parte.
No entraremos en detalles sobre las funciones de aptitud aquí. Sin embargo, señalaremos oportunidades
y ejemplos del enfoque cuando corresponda. Observe la correlación entre la frecuencia con la que se
ejecutan las funciones de aptitud y la retroalimentación que brindan. Verá que la adopción de prácticas de
ingeniería ágil, como la integración continua, el aprovisionamiento automático de máquinas y prácticas
similares, facilita la creación de arquitecturas resilientes. También ilustra cómo la arquitectura se ha
entrelazado con las prácticas de ingeniería.
Operaciones/DevOps
La intersección reciente más obvia entre la arquitectura y campos relacionados se produjo con el
advenimiento de DevOps, impulsado por un replanteamiento de los axiomas arquitectónicos.
Durante muchos años, muchas empresas consideraron las operaciones como una función separada del
desarrollo de software; a menudo, subcontrataban las operaciones a otra empresa como medida de
ahorro de costos. Muchas arquitecturas diseñadas durante los años 1990 y 2000 asumieron que los
arquitectos no podían controlar las operaciones y se construyeron de manera defensiva en torno a esa
restricción (para un buen ejemplo de esto, consulte Arquitectura basada en el espacio en el Capítulo 15).
Sin embargo, hace unos años, varias empresas comenzaron a experimentar con nuevas formas de
arquitectura que combinan muchas preocupaciones operativas con la arquitectura. Por ejemplo, en
arquitecturas de estilo más antiguo, como la arquitectura SOA impulsada por ESB, la arquitectura estaba
diseñada para manejar cuestiones como la escala elástica, lo que complicaba enormemente la arquitectura
en el proceso. Básicamente, los arquitectos se vieron obligados a diseñar defensivamente en torno a las limitaciones.
Intersección de la arquitectura y… | 17
Machine Translated by Google
Las modificaciones introducidas se debieron a la medida de ahorro de costos que suponía la externalización de
las operaciones. Por lo tanto, construyeron arquitecturas que podían gestionar la escala, el rendimiento, la
elasticidad y una serie de otras capacidades internamente. El efecto secundario de ese diseño fue una
arquitectura mucho más compleja.
Los creadores del estilo de arquitectura de microservicios se dieron cuenta de que estas preocupaciones
operativas se gestionan mejor desde el área de operaciones. Al crear un vínculo entre la arquitectura y las
operaciones, los arquitectos pueden simplificar el diseño y confiar en las operaciones para las cosas que mejor
gestionan. Por lo tanto, la comprensión de una apropiación indebida de recursos condujo a una complejidad
accidental, y los arquitectos y las operaciones se unieron para crear microservicios, cuyos detalles cubrimos en
el Capítulo 17.
Proceso
Otro axioma es que la arquitectura de software es en su mayor parte ortogonal al proceso de desarrollo de
software; la forma en que se construye el software (proceso) tiene poco impacto en la arquitectura de software
(estructura). Por lo tanto, si bien el proceso de desarrollo de software que utiliza un equipo tiene cierto impacto
en la arquitectura de software (especialmente en torno a las prácticas de ingeniería), históricamente se ha
pensado que en su mayoría son independientes. La mayoría de los libros sobre arquitectura de software ignoran
el proceso de desarrollo de software y hacen suposiciones engañosas sobre cuestiones como la previsibilidad.
Sin embargo, el proceso mediante el cual los equipos desarrollan software tiene un impacto en muchas facetas
de la arquitectura de software. Por ejemplo, muchas empresas en las últimas décadas han adoptado metodologías
de desarrollo ágiles debido a la naturaleza del software. Los arquitectos en proyectos ágiles pueden asumir un
desarrollo iterativo y, por lo tanto, un ciclo de retroalimentación más rápido para las decisiones. Eso, a su vez,
les permite ser más agresivos en cuanto a la experimentación y otros conocimientos que dependen de la
retroalimentación.
Como señala la cita anterior de Mark, toda arquitectura se vuelve iterativa; es solo cuestión de tiempo. Con ese
fin, asumiremos una base de metodologías ágiles en todo momento y señalaremos las excepciones cuando
corresponda. Por ejemplo, todavía es común que muchas arquitecturas monolíticas utilicen procesos más
antiguos debido a su antigüedad, política u otros factores atenuantes no relacionados con el software.
18 | Capítulo 1: Introducción
Machine Translated by Google
Datos
Un gran porcentaje del desarrollo de aplicaciones serias incluye el almacenamiento externo de datos,
a menudo en forma de base de datos relacional (o, cada vez más, NoSQL). Sin embargo, muchos
libros sobre arquitectura de software solo tratan superficialmente este importante aspecto de la
arquitectura. El código y los datos tienen una relación simbiótica: uno no es útil sin el otro.
Los administradores de bases de datos suelen trabajar junto con arquitectos para crear arquitecturas
de datos para sistemas complejos, analizando cómo las relaciones y la reutilización afectarán a una
cartera de aplicaciones. En este libro no profundizaremos en ese nivel de detalle especializado. Al
mismo tiempo, no ignoraremos la existencia y dependencia del almacenamiento externo. En particular,
cuando hablamos de los aspectos operativos de la arquitectura y la cuántica arquitectónica (consulte
“Cuántica arquitectónica y granularidad” en la página 92), incluimos preocupaciones externas
importantes como las bases de datos.
No existe nada en un espectro claro y claro para los arquitectos de software. Cada decisión debe tener
en cuenta muchos factores opuestos.
Si un arquitecto cree que ha descubierto algo que no implica una compensación, lo más probable es que
todavía no haya identificado dicha compensación.
—Corolario 1
Definimos la arquitectura de software en términos que van más allá del andamiaje estructural,
incorporando principios, características, etc. La arquitectura es más amplia que la simple combinación
de elementos estructurales, como se refleja en nuestra Segunda Ley de la Arquitectura de Software:
Los autores descubrieron la importancia de esta perspectiva cuando intentamos conservar los
resultados de los ejercicios realizados por los estudiantes durante el taller mientras elaboraban
soluciones arquitectónicas. Debido a que los ejercicios estaban cronometrados, los únicos artefactos
que conservamos fueron los diagramas que representan la topología. En otras palabras, capturamos
cómo resolvieron el problema, pero no por qué el equipo tomó decisiones particulares. Un arquitecto
puede observar un sistema existente del que no tiene conocimiento y determinar cómo funciona la estructura del sistema.
La arquitectura funciona, pero será difícil explicar por qué se tomaron ciertas decisiones en lugar de
otras.
A lo largo del libro, destacamos por qué los arquitectos toman determinadas decisiones y hacen
concesiones. También destacamos buenas técnicas para capturar decisiones importantes en
“Registros de decisiones de arquitectura” en la página 285.
20 | Capítulo 1: Introducción
Machine Translated by Google
PARTE I
Cimientos
CAPÍTULO 2
Pensamiento arquitectónico
El pensamiento arquitectónico es mucho más que eso. Es ver las cosas con un ojo arquitectónico, o
un punto de vista arquitectónico. Hay cuatro aspectos principales de pensar como arquitecto. En
primer lugar, se trata de comprender la diferencia entre arquitectura y diseño y saber cómo colaborar
con los equipos de desarrollo para que la arquitectura funcione. En segundo lugar, se trata de tener
una amplia gama de conocimientos técnicos, manteniendo al mismo tiempo un cierto nivel de
profundidad técnica, lo que permite al arquitecto ver soluciones y posibilidades que otros no ven. En
tercer lugar, se trata de comprender, analizar y conciliar las compensaciones entre varias soluciones
y tecnologías. Por último, se trata de comprender la importancia de los impulsores comerciales y
cómo se traducen en preocupaciones arquitectónicas.
En este capítulo exploramos estos cuatro aspectos de pensar como arquitecto y ver las cosas con un
ojo arquitectónico.
Considere la Figura 21, que ilustra las responsabilidades tradicionales que tiene un arquitecto, en
comparación con las de un desarrollador. Como se muestra en el diagrama, un arquitecto es responsable de:
23
Machine Translated by Google
Se encarga de tareas como analizar los requisitos de negocio para extraer y definir las
características arquitectónicas (“ilidades”), seleccionar qué patrones y estilos de arquitectura se
ajustarían al dominio del problema y crear componentes (los bloques de construcción del sistema).
Los artefactos creados a partir de estas actividades se entregan luego al equipo de desarrollo, que
es responsable de crear diagramas de clase para cada componente, crear pantallas de interfaz de
usuario y desarrollar y probar el código fuente.
Para que la arquitectura funcione, se deben derribar las barreras físicas y virtuales que existen
entre los arquitectos y los desarrolladores, formando así una relación bidireccional sólida entre los
arquitectos y los equipos de desarrollo. El arquitecto y el desarrollador deben estar en el mismo
equipo virtual para que esto funcione, como se muestra en la Figura 22. Este modelo no solo
facilita una comunicación bidireccional sólida entre la arquitectura y el desarrollo, sino que también
permite al arquitecto brindar tutoría y entrenamiento a los desarrolladores del equipo.
A diferencia de los enfoques tradicionales en cascada para la arquitectura de software estática y rígida, la
arquitectura de los sistemas actuales cambia y evoluciona en cada iteración o fase de un proyecto. Una estrecha
colaboración entre el arquitecto y el equipo de desarrollo es esencial para el éxito de cualquier proyecto de software.
Entonces, ¿dónde termina la arquitectura y dónde comienza el diseño? No es así. Ambos son parte del círculo de
la vida dentro de un proyecto de software y siempre deben mantenerse sincronizados entre sí para tener éxito.
Amplitud técnica
El alcance de los detalles tecnológicos difiere entre los desarrolladores y los arquitectos. A diferencia de un
desarrollador, que debe tener una cantidad significativa de conocimientos técnicos para realizar su trabajo, un
arquitecto de software debe tener una cantidad significativa de conocimientos técnicos para pensar como un
arquitecto y ver las cosas desde un punto de vista arquitectónico. Esto se ilustra con la pirámide de conocimiento
que se muestra en la Figura 23, que encapsula todo el conocimiento técnico del mundo. Resulta que el tipo de
información que un tecnólogo debe valorar difiere según las etapas de su carrera.
Amplitud técnica | 25
Machine Translated by Google
Como se muestra en la Figura 23, cualquier individuo puede dividir todo su conocimiento en tres
secciones: cosas que sabe, cosas que sabe que no sabe y cosas que no sabe que no sabe.
Las cosas que sabes incluyen las tecnologías, los marcos de trabajo, los lenguajes y las herramientas
que un tecnólogo usa a diario para realizar su trabajo, como saber Java como programador de Java.
Las cosas que sabes que no sabes incluyen aquellas cosas que un tecnólogo conoce un poco o de las
que ha oído hablar, pero en las que tiene poca o ninguna experiencia. Un buen ejemplo de este nivel
de conocimiento es el lenguaje de programación Clojure. La mayoría de los tecnólogos han oído hablar
de Clojure y saben que es un lenguaje de programación basado en Lisp, pero no pueden codificar en el
lenguaje. Las cosas que no sabes que no sabes son la parte más grande del triángulo del conocimiento
e incluyen toda la serie de tecnologías, herramientas, marcos de trabajo y lenguajes que serían la
solución perfecta para un problema que un tecnólogo está tratando de resolver, pero el tecnólogo ni
siquiera sabe que esas cosas existen.
La carrera inicial de un desarrollador se centra en expandir la parte superior de la pirámide para generar experiencia
y conocimientos. Este es el enfoque ideal al principio, porque los desarrolladores necesitan más perspectiva,
conocimiento práctico y experiencia práctica. Expandir la parte superior expande incidentalmente la sección media;
a medida que los desarrolladores encuentran más tecnologías y artefactos relacionados, se suma a su stock de
cosas que saben que no saben.
En la Figura 24, la expansión de la parte superior de la pirámide es beneficiosa porque se valora la experiencia. Sin
embargo, lo que uno sabe es también lo que se debe mantener: nada es estático en el mundo del software. Si un
desarrollador se convierte en un experto en Ruby on Rails, esa experiencia no durará si ignora Ruby on Rails durante
un año o dos. Las cosas que se encuentran en la parte superior de la pirámide requieren una inversión de tiempo
para mantener la experiencia. En última instancia, el tamaño de la parte superior de la pirámide de un individuo es
su profundidad técnica.
Amplitud técnica | 27
Machine Translated by Google
Sin embargo, la naturaleza del conocimiento cambia a medida que los desarrolladores pasan a
desempeñar el papel de arquitectos. Una gran parte del valor de un arquitecto es una amplia comprensión
de la tecnología y de cómo utilizarla para resolver problemas particulares. Por ejemplo, como arquitecto,
es más beneficioso saber que existen cinco soluciones para un problema particular que tener experiencia
singular en una sola. Las partes más importantes de la pirámide para los arquitectos son las secciones
superior e intermedia; la profundidad de la sección intermedia en la sección inferior representa la amplitud
técnica de un arquitecto, como se muestra en la Figura 25.
Figura 25. Lo que una persona sabe es profundidad técnica, y cuánto sabe una persona es amplitud
técnica
Para un arquitecto, la amplitud es más importante que la profundidad. Dado que los arquitectos deben
tomar decisiones que adecuen sus capacidades a las limitaciones técnicas, es valioso tener un amplio
conocimiento de una amplia variedad de soluciones. Por lo tanto, para un arquitecto, la mejor opción es
sacrificar parte de la experiencia adquirida con esfuerzo y utilizar ese tiempo para ampliar su cartera,
como se muestra en la Figura 26. Como se ilustra en el diagrama, algunas áreas de especialización
permanecerán, probablemente en áreas tecnológicas particularmente agradables, mientras que otras se
atrofiarán de manera útil.
Nuestra pirámide de conocimiento ilustra cuán fundamentalmente diferente es el rol del arquitecto
en comparación con el de desarrollador. Los desarrolladores pasan toda su carrera perfeccionando
su experiencia, y la transición al rol de arquitecto significa un cambio en esa perspectiva, algo que
a muchas personas les resulta difícil. Esto a su vez conduce a dos disfunciones comunes: primero,
un arquitecto intenta mantener su experiencia en una amplia variedad de áreas, sin tener éxito en
ninguna de ellas y agotándose en el proceso. Segundo, se manifiesta como una experiencia
obsoleta: la sensación errónea de que su información obsoleta sigue siendo innovadora. Vemos
esto a menudo en grandes empresas donde los desarrolladores que fundaron la empresa han
pasado a roles de liderazgo pero aún toman decisiones tecnológicas utilizando criterios antiguos
(ver “AntiPatrón del Hombre de las Cavernas Congelado” en la página 30).
Los arquitectos deberían centrarse en la amplitud técnica para tener un arsenal más amplio del que
sacar flechas. Los desarrolladores que estén en transición al rol de arquitectos tal vez tengan que
cambiar la forma en que ven la adquisición de conocimientos. Equilibrar su cartera de conocimientos
en cuanto a profundidad y amplitud es algo que todo desarrollador debería considerar a lo largo de
su carrera.
Amplitud técnica | 29
Machine Translated by Google
Un antipatrón de comportamiento que se observa con frecuencia en la vida real, el antipatrón del
hombre de las cavernas congelado, describe a un arquitecto que siempre vuelve a su preocupación
irracional favorita por cada arquitectura. Por ejemplo, uno de los colegas de Neal trabajaba en un
sistema que presentaba una arquitectura centralizada. Sin embargo, cada vez que entregaban el
diseño a los arquitectos clientes, la pregunta persistente era: "¿Pero qué pasa si perdemos Italia?".
Varios años antes, un extraño problema de comunicación había impedido que la sede central se
comunicara con sus tiendas en Italia, lo que causó grandes inconvenientes. Si bien las probabilidades
de que volviera a ocurrir eran extremadamente pequeñas, los arquitectos se habían obsesionado
con esta característica arquitectónica en particular.
En general, este antipatrón se manifiesta en arquitectos que han sufrido en el pasado una mala
decisión o un suceso inesperado, lo que los vuelve especialmente cautelosos en el futuro. Si bien
la evaluación de riesgos es importante, también debe ser realista. Comprender la diferencia entre
el riesgo técnico real y el percibido es parte del proceso de aprendizaje continuo de los arquitectos.
Pensar como un arquitecto requiere superar estas ideas y experiencias del “hombre de las cavernas
congelado”, ver otras soluciones y plantear preguntas más relevantes.
Análisis de compensaciones
Pensar como arquitecto consiste en ver las ventajas y desventajas de cada solución, técnica o
de otro tipo, y analizarlas para determinar cuál es la mejor solución. Para citar a Mark (uno de
sus autores):
En arquitectura, todo es cuestión de equilibrios, por eso la famosa respuesta a todas las
preguntas sobre arquitectura del universo es “depende”. Aunque a muchas personas les molesta
cada vez más esta respuesta, lamentablemente es cierta. No se puede buscar en Google la
respuesta a si REST o la mensajería serían mejores, o si los microservicios son el estilo de
arquitectura adecuado, porque depende. Depende del entorno de implementación, los
impulsores comerciales, la cultura de la empresa, los presupuestos, los plazos, el conjunto de
habilidades de los desarrolladores y docenas de otros factores. El entorno, la situación y el
problema de cada uno son diferentes, de ahí que la arquitectura sea tan difícil. Para citar a Neal (otro de sus autore
Por ejemplo, consideremos un sistema de subasta de artículos, como se ilustra en la Figura 27, donde alguien hace
una oferta por un artículo que será subastado.
Figura 27. Ejemplo de un sistema de subasta que plantea una disyuntiva: ¿colas o temas?
El servicio Bid Producer genera una oferta del postor y luego envía el monto de la oferta a los servicios Bid
Capture, Bid Tracking y Bid Analytics . Esto se puede hacer mediante colas en un modo de mensajería punto a
punto o mediante un tema en un modo de mensajería de publicación y suscripción. ¿Cuál debería usar el
arquitecto? No se puede buscar la respuesta en Google. El pensamiento arquitectónico requiere que el arquitecto
analice las ventajas y desventajas asociadas con cada opción y seleccione la mejor dada la situación específica.
Las dos opciones de mensajería para el sistema de subasta de artículos se muestran en las Figuras 28 y 29, donde
la Figura 28 ilustra el uso de un tema en un modelo de mensajería de publicación y suscripción, y la Figura 29
ilustra el uso de colas en un modelo de mensajería punto a punto.
Análisis de compensaciones | 31
Machine Translated by Google
La clara ventaja (y la solución aparentemente obvia) para este problema en la Figura 28
es la de la extensibilidad arquitectónica. El servicio Bid Producer solo requiere una única
conexión a un tema, a diferencia de la solución de cola en la Figura 29 donde el Bid
Producer necesita conectarse a tres colas diferentes. Si se añadiera un nuevo servicio
llamado Bid History a este sistema debido al requisito de proporcionar a cada postor un
historial de todas las ofertas que realizó en cada subasta, no se necesitaría ningún cambio
en el sistema existente. Cuando se crea el nuevo servicio Bid History , simplemente podría
suscribirse al tema que ya contiene la información de la oferta. Sin embargo, en la opción
de cola que se muestra en la Figura 29, se requeriría una nueva cola para el servicio Bid
History , y el Bid Producer necesitaría ser modificado para agregar una conexión adicional
a la nueva cola. El punto aquí es que el uso de colas requiere un cambio significativo en el
sistema cuando se agrega una nueva funcionalidad de oferta, mientras que con el enfoque
de temas no se necesita ningún cambio en la infraestructura existente. Además, observe
que el productor de ofertas está más desacoplado en la opción de tema: el productor de
ofertas no sabe cómo se utilizará la información de la oferta ni qué servicios la utilizarán.
En la opción de cola, el productor de ofertas sabe exactamente cómo se utiliza la
información de la oferta (y quién la utiliza) y, por lo tanto, está más acoplado al sistema.
Con este análisis parece claro que el enfoque temático que utiliza el modelo de mensajería
de publicación y suscripción es la opción obvia y la mejor. Sin embargo, para citar a Rich
Hickey, el creador del lenguaje de programación Clojure:
Los programadores conocen los beneficios de todo y las desventajas de no hacer nada. Los arquitectos
deben comprender ambos.
Pensar arquitectónicamente es mirar los beneficios de una solución dada, pero también analizar los
aspectos negativos, o las compensaciones, asociadas con una solución. Continuando con el
ejemplo del sistema de subastas, un arquitecto de software analizaría los aspectos negativos de la
solución de temas. Al analizar las diferencias, observe primero en la Figura 28 que con un tema,
cualquiera puede acceder a los datos de licitación, lo que introduce un posible problema con el
acceso a los datos y la seguridad de los datos. En el modelo de cola ilustrado en la Figura 29, los
datos enviados a la cola solo pueden ser accedidos por el consumidor específico que recibe ese
mensaje. Si un servicio no autorizado escuchara en una cola, esas ofertas no serían recibidas por
el servicio correspondiente y se enviaría inmediatamente una notificación sobre la pérdida de datos
(y, por lo tanto, una posible violación de la seguridad). En otras palabras, es muy fácil interceptar
un tema, pero no una cola.
Además del problema de seguridad, la solución del tema en la Figura 28 solo admite contratos
homogéneos. Todos los servicios que reciben los datos de licitación deben aceptar el mismo
contrato y el mismo conjunto de datos de licitación. En la opción de cola en la Figura 29, cada
consumidor puede tener su propio contrato específico para los datos que necesita. Por ejemplo,
supongamos que el nuevo servicio Historial de ofertas requiere el precio de venta actual junto con
la oferta, pero ningún otro servicio necesita esa información. En este caso, el contrato debería
modificarse, lo que afectaría a todos los demás servicios que usan esos datos. En el modelo de
cola, este sería un canal separado, por lo tanto, un contrato separado que no afectaría a ningún otro servicio.
Otra desventaja del modelo de temas ilustrado en la Figura 28 es que no admite el monitoreo de la
cantidad de mensajes en el tema y, por lo tanto, las capacidades de escalado automático. Sin
embargo, con la opción de cola en la Figura 29, cada cola se puede monitorear individualmente y
se puede aplicar un equilibrio de carga programático a cada consumidor de ofertas para que cada
uno pueda escalarse automáticamente de manera independiente de los demás. Tenga en cuenta
que esta compensación es específica de la tecnología, ya que el Protocolo de cola de mensajes
avanzado (AMQP) Puede soportar el equilibrio de carga y el monitoreo programático debido a la
separación entre un intercambio (lo que el productor envía) y una cola (lo que el consumidor
escucha).
Dado este análisis de pros y contras, ¿cuál es ahora la mejor opción? ¿Y la respuesta? ¡Depende!
La Tabla 21 resume estas pros y contras.
Extensibilidad arquitectónica Preocupaciones sobre el acceso a los datos y la seguridad de los datos
Monitoreo y escalabilidad
programática
Análisis de compensaciones | 33
Machine Translated by Google
La cuestión aquí es que todo en la arquitectura de software tiene sus pros y sus contras: ventajas y
desventajas. Pensar como un arquitecto implica analizar estas pros y contras y luego preguntarse:
“¿Qué es más importante: la extensibilidad o la seguridad?”. La decisión entre diferentes soluciones
siempre dependerá de los factores comerciales, el entorno y una serie de otros factores.
El primer consejo para lograr un equilibrio entre la codificación práctica y ser un arquitecto de software
es evitar la trampa del cuello de botella. La trampa del cuello de botella ocurre cuando el arquitecto
ha tomado posesión del código dentro de la ruta crítica de un proyecto (generalmente el código del
marco subyacente) y se convierte en un cuello de botella para el equipo. Esto sucede porque el
arquitecto no es un desarrollador a tiempo completo y, por lo tanto, debe equilibrar su rol de
desarrollador (escribir y probar el código fuente) y su rol de arquitecto (dibujar diagramas, asistir a
reuniones y, bueno, asistir a más reuniones).
Una forma de evitar la trampa del cuello de botella como arquitecto de software eficaz es delegar la
ruta crítica y el código del marco de trabajo a otros miembros del equipo de desarrollo y luego
centrarse en codificar una parte de la funcionalidad empresarial (un servicio o una pantalla) una a tres
iteraciones más adelante. Al hacer esto, se obtienen tres cosas positivas. En primer lugar, el arquitecto
adquiere experiencia práctica escribiendo código de producción sin convertirse en un cuello de botella
para el equipo. En segundo lugar, la ruta crítica y el código del marco de trabajo se distribuyen al
equipo de desarrollo (donde pertenecen), lo que les otorga propiedad y una mejor comprensión de las
partes más difíciles del sistema. En tercer lugar, y quizás lo más importante, el arquitecto escribe el
mismo código fuente relacionado con el negocio que el equipo de desarrollo y, por lo tanto, puede
identificarse mejor con el equipo de desarrollo en
términos del dolor que podrían estar atravesando con los procesos, procedimientos y el entorno de
desarrollo.
Supongamos, sin embargo, que el arquitecto no puede desarrollar código con el equipo de desarrollo.
¿Cómo puede un arquitecto de software seguir trabajando de forma práctica y mantener cierto nivel de
profundidad técnica? Hay cuatro formas básicas en las que un arquitecto puede seguir trabajando de
forma práctica sin tener que "practicar la codificación desde casa" (aunque recomendamos practicar la
codificación en casa también).
La primera forma es realizar pruebas de concepto o POC con frecuencia. Esta práctica no solo requiere
que el arquitecto escriba el código fuente, sino que también ayuda a validar una decisión de arquitectura
al tener en cuenta los detalles de implementación. Por ejemplo, si un arquitecto está estancado
tratando de tomar una decisión entre dos soluciones de almacenamiento en caché, una forma eficaz
de ayudar a tomar esta decisión es desarrollar un ejemplo funcional en cada producto de
almacenamiento en caché y comparar los resultados. Esto permite al arquitecto ver de primera mano
los detalles de implementación y la cantidad de esfuerzo necesario para desarrollar la solución
completa. También permite al arquitecto comparar mejor las características arquitectónicas, como la
escalabilidad, el rendimiento o la tolerancia general a fallas de las diferentes soluciones de almacenamiento en caché.
Nuestro consejo a la hora de realizar trabajos de prueba de concepto es que, siempre que sea posible,
el arquitecto escriba el código de mejor calidad de producción que pueda. Recomendamos esta práctica
por dos razones. En primer lugar, con bastante frecuencia, el código de prueba de concepto descartable
va al repositorio de código fuente y se convierte en la arquitectura de referencia o el ejemplo que otros
deben seguir. Lo último que querría un arquitecto es que su código descartable y descuidado sea una
representación de su trabajo típico. La segunda razón es que al escribir código de prueba de concepto
de calidad de producción, el arquitecto adquiere práctica para escribir código de calidad y bien
estructurado en lugar de desarrollar continuamente malas prácticas de codificación.
Otra forma en la que un arquitecto puede seguir participando activamente es abordar algunas de las
historias de deuda técnica o de arquitectura, lo que libera al equipo de desarrollo para que trabaje en
las historias de usuario funcionales críticas. Estas historias suelen tener una prioridad baja, por lo que
si el arquitecto no tiene la oportunidad de completar una historia de deuda técnica o de arquitectura
dentro de una iteración determinada, no es el fin del mundo y, por lo general, no afecta el éxito de la
iteración.
De manera similar, trabajar en la corrección de errores dentro de una iteración es otra forma de
mantener la codificación activa y, al mismo tiempo, ayudar al equipo de desarrollo. Si bien no es una
técnica glamorosa, permite al arquitecto identificar dónde pueden estar los problemas y las debilidades
dentro de la base de código y, posiblemente, de la arquitectura.
El equipo de desarrollo agradecerá la automatización. Algunos ejemplos son los validadores de código fuente
automatizados para ayudar a verificar estándares de codificación específicos que no se encuentran en otras
pruebas de lint, listas de verificación automatizadas y tareas repetitivas de refactorización de código manual.
La automatización también puede adoptar la forma de análisis arquitectónico y funciones de adecuación para
garantizar la vitalidad y el cumplimiento de la arquitectura. Por ejemplo, un arquitecto puede escribir código Java
en ArchUnit en la plataforma Java para automatizar el cumplimiento arquitectónico o escribir funciones de aptitud
personalizadas para garantizar el cumplimiento arquitectónico y, al mismo tiempo, adquirir experiencia práctica.
Hablamos de estas técnicas en el Capítulo 6.
Una última técnica para seguir siendo activo como arquitecto es realizar revisiones de código frecuentes.
Si bien el arquitecto no escribe el código, al menos participa en el código fuente. Además, realizar revisiones de
código tiene el beneficio adicional de poder garantizar el cumplimiento de la arquitectura y buscar oportunidades
de tutoría y entrenamiento en el equipo.
CAPÍTULO 3
Modularidad
En primer lugar, queremos desenredar algunos términos comunes utilizados y sobreutilizados en las
discusiones sobre la arquitectura en torno a la modularidad y proporcionar definiciones para su uso a
lo largo del libro.
Distintas plataformas ofrecen distintos mecanismos de reutilización de código, pero todas admiten
alguna forma de agrupar código relacionado en módulos. Si bien este concepto es universal en la
arquitectura de software, ha resultado complicado definirlo. Una búsqueda casual en Internet arroja
docenas de definiciones, sin coherencia (y con algunas contradicciones). Como puede ver en la cita
de Myers, este no es un problema nuevo. Sin embargo, dado que no existe una definición reconocida,
debemos lanzarnos a la palestra y proporcionar nuestras propias definiciones en aras de la coherencia
en todo el libro.
37
Machine Translated by Google
Preservar una buena modularidad ejemplifica nuestra definición de una característica implícita de la
arquitectura: prácticamente ningún proyecto presenta un requisito que pida al arquitecto garantizar una buena
distinción y comunicación modular, pero las bases de código sostenibles requieren orden y consistencia.
Definición
El diccionario define módulo como “cada una de las partes estandarizadas o unidades independientes que
se pueden usar para construir una estructura más compleja”. Usamos modularidad para describir una
agrupación lógica de código relacionado, que podría ser un grupo de clases en un lenguaje orientado a
objetos o funciones en un lenguaje estructurado o funcional. La mayoría de los lenguajes proporcionan
mecanismos para la modularidad (paquete en Java, espacio de nombres en .NET, etc.). Los desarrolladores
suelen usar módulos como una forma de agrupar código relacionado.
Por ejemplo, el paquete com.mycompany.customer en Java debería contener cosas relacionadas
con los clientes.
Los lenguajes actuales cuentan con una amplia variedad de mecanismos de empaquetado, lo que dificulta la
tarea del desarrollador de elegir entre ellos. Por ejemplo, en muchos lenguajes modernos, los desarrolladores
pueden definir el comportamiento en funciones/métodos, clases o paquetes/espacios de nombres, cada uno
con diferentes reglas de visibilidad y alcance. Otros lenguajes complican esto aún más al agregar
construcciones de programación como el protocolo de metaobjetos. para proporcionar a los desarrolladores
aún más mecanismos de extensión.
Los arquitectos deben ser conscientes de cómo los desarrolladores empaquetan las cosas porque esto tiene
implicaciones importantes en la arquitectura. Por ejemplo, si varios paquetes están estrechamente acoplados
entre sí, la reutilización de uno de ellos para un trabajo relacionado se vuelve más difícil.
Los desarrolladores que son anteriores a los lenguajes orientados a objetos pueden preguntarse por qué
existen tantos esquemas de separación diferentes. Gran parte de la razón tiene que ver con la
compatibilidad con versiones anteriores, no con el código, sino con la forma en que los desarrolladores
piensan sobre las cosas. En marzo de 1968, Edsger Dijkstra publicó una carta en las Comunicaciones de
la ACM titulada “La declaración Go To se considera dañina”. Denigró el uso común de la declaración
GOTO , común en los lenguajes de programación de la época, que permitía saltos no lineales dentro del
código, lo que dificultaba el razonamiento y la depuración.
Este artículo ayudó a marcar el comienzo de la era de los lenguajes de programación estructurados,
ejemplificados por Pascal y C, que alentaron una reflexión más profunda sobre cómo encajan las cosas.
Los desarrolladores se dieron cuenta rápidamente de que la mayoría de los lenguajes no tenían una buena
manera de agrupar cosas similares de forma lógica. Así nació la breve era de los lenguajes modulares,
como Modula (el siguiente lenguaje del creador de Pascal, Niklaus Wirth) y Ada. Estos lenguajes tenían la
estructura de programación de un módulo, de forma muy similar a como hoy en día pensamos en los
paquetes o espacios de nombres (pero sin las clases).
38 | Capítulo 3: Modularidad
Machine Translated by Google
La era de la programación modular duró poco. Los lenguajes orientados a objetos se hicieron populares
porque ofrecían nuevas formas de encapsular y reutilizar el código. Aun así, los diseñadores de lenguajes
se dieron cuenta de la utilidad de los módulos y los mantuvieron en forma de paquetes, espacios de
nombres, etc. Existen muchas características de compatibilidad extrañas en los lenguajes que admiten
estos diferentes paradigmas. Por ejemplo, Java admite paradigmas modulares (a través de paquetes e
inicialización a nivel de paquete mediante inicializadores estáticos), orientados a objetos y funcionales,
cada estilo de programación con sus propias reglas de alcance y peculiaridades.
En las discusiones sobre arquitectura, utilizamos modularidad como un término general para
denotar una agrupación relacionada de código: clases, funciones o cualquier otra agrupación.
Esto no implica una separación física, sino simplemente una separación lógica; la diferencia a
veces es importante. Por ejemplo, agrupar una gran cantidad de clases en una aplicación
monolítica puede tener sentido desde el punto de vista de la conveniencia. Sin embargo, cuando
llega el momento de reestructurar la arquitectura, el acoplamiento fomentado por la partición
flexible se convierte en un impedimento para romper el monolito. Por lo tanto, es útil hablar de
modularidad como un concepto separado de la separación física forzada o implícita por una
plataforma particular.
originales de Java tenían una amplia experiencia en el manejo de conflictos y choques de nombres en
las diversas plataformas de programación de la época. El diseño original de Java utilizó un truco
inteligente para evitar la posibilidad de ambigüedad entre dos clases que tenían el mismo nombre. Por
ejemplo, ¿qué sucedería si el dominio de su problema incluyera un orden de catálogo y un orden de
instalación: ambos órdenes nombrados pero con connotaciones (y clases) muy diferentes? La solución
en Java fue crear el mecanismo de espacio de nombres de paquetes , junto con el requisito de que la
estructura física del directorio coincidiera simplemente con el nombre del paquete. Debido a que los
sistemas de archivos no permiten que el mismo archivo nombrado resida en el mismo directorio,
aprovecharon las características inherentes del sistema operativo para evitar la posibilidad de
ambigüedad. Por lo tanto, la ruta de clases original en Java contenía solo directorios, lo que impedía la
posibilidad de conflictos de nombres.
Definición | 39
Machine Translated by Google
Sin embargo, como descubrieron los diseñadores del lenguaje, forzar a que cada proyecto tuviera una estructura de
directorio completamente formada era engorroso, especialmente a medida que los proyectos se hacían más grandes.
Además, crear activos reutilizables era difícil: los marcos y las bibliotecas deben "explotarse" en la estructura de
directorios. En la segunda versión principal de Java (1.2, llamada Java 2), los diseñadores agregaron el mecanismo
jar , lo que permite que un archivo de almacenamiento actúe como una estructura de directorios en una ruta de
clases. Durante la década siguiente, los desarrolladores de Java lucharon por lograr que la ruta de clases fuera
exactamente la correcta, como una combinación de directorios y archivos JAR. Y, por supuesto, la intención original
se rompió: ahora dos archivos JAR podían crear nombres conflictivos en una ruta de clases, lo que dio lugar a
numerosas historias de guerra sobre la depuración de cargadores de clases.
Medición de la modularidad
Dada la importancia de la modularidad para los arquitectos, necesitan herramientas para comprenderla.
Afortunadamente, los investigadores crearon una variedad de métricas independientes del lenguaje para ayudar a los
arquitectos a comprender la modularidad. Nos centramos en tres conceptos clave: cohesión, acoplamiento y
conocimiento.
Cohesión
La cohesión se refiere al grado en que las partes de un módulo deben estar contenidas dentro del mismo módulo. En
otras palabras, es una medida de cuán relacionadas están las partes entre sí. Idealmente, un módulo cohesivo es aquel
en el que todas las partes deben estar empaquetadas juntas, porque dividirlas en partes más pequeñas requeriría acoplar
las partes mediante llamadas entre módulos para lograr resultados útiles.
Intentar dividir un módulo cohesivo sólo daría como resultado un mayor acoplamiento y
una menor legibilidad.
—Larry Constantine
Los científicos informáticos han definido una serie de medidas de cohesión, que se enumeran aquí a partir de las mejores
Para peor:
parte del módulo está relacionada con las demás y el módulo contiene todo lo esencial para funcionar.
Cohesión comunicacional
Dos módulos forman una cadena de comunicación, donde cada uno opera sobre información y/o contribuye a algún
resultado. Por ejemplo, agregar un registro a la base de datos y generar un correo electrónico en función de esa
información.
40 | Capítulo 3: Modularidad
Machine Translated by Google
Cohesión procedimental
Cohesión temporal
Los módulos se relacionan en función de las dependencias temporales. Por ejemplo, muchos sistemas
tienen una lista de cosas aparentemente no relacionadas que deben inicializarse al iniciar el sistema;
estas diferentes tareas son cohesivas temporalmente.
Cohesión casual
Los elementos de un módulo no están relacionados más allá de estar en el mismo archivo fuente; esto
representa la forma más negativa de cohesión.
A pesar de tener siete variantes enumeradas, la cohesión es una métrica menos precisa que el acoplamiento.
A menudo, el grado de cohesión de un módulo en particular queda a criterio de un arquitecto en particular.
Por ejemplo, considere esta definición de módulo:
Mantenimiento de clientes
• añadir cliente
• actualizar al cliente
• conseguir clientes
• notificar al cliente
¿Las dos últimas entradas deben residir en este módulo o el desarrollador debe crear dos módulos separados,
como por ejemplo:
Mantenimiento de clientes
• añadir cliente
• actualizar al cliente
• conseguir clientes
• notificar al cliente
Medición de la modularidad | 41
Machine Translated by Google
Mantenimiento de pedidos
• ¿Son esas las únicas dos operaciones para el mantenimiento de pedidos? Si es así, puede que tenga
sentido volver a agruparlas en el mantenimiento de clientes.
• ¿Se espera que el Mantenimiento del Cliente crezca mucho más, alentando a los desarrolladores?
¿Buscar oportunidades para extraer comportamiento?
Estas preguntas representan el tipo de análisis de compensaciones que está en el centro del trabajo de un
arquitecto de software.
La métrica de falta de cohesión en los métodos (LCOM) de Chidamber y Kemerer mide la cohesión
estructural de un módulo, normalmente un componente. La versión inicial aparece en la ecuación 31.
P − Q , de Si P > Q
LCOM =
0, lo contrario
P aumenta en uno para cualquier método que no acceda a un campo compartido en particular y Q
disminuye en uno para los métodos que sí comparten un campo compartido en particular. Los autores
simpatizan con aquellos que no entienden esta formulación. Peor aún, se ha vuelto gradualmente más
elaborada con el tiempo. La segunda variación introducida en 1996 (de ahí el nombre LCOM96B)
aparece en la ecuación 32.
42 | Capítulo 3: Modularidad
Machine Translated by Google
a
1 m − μAj
LCOM96b =
a j =∑1 metro
No nos molestaremos en desenredar las variables y operadores de la ecuación 32 porque la siguiente
explicación escrita es más clara. Básicamente, la métrica LCOM expone el acoplamiento incidental dentro
de las clases. Aquí hay una mejor definición de LCOM:
LCOM
La suma de conjuntos de métodos no compartidos a través de campos compartidos
Considere una clase con campos privados a y b. Muchos de los métodos solo acceden a a, y muchos
otros métodos solo acceden a b. La suma de los conjuntos de métodos no compartidos a través de campos
compartidos (a y b) es alta; por lo tanto, esta clase informa un puntaje LCOM alto, lo que indica que tiene
un puntaje alto en falta de cohesión en los métodos. Considere las tres clases que se muestran en la
Figura 31.
Figura 31. Ilustración de la métrica LCOM, donde los campos son octágonos y los métodos son
cuadrados
En la Figura 31, los campos aparecen como letras individuales y los métodos aparecen como bloques. En
la Clase X, la puntuación LCOM es baja, lo que indica una buena cohesión estructural. Sin embargo, la
Clase Y carece de cohesión; cada uno de los pares de campo/método en la Clase Y podría aparecer en
su propia clase sin afectar el comportamiento. La Clase Z muestra una cohesión mixta, donde los
desarrolladores podrían refactorizar la última combinación de campo/método en su propia clase.
Medición de la modularidad | 43
Machine Translated by Google
La métrica LCOM es útil para los arquitectos que analizan bases de código para pasar de un estilo
arquitectónico a otro. Uno de los dolores de cabeza más comunes al trasladar arquitecturas son las clases
de utilidad compartidas. El uso de la métrica LCOM puede ayudar a los arquitectos a encontrar clases
que están acopladas de manera incidental y que nunca deberían haber sido una sola clase desde el
principio.
Muchas métricas de software tienen deficiencias graves y LCOM no es inmune a ellas. Todo lo que esta
métrica puede detectar es una falta de cohesión estructural; no tiene forma de determinar de manera
lógica si las piezas particulares encajan entre sí. Esto refleja nuestra Segunda Ley de la Arquitectura de
Software: es mejor el por qué que el cómo.
Acoplamiento
¿Por qué dos métricas críticas en el mundo de la arquitectura que representan conceptos
opuestos se denominan prácticamente de la misma manera y difieren solo en las vocales que
suenan más parecidas? Estos términos se originaron en el Diseño Estructurado de Yourdon y
Constantine. Tomando prestados conceptos de las matemáticas, acuñaron los términos de
acoplamiento aferente y eferente, ahora comunes, que deberían haberse llamado acoplamiento entrante y saliente.
Sin embargo, debido a que los autores originales se inclinaron por la simetría matemática en
lugar de la claridad, los desarrolladores idearon varios mnemónicos para ayudar: a aparece antes
de e en el alfabeto inglés, lo que corresponde a que entrante esté antes de saliente, o la
observación de que la letra e en eferente coincide con la letra inicial en salida, lo que corresponde
a conexiones salientes.
acoplamiento de componentes tiene valor para los arquitectos, varias otras métricas derivadas permiten
una evaluación más profunda. Estas métricas fueron creadas por Robert Martin para un libro de C++,
pero son ampliamente aplicables a otros lenguajes orientados a objetos.
44 | Capítulo 3: Modularidad
Machine Translated by Google
a
∑m
A=
do
∑m
a
En la ecuación, m es representa elementos abstractos (interfaces o clases abstractas) con
el módulo y m representa elementos concretos (clases no abstractas). Esta métrica busca los mismos
do
criterios. La forma más sencilla de visualizar esta métrica: considere una aplicación con 5000 líneas
de código, todas en un método main() . El numerador de abstracción es 1, mientras que el
denominador es 5000, lo que arroja una abstracción de casi 0. Por lo tanto, esta métrica mide la
proporción de abstracciones en su código.
Los arquitectos calculan la abstracción calculando la relación entre la suma de los artefactos
abstractos y la suma de los concretos.
Otra métrica derivada, la inestabilidad, se define como la relación entre el acoplamiento eferente y la
suma del acoplamiento eferente y aferente, que se muestra en la ecuación 34.
y a
En la ecuación, c representa el acoplamiento eferente (o saliente), y c representa a las víctimas
La métrica de inestabilidad determina la volatilidad de una base de código. Una base de código que
exhibe altos grados de inestabilidad se rompe más fácilmente cuando se modifica debido al alto
acoplamiento. Por ejemplo, si una clase llama a muchas otras clases para delegar trabajo, la clase
que llama muestra una alta susceptibilidad a romperse si uno o más de los métodos llamados
cambian.
Medición de la modularidad | 45
Machine Translated by Google
desde la secuencia principal, una métrica derivada basada en la inestabilidad y la abstracción, que se muestra
en la ecuación 35.
D=A+I1
Nótese que tanto la abstracción como la inestabilidad son fracciones cuyos resultados siempre
estarán entre 0 y 1 (excepto en casos extremos de abstracción que no serían prácticos).
Así, al graficar la relación, vemos el gráfico de la Figura 32.
Figura 32. La secuencia principal define la relación ideal entre abstracción e inestabilidad.
La métrica de distancia imagina una relación ideal entre abstracción e inestabilidad; las clases
que se encuentran cerca de esta línea idealizada exhiben una combinación saludable de estas
dos preocupaciones en pugna. Por ejemplo, graficar una clase particular permite a los
desarrolladores calcular la distancia desde la métrica de secuencia principal, ilustrada en la Figura 33.
46 | Capítulo 3: Modularidad
Machine Translated by Google
Figura 33. Distancia normalizada desde la secuencia principal para una clase particular
En la Figura 33, los desarrolladores grafican la clase candidata y luego miden la distancia desde la
línea idealizada. Cuanto más cerca de la línea, mejor equilibrada está la clase. Las clases que caen
demasiado en la esquina superior derecha entran en lo que los arquitectos llaman la zona de
inutilidad: el código que es demasiado abstracto se vuelve difícil de usar. Por el contrario, el código
que cae en la esquina inferior izquierda entra en la zona de dolor: el código con demasiada
implementación y no suficiente abstracción se vuelve frágil y difícil de mantener, como se ilustra en
la Figura 34.
Medición de la modularidad | 47
Machine Translated by Google
Existen herramientas en muchas plataformas para proporcionar estas medidas, que ayudan a los
arquitectos a analizar bases de código debido a la falta de familiaridad, la migración o la deuda técnica.
evaluación.
Si bien la industria cuenta con algunas métricas a nivel de código que brindan información valiosa sobre
las bases de código, nuestras herramientas son extremadamente contundentes en comparación con
las herramientas de análisis de otras disciplinas de ingeniería. Incluso las métricas derivadas
directamente de la estructura del código requieren interpretación. Por ejemplo, la complejidad ciclomática
(consulte “Complejidad ciclomática” en la página 79) mide la complejidad en las bases de código, pero
no puede distinguirla de la complejidad esencial (porque el problema subyacente es complejo) o la
complejidad accidental (el código es más complejo de lo que debería ser). Prácticamente todas las
métricas a nivel de código requieren interpretación, pero sigue siendo útil establecer líneas de base
para métricas críticas como la complejidad ciclomática para que los arquitectos puedan evaluar qué tipo
exhiben. Analizamos la configuración de dichas pruebas en “Funciones de gobernanza y aptitud” en la página 82.
Obsérvese que el libro mencionado anteriormente de Edward Yourdon y Larry Constantine (Structured
Design: Fundamentals of a Discipline of Computer Program and Systems Design) es anterior a la
popularidad de los lenguajes orientados a objetos, centrándose en cambio en construcciones de
programación estructurada, como funciones (no métodos). También definió otros tipos de acoplamiento
que no cubrimos aquí porque han sido reemplazados por la connascencia.
Conocimiento
En 1996, Meilir PageJones publicó What Every Programmer Should Know About ObjectOriented
Design (Dorset House), donde perfeccionó las métricas de acoplamiento aferente y eferente y las
reformuló para lenguajes orientados a objetos con un concepto que denominó connascence
(concepción). Así es como definió el término:
Connascencia estática
48 | Capítulo 3: Modularidad
Machine Translated by Google
Los nombres de métodos representan la forma más común en que se acoplan las bases de código y la más
deseable, especialmente a la luz de las herramientas de refactorización modernas que hacen que los cambios
de nombres en todo el sistema sean triviales.
Este tipo de connascencia se refiere a la facilidad común en muchos lenguajes de tipado estático de limitar
las variables y parámetros a tipos específicos. Sin embargo, esta capacidad no es puramente una
característica del lenguaje: algunos lenguajes de tipado dinámico ofrecen tipado selectivo, en particular
Clojure. y especificación Clojure.
Connascence of Meaning (CoM) o Connascence of Convention (CoC) (Connascence of Meaning) o Connascence of Convention (CoC) (Connascence of Convention) (Connascence of Meaning) (Connascence of Convention ...
El caso más común y obvio de este tipo de connascencia en las bases de código son los números codificados
de forma rígida en lugar de las constantes. Por ejemplo, en algunos lenguajes es común considerar la
posibilidad de definir en algún lugar int TRUE = 1; int FALSE = 0.
Imagínense los problemas si alguien invierte esos valores.
Este es un problema con los valores de los parámetros para las llamadas a métodos y funciones, incluso en
lenguajes que cuentan con tipado estático. Por ejemplo, si un desarrollador crea un método void
updateSeat(String name, String seatLocation) y lo llama con los valores updateSeat("14D", "Ford, N"), la
semántica no es correcta, incluso si los tipos lo son.
Un caso común de este tipo de conexión ocurre cuando un desarrollador define un algoritmo de hash de
seguridad que debe ejecutarse tanto en el servidor como en el cliente y producir resultados idénticos para
autenticar al usuario. Obviamente, esto representa una forma alta de acoplamiento: si alguno de los algoritmos
cambia algún detalle, el protocolo de enlace ya no funcionará.
Medición de la modularidad | 49
Machine Translated by Google
Connascence dinámico
El otro tipo de connascence que PageJones definió fue el connascence dinámico, que analiza las
llamadas en tiempo de ejecución. A continuación se presenta una descripción de los diferentes tipos
de connascence dinámico:
El caso común de este tipo de conexión es una condición de carrera causada por dos subprocesos
que se ejecutan al mismo tiempo, lo que afecta el resultado de la operación conjunta.
Consideremos el caso en el que un desarrollador ha definido un rectángulo con cuatro puntos, que
representan las esquinas. Para mantener la integridad de la estructura de datos, el desarrollador no
puede cambiar aleatoriamente uno de los puntos sin considerar el impacto en los demás puntos.
El ejemplo común de este tipo de conexión involucra dos componentes independientes que deben
compartir y actualizar una estructura de datos común, como una cola distribuida.
A los arquitectos les resulta más difícil determinar la conexión dinámica porque carecemos de herramientas para
analizar las llamadas en tiempo de ejecución con tanta eficacia como podemos analizar el gráfico de llamadas.
50 | Capítulo 3: Modularidad
Machine Translated by Google
Propiedades de Connascence
Connascence es una herramienta de análisis para arquitectos y desarrolladores, y algunas propiedades de Connascence
ayudan a los desarrolladores a utilizarla de forma inteligente. A continuación, se incluye una descripción de cada una
de estas propiedades de Connascence:
Los
arquitectos determinan la fuerza de la connascencia según la facilidad con la que un desarrollador
puede refactorizar ese tipo de acoplamiento; se ha demostrado que distintos tipos de connascencia
son más deseables, como se muestra en la Figura 35. Los arquitectos y desarrolladores pueden
mejorar las características de acoplamiento de su base de código mediante la refactorización hacia
mejores tipos de connascencia.
Los arquitectos deberían preferir la connascencia estática a la dinámica porque los desarrolladores
pueden determinarla mediante un simple análisis del código fuente y las herramientas modernas
hacen que sea trivial mejorar la connascencia estática. Por ejemplo, considere el caso de la
connascencia de significado, que los desarrolladores pueden mejorar refactorizando a la
connascencia de nombre creando una constante nombrada en lugar de un valor mágico.
Localidad
La localidad de connascencia mide qué tan próximos están los módulos entre sí en la base de
código. El código proximal (en el mismo módulo) normalmente tiene más y mayores formas de
connascencia que el código más separado (en módulos o bases de código separados). En otras
palabras, formas de connascencia que indican un acoplamiento deficiente
Medición de la modularidad | 51
Machine Translated by Google
Cuando están muy separados, están bien cuando están más juntos. Por ejemplo, si dos clases en el
mismo componente tienen connascencia de significado, es menos dañino para la base de código que
si dos componentes tienen la misma forma de connascencia.
Los desarrolladores deben considerar la fortaleza y la localidad en conjunto. Las formas más fuertes
de connascencia encontradas dentro del mismo módulo representan menos olor a código que la
misma connascencia dispersa.
Grado
El grado de conocimiento se relaciona con el tamaño de su impacto: ¿afecta a unas pocas clases o
a muchas? Los grados menores de conocimiento dañan menos las bases de código. En otras
palabras, tener un alto nivel de conocimiento dinámico no es terrible si solo tienes unos pocos
módulos. Sin embargo, las bases de código tienden a crecer, lo que hace que un problema pequeño
sea correspondientemente más grande.
PageJones ofrece tres pautas para utilizar la connascencia para mejorar la modularidad de los sistemas:
Regla de localidad: a medida que aumenta la distancia entre los elementos del software, utilice formas de
conexión más débiles
ahora, hemos hablado tanto del acoplamiento como de la connascencia, medidas de diferentes épocas y
con diferentes objetivos. Sin embargo, desde el punto de vista de un arquitecto, estas dos visiones se
superponen. Lo que PageJones identifica como connascencia estática representa grados de acoplamiento
entrante o saliente. La programación estructurada solo se preocupa por la entrada o la salida, mientras
que la connascencia se preocupa por cómo se acoplan las cosas.
Para ayudar a visualizar la superposición de conceptos, considere la Figura 36. Los conceptos de
acoplamiento de programación estructurada aparecen a la izquierda, mientras que las características de
connascencia aparecen a la derecha. Lo que la programación estructurada denomina acoplamiento de
datos (llamadas a métodos), la connascencia proporciona asesoramiento sobre cómo debe manifestarse
ese acoplamiento. La programación estructurada no abordó realmente las áreas cubiertas por la
connascencia dinámica; resumimos ese concepto brevemente en “Granularidad y cuántica arquitectónica”
en la página 92.
52 | Capítulo 3: Modularidad
Machine Translated by Google
años 1990 Existen varios problemas para los arquitectos al aplicar estas métricas útiles para analizar y diseñar
sistemas. En primer lugar, estas medidas observan los detalles en un nivel bajo de código, centrándose en la
calidad y la higiene del código más que necesariamente en la estructura arquitectónica. Los arquitectos tienden a
preocuparse más por cómo se acoplan los módulos en lugar del grado de acoplamiento. Por ejemplo, un arquitecto
se preocupa por la comunicación sincrónica versus asincrónica, y no le importa tanto cómo se implementa.
El segundo problema con la connascencia es que no aborda una decisión fundamental que muchos arquitectos
modernos deben tomar: ¿comunicación sincrónica o asincrónica en arquitecturas distribuidas como los
microservicios? Volviendo a la Primera Ley de la Arquitectura de Software, todo es una cuestión de compromisos.
Después de analizar el alcance de las características de la arquitectura en el Capítulo 7, presentaremos nuevas
formas de pensar en la connascencia moderna.
De módulos a componentes
Usamos el término módulo a lo largo del libro como un nombre genérico para un conjunto de códigos relacionados.
Sin embargo, la mayoría de las plataformas admiten algún tipo de componente, uno de los elementos fundamentales
para los arquitectos de software. El concepto y el análisis correspondiente de la separación lógica o física existen
desde los primeros días de la informática. Sin embargo, a pesar de todo lo que se ha escrito y pensado sobre los
componentes y la separación, los desarrolladores y arquitectos aún tienen dificultades para lograr buenos resultados.
De módulos a componentes | 53
Machine Translated by Google
Machine Translated by Google
CAPÍTULO 4
Una empresa decide resolver un problema particular mediante un software, por lo que recopila una
lista de requisitos para ese sistema. Existe una amplia variedad de técnicas para el ejercicio de
recopilación de requisitos, generalmente definidas por el proceso de desarrollo de software utilizado
por el equipo. Pero el arquitecto debe considerar muchos otros factores al diseñar una solución de
software, como se ilustra en la Figura 41.
Figura 41. Una solución de software consta tanto de requisitos de dominio como de características
arquitectónicas.
Los arquitectos pueden colaborar en la definición del dominio o de los requisitos del negocio, pero
una responsabilidad clave implica definir, descubrir y analizar todo lo que el software debe hacer que
no esté directamente relacionado con la funcionalidad del dominio: las características arquitectónicas.
55
Machine Translated by Google
implica una evaluación de calidad posterior al hecho, más que un diseño. Preferimos las características de
la arquitectura porque describen cuestiones críticas para el éxito de la arquitectura y, por lo tanto, del
sistema en su conjunto, sin descontar su importancia.
La definición ilustrada en la Figura 42 consta de los tres componentes enumerados, además de algunos
modificadores:
Al diseñar una aplicación, los requisitos especifican lo que la aplicación debe hacer; las características
de la arquitectura especifican los criterios operativos y de diseño para el éxito, en relación con cómo
implementar los requisitos y por qué se tomaron ciertas decisiones. Por ejemplo, una característica
importante común de la arquitectura especifica un cierto nivel de rendimiento para la aplicación, que a
menudo no aparece en un documento de requisitos. Aún más pertinente: ningún documento de
requisitos establece “prevenir la deuda técnica”, pero es una consideración de diseño común para
arquitectos y desarrolladores. Tratamos esta distinción entre características explícitas e implícitas en
profundidad en “Extracción de características de la arquitectura a partir de preocupaciones del dominio”
en la página 65.
Por supuesto, incluso estos dos criterios no son suficientes en muchos casos para tomar esta decisión:
los incidentes de seguridad anteriores, la naturaleza de la integración con el tercero y una serie de otros
criterios pueden estar presentes durante esta decisión. Aun así, muestra algunas de las consideraciones
que los arquitectos deben tener en cuenta al determinar cómo diseñar para ciertas capacidades.
En la Figura 42, la elección de un triángulo es intencional: cada uno de los elementos de definición respalda a
los demás, que a su vez respaldan el diseño general del sistema.
La intersección creada por el triángulo ilustra el hecho de que estas características arquitectónicas a menudo
interactúan entre sí, lo que lleva al uso generalizado entre los arquitectos del término "compensación".
A pesar del volumen y la escala, los arquitectos suelen dividir las características de la arquitectura en
categorías amplias. En las siguientes secciones se describen algunas, junto con algunos ejemplos.
Disponibilidad Durante cuánto tiempo deberá estar disponible el sistema (si está disponible las 24 horas del día, los 7 días de la semana, se deben tomar medidas para permitir
Actuación Incluye pruebas de estrés, análisis de picos, análisis de la frecuencia de las funciones utilizadas, capacidad requerida y tiempos de respuesta. La
aceptación del rendimiento a veces requiere un ejercicio propio, que lleva meses completar.
Recuperabilidad Requisitos de continuidad del negocio (por ejemplo, en caso de desastre, ¿con qué rapidez se requiere que el sistema vuelva a estar en línea?).
Confiabilidad/ Evalúe si el sistema debe ser a prueba de fallos o si es de importancia crítica para la misión y afecta a la vida de las personas. Si falla, ¿le costará a
Robustez Capacidad de manejar errores y condiciones límite durante la ejecución si falla la conexión a Internet o si hay un corte de energía o una falla de
hardware.
Escalabilidad Capacidad del sistema para funcionar y funcionar a medida que aumenta el número de usuarios o solicitudes.
Las características de la arquitectura operativa se superponen en gran medida con las preocupaciones
operativas y de DevOps, y forman la intersección de esas preocupaciones en muchos proyectos de software.
Los arquitectos deben preocuparse por la estructura del código. En muchos casos, el arquitecto
tiene responsabilidad exclusiva o compartida por las cuestiones de calidad del código, como la buena modularidad,
acoplamiento controlado entre componentes, código legible y una serie de otros elementos internos
Evaluaciones de calidad. La Tabla 42 enumera algunas características de la arquitectura estructural.
Término Definición
Configurabilidad Capacidad para que los usuarios finales cambien fácilmente aspectos de la configuración del software (a través de
interfaces).
Localización Soporte para múltiples idiomas en pantallas de ingreso/consulta en campos de datos; en informes, caracteres multibyte
Portabilidad ¿Es necesario que el sistema se ejecute en más de una plataforma? (Por ejemplo, ¿es necesario que el frontend se ejecute en más de una plataforma?)
Capacidad de soporte ¿Qué nivel de soporte técnico necesita la aplicación? ¿Qué nivel de registro y otras funciones?
Capacidad de actualización Capacidad de actualizar fácil y rápidamente desde una versión anterior de esta aplicación/solución a una versión más nueva
en servidores y clientes.
Accesibilidad Acceso a todos sus usuarios, incluidos aquellos con discapacidades como daltonismo o pérdida auditiva.
Archivabilidad ¿Será necesario archivar o eliminar los datos después de un período de tiempo? (Por ejemplo, las cuentas de clientes son
Para eliminarse después de tres meses o marcarse como obsoleto y archivarse en una base de datos secundaria para el futuro.
acceso.)
Autenticación Requisitos de seguridad para garantizar que los usuarios sean quienes dicen ser.
Autorización Requisitos de seguridad para garantizar que los usuarios puedan acceder solo a ciertas funciones dentro de la aplicación (por caso de uso,
Legal ¿En qué restricciones legislativas opera el sistema (protección de datos, Sarbanes Oxley, RGPD, etc.)?
¿Qué derechos de reserva exige la empresa? ¿Existe alguna normativa sobre la forma de presentar la solicitud?
¿construido o desplegado?
Término Definición
Privacidad Capacidad de ocultar transacciones a los empleados internos de la empresa (transacciones cifradas para que ni siquiera los administradores de bases
Seguridad ¿Es necesario cifrar los datos en la base de datos? ¿Se deben cifrar para la comunicación en red entre sistemas internos? ¿Qué tipo de
Capacidad de soporte ¿Qué nivel de soporte técnico necesita la aplicación? ¿Qué nivel de registro y otras funciones se requieren para depurar errores en el sistema?
Usabilidad/ Nivel de formación necesario para que los usuarios alcancen sus objetivos con la aplicación/solución. Los requisitos de usabilidad deben
factibilidad tratarse con la misma seriedad que cualquier otro problema arquitectónico.
Cualquier lista de características arquitectónicas será necesariamente una lista incompleta; cualquier
software puede inventar características arquitectónicas importantes basándose en factores únicos (ver
“Italialidad” en la página 60 para ver un ejemplo).
Italyility
Una de las colegas de Neal cuenta una historia sobre la naturaleza única de las características
arquitectónicas. Trabajó para un cliente cuyo mandato requería una arquitectura centralizada.
Sin embargo, para cada diseño propuesto, la primera pregunta del cliente era "Pero ¿qué
pasa si perdemos Italia?" Hace años, debido a una interrupción inesperada de las
comunicaciones, la oficina central había perdido la comunicación con las sucursales italianas,
y fue organizacionalmente traumático. Por lo tanto, un requisito firme de todas las arquitecturas
futuras insistió en lo que el equipo finalmente llamó Italyility, que todos sabían que significaba
una combinación única de disponibilidad, recuperabilidad y resiliencia.
Además, muchos de los términos anteriores son imprecisos y ambiguos, a veces debido a matices sutiles
o a la falta de definiciones objetivas. Por ejemplo, interoperabilidad y compatibilidad pueden parecer
equivalentes, lo que será cierto para algunos sistemas.
Sin embargo, difieren porque la interoperabilidad implica facilidad de integración con otros sistemas, lo
que a su vez implica API publicadas y documentadas. La compatibilidad, por otro lado, está más
relacionada con los estándares de la industria y del dominio. Otro ejemplo es la capacidad de aprendizaje.
Una definición es lo fácil que es para los usuarios aprender a usar el software, y otra definición es el nivel
en el que el sistema puede aprender automáticamente sobre su entorno para volverse autoconfigurable
o autooptimizable utilizando algoritmos de aprendizaje automático.
No existe una lista completa de normas. La Organización Internacional de Normalización (ISO) publica
una lista organizada por capacidades, superponiendo muchas de las que hemos
enumeradas, pero principalmente constituyendo una lista incompleta de categorías. A continuación se enumeran
algunas de las definiciones ISO:
Compatibilidad
Grado en el que un producto, sistema o componente puede intercambiar información con otros productos,
sistemas o componentes y/o realizar sus funciones requeridas mientras comparte el mismo entorno de hardware
o software. Incluye coexistencia (puede realizar sus funciones requeridas de manera eficiente mientras comparte
un entorno y recursos comunes con otros productos) e interoperabilidad (grado en el que dos o más sistemas
pueden intercambiar y utilizar información).
Usabilidad
Los usuarios pueden utilizar el sistema de manera eficaz, eficiente y satisfactoria para el propósito previsto.
Incluye la idoneidad, la reconocibilidad (los usuarios pueden reconocer si el software es apropiado para sus
necesidades), la facilidad de aprendizaje (la facilidad con la que los usuarios pueden aprender a utilizar el
software), la protección contra errores del usuario (protección contra errores del usuario) y la accesibilidad (hacer
que el software esté disponible para personas con la gama más amplia de características y capacidades).
Grado de
confiabilidad en el que un sistema funciona bajo condiciones específicas durante un período de tiempo
específico. Esta característica incluye subcategorías como madurez (¿el software cumple con las necesidades
de confiabilidad en condiciones normales de funcionamiento?), disponibilidad (el software está operativo y
accesible), tolerancia a fallas (¿el software funciona como se espera a pesar de fallas de hardware o software?)
y recuperabilidad (¿puede el software recuperarse de una falla recuperando los datos afectados y restableciendo
el estado deseado del sistema?).
Grado de
seguridad El software protege la información y los datos de modo que las personas u otros productos o sistemas
tengan el grado de acceso a los datos apropiado para sus tipos y niveles de autorización. Esta familia de
características incluye la confidencialidad (los datos son accesibles solo para aquellos autorizados a tener
acceso), la integridad (el software evita el acceso no autorizado o la modificación del software o los datos), el no
repudio (se puede probar que se han producido acciones o eventos), la rendición de cuentas (se pueden rastrear
las acciones de un usuario) y la autenticidad (probar la identidad de un usuario).
Mantenibilidad
Representa el grado de efectividad y eficiencia con el que los desarrolladores pueden
modificar el software para mejorarlo, corregirlo o adaptarlo a cambios en el entorno y/o los
requisitos. Esta característica incluye la modularidad (grado en el que el software está
compuesto de componentes discretos), la reutilización (grado en el que los desarrolladores
pueden usar un activo en más de un sistema o en la creación de otros activos), la
analizabilidad (la facilidad con la que los desarrolladores pueden recopilar métricas concretas
sobre el software), la modificabilidad (grado en el que los desarrolladores pueden modificar
el software sin introducir defectos ni degradar la calidad del producto existente) y la testabilidad
(la facilidad con la que los desarrolladores y otros pueden probar el software).
Portabilidad
Grado en el cual los desarrolladores pueden transferir un sistema, producto o componente
de un hardware, software u otro entorno operativo o de uso a otro.
Esta característica incluye las subcaracterísticas de adaptabilidad (¿pueden los desarrolladores
adaptar de manera eficaz y eficiente el software para hardware, software u otros entornos
operativos o de uso diferentes o en evolución?), instalabilidad (¿puede el software instalarse
y/o desinstalarse en un entorno específico?) y reemplazabilidad (con qué facilidad los
desarrolladores pueden reemplazar la funcionalidad con otro software).
El último elemento de la lista ISO aborda los aspectos funcionales del software, que no creemos
que deban incluirse en esta lista:
Idoneidad funcional
Esta característica representa el grado en el que un producto o sistema proporciona funciones
que satisfacen las necesidades declaradas e implícitas cuando se utiliza en condiciones
específicas. Esta característica se compone de las siguientes subcaracterísticas:
Completitud funcional
Grado en el que el conjunto de funciones cubre todas las tareas especificadas y los
objetivos del usuario.
Corrección funcional
Grado en el que un producto o sistema proporciona los resultados correctos con el grado
de precisión necesario.
Adecuación funcional
Grado en el que las funciones facilitan el cumplimiento de tareas y objetivos específicos.
Estas no son características de la arquitectura, sino más bien los requisitos motivacionales
para crear el software. Esto ilustra cómo ha evolucionado el pensamiento sobre la
relación entre las características de la arquitectura y el dominio del problema. Abordamos
esta evolución en el Capítulo 7.
Una metáfora ayudará a ilustrar esta interconectividad. Aparentemente, los pilotos a menudo tienen
dificultades para aprender a volar helicópteros porque se requiere un control para cada mano y cada
pie, y cambiar uno afecta a los demás. Por lo tanto, volar un helicóptero es un ejercicio de equilibrio,
que describe muy bien el proceso de compensación al elegir las características de la arquitectura. Cada
característica de la arquitectura que un arquitecto diseña para respaldar potencialmente complica el
diseño general.
Por lo tanto, los arquitectos rara vez se encuentran en situaciones en las que pueden diseñar un sistema
y maximizar cada característica arquitectónica. Más a menudo, las decisiones se reducen a
compensaciones entre varias preocupaciones en pugna.
Esto sugiere que los arquitectos deben esforzarse por diseñar una arquitectura que sea lo más iterativa
posible. Si se pueden realizar cambios en la arquitectura con mayor facilidad, se puede estresar menos.
Se trata de descubrir exactamente lo correcto en el primer intento. Una de las lecciones más
importantes del desarrollo de software ágil es el valor de la iteración; esto es válido en todos
los niveles del desarrollo de software, incluida la arquitectura.
CAPÍTULO 5
Identificar las características arquitectónicas impulsoras es uno de los primeros pasos para crear
una arquitectura o determinar la validez de una arquitectura existente. Identificar las características
arquitectónicas correctas (“ilidades”) para un problema o aplicación determinados requiere que un
arquitecto no solo comprenda el problema del dominio, sino que también colabore con las partes
interesadas del dominio del problema para determinar qué es realmente importante desde una
perspectiva del dominio.
Un arquitecto debe ser capaz de traducir las preocupaciones del dominio para identificar las
características arquitectónicas correctas. Por ejemplo, ¿la escalabilidad es la preocupación más
importante o la tolerancia a fallas, la seguridad o el rendimiento? Tal vez el sistema requiera las
cuatro características combinadas. Comprender los objetivos clave del dominio y la situación del
dominio le permite a un arquitecto traducir esas preocupaciones del dominio en “capacidades”, que
luego forman la base para tomar decisiones arquitectónicas correctas y justificables.
Un consejo a la hora de colaborar con las partes interesadas del dominio para definir las
características arquitectónicas impulsoras es trabajar duro para mantener la lista final lo más corta
posible. Un antipatrón común en la arquitectura implica intentar diseñar una arquitectura genérica,
una que admita todas las características de la arquitectura. Cada característica de la arquitectura
que la arquitectura admite complica el diseño general del sistema; admitir demasiadas características
de la arquitectura conduce a una complejidad cada vez mayor antes de que el arquitecto y los
desarrolladores hayan comenzado a abordar el dominio del problema, el dominio original.
65
Machine Translated by Google
Motivación para escribir el software. No te obsesiones con la cantidad de características, sino con la
motivación para mantener el diseño simple.
Muchos arquitectos y partes interesadas del dominio desean priorizar la lista final de características
de arquitectura que la aplicación o el sistema deben soportar. Si bien esto es ciertamente deseable,
en la mayoría de los casos es una tarea inútil y no solo hará perder tiempo, sino que también
producirá mucha frustración y desacuerdo innecesarios con las partes interesadas clave. Rara vez
todas las partes interesadas estarán de acuerdo sobre la prioridad de todas y cada una de las
características. Un mejor enfoque es que las partes interesadas del dominio seleccionen las tres
características más importantes de la lista final (en cualquier orden). No solo es mucho más fácil
llegar a un consenso, sino que también fomenta las discusiones sobre lo que es más importante y
ayuda al arquitecto a analizar las compensaciones al tomar decisiones vitales sobre la arquitectura.
Tiempo de comercialización
Agilidad, capacidad de prueba y de implementación
Satisfacción del usuario Rendimiento, disponibilidad, tolerancia a fallos, capacidad de prueba, capacidad de implementación, agilidad, seguridad
Ventaja competitiva Agilidad, capacidad de prueba, capacidad de implementación, escalabilidad, disponibilidad, tolerancia a fallas
Un aspecto importante que hay que tener en cuenta es que la agilidad no es igual a tiempo de
comercialización, sino que es agilidad + capacidad de prueba + capacidad de implementación. Esta es una
trampa en la que caen muchos arquitectos cuando traducen las preocupaciones de un dominio. Centrarse
en un solo ingrediente es como olvidarse de poner la harina en la masa del pastel. Por ejemplo, una parte
interesada en un dominio podría decir algo como “Debido a los requisitos regulatorios, es absolutamente
imperativo que completemos la fijación de precios de los fondos al final del día a tiempo”. Un arquitecto
ineficaz podría centrarse únicamente en el rendimiento porque ese parece ser el foco principal de esa preocupación de dominio.
Sin embargo, ese arquitecto fracasará por muchas razones. En primer lugar, no importa cuán rápido sea el
sistema si no está disponible cuando se lo necesita. En segundo lugar, a medida que el dominio crece y se
crean más fondos, el sistema también debe poder escalar para terminar el procesamiento de fin de día a
tiempo. En tercer lugar, el sistema no solo debe estar disponible, sino que también debe ser confiable para
que no se bloquee mientras se calculan los precios de los fondos de fin de día. En cuarto lugar, ¿qué
sucede si el precio de los fondos de fin de día está completo en un 85% y el sistema se bloquea? Debe
poder recuperarse y reiniciarse donde se quedó el precio. Por último, el sistema puede ser rápido, pero ¿se
están calculando correctamente los precios de los fondos? Por lo tanto, además del rendimiento, el
arquitecto también debe centrarse por igual en la disponibilidad, la escalabilidad, la confiabilidad, la
capacidad de recuperación y la auditabilidad.
¡Procrastinate sabe la respuesta a esta pregunta! Es raro que detalles como estos aparezcan en
los documentos de requisitos, pero sí que informan las decisiones de diseño.
unos años, Ted Neward, un conocido arquitecto, ideó los katas de arquitectura, un método inteligente
que permite a los arquitectos principiantes practicar la derivación de características arquitectónicas
a partir de descripciones específicas de un dominio. Procedente de Japón y de las artes marciales,
un kata es un ejercicio de entrenamiento individual, en el que el énfasis recae en la forma y la
técnica adecuadas.
¿Cómo conseguimos grandes diseñadores? Los grandes diseñadores diseñan, por supuesto.
—Fred Brooks
Entonces, ¿cómo vamos a conseguir grandes arquitectos si sólo tienen la oportunidad de ejercer la
arquitectura menos de media docena de veces en su carrera?
Para ofrecer un plan de estudios a los arquitectos en ciernes, Ted creó el primer sitio de katas de arquitectura,
que sus autores Neal y Mark adaptaron y actualizaron. La premisa básica del ejercicio de kata ofrece a los
arquitectos un problema planteado en términos de dominio y un contexto adicional (cosas que podrían no
aparecer en los requisitos pero que tienen un impacto en el diseño).
Los equipos pequeños trabajan durante 45 minutos en un diseño y luego muestran los resultados a los
demás grupos, que votan quién ha ideado la mejor arquitectura. Fieles a su propósito original, los katas de
arquitectura ofrecen un laboratorio útil para los arquitectos en ciernes.
Descripción
El problema general del dominio que el sistema está intentando resolver
Usuarios
Requisitos
Requisitos a nivel de dominio/dominio, como un arquitecto podría esperar de los usuarios del dominio/
expertos del dominio
Neal actualizó el formato unos años más tarde en su blog. agregar la sección de contexto adicional a
cada kata con consideraciones adicionales importantes, haciendo que los ejercicios sean más
realistas.
Contexto adicional
Muchas de las consideraciones que debe hacer un arquitecto no se expresan explícitamente en los
requisitos, sino más bien en el conocimiento implícito del dominio del problema.
Animamos a los arquitectos en ciernes a utilizar el sitio para realizar sus propios ejercicios de kata.
Cualquiera puede organizar un almuerzo informal en el que un equipo de aspirantes a arquitectos puede
resolver un problema y conseguir que un arquitecto experimentado evalúe el diseño y las ventajas y desventajas.
Análisis, ya sea en el momento o a partir de un breve análisis posterior. El diseño no será elaborado porque el
ejercicio tiene un límite de tiempo. Lo ideal es que los miembros del equipo reciban comentarios de la arquitectura
experimentada sobre las compensaciones que no se han tenido en cuenta y los diseños alternativos.
Descripción
Una tienda nacional de sándwiches quiere habilitar pedidos en línea (además de su actual servicio de
llamada).
Usuarios
Requisitos • Los
usuarios realizarán su pedido, luego se les indicará un horario para retirar su sándwich y las instrucciones
para llegar a la tienda (que debe integrarse con varios servicios de mapas externos que incluyan
información de tráfico).
Contexto adicional •
objetivo corporativo es contratar mano de obra barata para maximizar las ganancias
En este escenario, ¿cómo podría un arquitecto obtener las características de la arquitectura? Cada parte del
requisito podría contribuir a uno o más aspectos de la arquitectura (y muchos no lo harán). El arquitecto no
diseña aquí todo el sistema; todavía debe dedicar un esfuerzo considerable a la elaboración del código para
resolver la declaración del dominio. En cambio, el arquitecto busca elementos que influyan o afecten el
diseño, en particular los estructurales.
En primer lugar, separe las características de la arquitectura candidata en características explícitas e implícitas.
Uno de los primeros detalles que debe llamar la atención de un arquitecto es el número de usuarios:
actualmente miles, quizás un día millones (¡esta es una tienda de bocadillos muy ambiciosa!).
Por lo tanto, la escalabilidad (la capacidad de manejar una gran cantidad de usuarios simultáneos sin una
degradación grave del rendimiento) es una de las principales características de la arquitectura.
Tenga en cuenta que el enunciado del problema no pedía explícitamente escalabilidad, sino que expresaba
ese requisito como una cantidad esperada de usuarios. Los arquitectos a menudo deben decodificar el lenguaje
del dominio en equivalentes de ingeniería.
Sin embargo, probablemente también necesitemos elasticidad: la capacidad de manejar ráfagas de solicitudes.
Estas dos características suelen aparecer agrupadas, pero tienen diferentes restricciones. La escalabilidad se
parece al gráfico que se muestra en la Figura 51.
La elasticidad, por otro lado, mide las ráfagas de tráfico, como se muestra en la Figura 52.
Algunos sistemas son escalables pero no elásticos. Por ejemplo, considere un sistema de reservas de hotel. A falta
de promociones o eventos especiales, el número de usuarios probablemente sea constante. Por el contrario,
considere un sistema de reserva de entradas para conciertos. A medida que se ponen a la venta nuevas entradas,
los fanáticos fervientes inundarán el sitio, lo que requiere altos grados de elasticidad. A menudo, los sistemas
elásticos también necesitan escalabilidad: la capacidad de manejar ráfagas y grandes cantidades de usuarios simultáneos.
El requisito de elasticidad no apareció en los requisitos de Silicon Sandwiches, pero el arquitecto debería identificarlo
como una consideración importante. Los requisitos a veces establecen características arquitectónicas directamente,
pero algunas se esconden dentro del dominio del problema. Consideremos una tienda de sándwiches. ¿Su tráfico
es constante durante todo el día?
¿O soporta los picos de tráfico a la hora de comer? Casi con toda seguridad, esto último.
Por tanto, un buen arquitecto debería identificar esta característica potencial de la arquitectura.
Un arquitecto debe considerar cada uno de estos requisitos comerciales a su vez para ver si existen características
arquitectónicas:
1. Los usuarios realizarán su pedido, luego se les indicará un horario para retirar su sándwich e instrucciones
para llegar a la tienda (que debe brindar la opción de integrarse con servicios de mapas externos que incluyan
información de tráfico).
Los servicios de mapeo externo implican puntos de integración, lo que puede afectar aspectos como
la confiabilidad. Por ejemplo, si un desarrollador crea un sistema que depende de un sistema de
terceros, pero la llamada falla, esto afecta la confiabilidad del sistema que realiza la llamada. Sin
embargo, los arquitectos también deben tener cuidado de no especificar en exceso las características
de la arquitectura. ¿Qué sucede si el servicio de tráfico externo no funciona? ¿Debería el servidor de Silicon
¿Los sitios tipo sándwich fallan o deberían ofrecer una eficiencia ligeramente menor sin información sobre
el tráfico? Los arquitectos siempre deben tener cuidado de no incorporar fragilidad o fragilidad innecesarias
en los diseños.
Los pagos en línea implican seguridad, pero nada en este requisito sugiere un nivel de seguridad
particularmente elevado más allá de lo implícito.
Este requisito puede imponer restricciones de costos a la arquitectura: el arquitecto debe verificar la
viabilidad (aplicando restricciones como costo, tiempo y habilidades del personal) para ver si se justifica una
arquitectura simple o sacrificial.
Este requisito implica internacionalización, o i18n. Existen muchas técnicas de diseño para manejar este
requisito, que no deberían requerir una estructura especial para adaptarse. Sin embargo, esto sin duda
determinará las decisiones de diseño.
9. El objetivo corporativo es contratar mano de obra barata para maximizar las ganancias.
Este requisito sugiere que la usabilidad será importante, pero nuevamente está más relacionado con el diseño
que con las características de la arquitectura.
La tercera característica de la arquitectura que derivamos de los requisitos anteriores es el rendimiento: nadie quiere
comprar en una tienda de bocadillos que tenga un rendimiento deficiente, especialmente en horas punta. Sin embargo,
el rendimiento es un concepto con matices: ¿para qué tipo de rendimiento debería diseñar el arquitecto? En el capítulo
6 abordamos los distintos matices del rendimiento.
También queremos definir cifras de rendimiento en conjunción con cifras de escalabilidad. En otras palabras, debemos
establecer una línea base de rendimiento sin una escala particular, así como determinar qué nivel de rendimiento es
aceptable para una cierta cantidad de usuarios. Muy a menudo, las características de la arquitectura interactúan entre
sí, lo que obliga a los arquitectos a definirlas en relación con las demás.
La seguridad aparece como una característica implícita en todos los sistemas: nadie quiere crear software inseguro.
Sin embargo, se le puede dar prioridad en función de su criticidad, lo que ilustra la naturaleza interconectada de
nuestra definición. Un arquitecto considera que la seguridad es una característica de la arquitectura si influye en algún
aspecto estructural del diseño y es crítica o importante para la aplicación.
En el caso de los sándwiches de silicio, un arquitecto podría suponer que los pagos deberían ser gestionados por un
tercero. Por lo tanto, siempre que los desarrolladores sigan las normas generales de seguridad (no pasar números de
tarjetas de crédito como texto sin formato, no almacenar demasiada información, etc.), el arquitecto no debería
necesitar ningún diseño estructural especial para adaptar la seguridad; bastará con un buen diseño en la aplicación.
Cada característica de la arquitectura interactúa con las demás, lo que conduce al error común de los arquitectos de
sobreespecificar las características de la arquitectura, lo que es tan perjudicial como subespecificarlas porque
complica demasiado el diseño del sistema.
La última característica arquitectónica importante que Silicon Sandwiches necesita soportar abarca varios detalles
de los requisitos: la capacidad de personalización. Observe que varias partes del dominio del problema ofrecen
un comportamiento personalizado: recetas, ventas locales e instrucciones que pueden anularse localmente. Por
lo tanto, la arquitectura debe admitir la capacidad de facilitar un comportamiento personalizado. Normalmente,
esto caería dentro del diseño de la aplicación. Sin embargo, como especifica nuestra definición, una parte del
dominio del problema que se basa en una estructura personalizada para respaldarla pasa al ámbito de una
característica de arquitectura. Sin embargo, este elemento de diseño no es crítico para el éxito de la aplicación.
Es importante señalar que no hay respuestas correctas a la hora de elegir las características de la arquitectura,
solo incorrectas (o, como señala Mark en una de sus conocidas citas):
Como en toda arquitectura, depende de varios factores. En primer lugar, ¿existen buenas razones,
como el rendimiento y el acoplamiento, para no implementar una arquitectura de microkernel? En
segundo lugar, ¿hay otras características deseables de la arquitectura que son más difíciles de
implementar en un diseño que en otro? En tercer lugar, ¿cuánto costaría soportar todas las
características de la arquitectura en cada diseño en comparación con el patrón? Este tipo de análisis
de compensaciones arquitectónicas constituye una parte importante del papel de un arquitecto.
Por encima de todo, es fundamental que el arquitecto colabore con los desarrolladores, el director de
proyectos, el equipo de operaciones y otros coconstructores del sistema de software. Ninguna decisión
de arquitectura debe tomarse aislada del equipo de implementación (lo que conduce al temido antipatrón
del arquitecto de torre de marfil). En el caso de los sándwiches de silicio, el arquitecto, el líder técnico,
los desarrolladores y los analistas de dominio deben colaborar para decidir cuál es la mejor manera de
implementar la personalización.
Un arquitecto podría diseñar una arquitectura que no admita la personalización estructuralmente, lo que requeriría
que el diseño de la propia aplicación admita ese comportamiento (consulte “Diseño versus arquitectura y
compensaciones” en la página 74). Los arquitectos no deberían estresarse demasiado por descubrir el conjunto
exacto de características de la arquitectura: los desarrolladores pueden implementar la funcionalidad de diversas
maneras. Sin embargo, la identificación correcta de las características de la arquitectura puede ser un proceso complejo.
Identificar elementos estructurales importantes puede facilitar un diseño más simple o más elegante.
Los arquitectos deben recordar: no existe el mejor diseño en arquitectura, solo el menos peor
conjunto de compensaciones.
Los arquitectos también deben priorizar estas características de arquitectura para tratar de encontrar
los conjuntos requeridos más simples. Un ejercicio útil una vez que el equipo ha hecho un primer
intento de identificar las características de arquitectura es tratar de determinar la menos importante:
si debe eliminar una, ¿cuál sería? En general, los arquitectos son más propensos a descartar las
características explícitas de la arquitectura, ya que muchas de las implícitas respaldan el éxito
general. La forma en que definimos lo que es crítico o importante para el éxito ayuda a los arquitectos
a determinar si la aplicación realmente requiere cada característica de la arquitectura. Al intentar
determinar la menos aplicable, los arquitectos pueden ayudar a determinar la necesidad crítica. En
el caso de los sándwiches de silicio, ¿qué característica de la arquitectura que hemos identificado
es la menos importante? Nuevamente, no existe una respuesta absolutamente correcta. Sin
embargo, en este caso, la solución podría perder la capacidad de personalización o el rendimiento.
Podríamos eliminar la capacidad de personalización como una característica de la arquitectura y
planificar la implementación de ese comportamiento como parte del diseño de la aplicación. De las
características de la arquitectura operativa, el rendimiento es probablemente la menos crítica para
el éxito. Por supuesto, los desarrolladores no pretenden crear una aplicación que tenga un
rendimiento terrible, sino una que no priorice el rendimiento sobre otras características, como la
escalabilidad o la disponibilidad.
CAPÍTULO 6
Medición y gobernanza
Características de la arquitectura
Los arquitectos deben lidiar con la extraordinaria variedad de características arquitectónicas en todos los
aspectos de los proyectos de software. Los aspectos operativos como el rendimiento, la elasticidad y la
escalabilidad se combinan con cuestiones estructurales como la modularidad y la capacidad de
implementación. Este capítulo se centra en definir de manera concreta algunas de las características
arquitectónicas más comunes y en crear mecanismos de gobernanza para ellas.
Existen varios problemas comunes en torno a la definición de las características de la arquitectura en las
organizaciones:
77
Machine Translated by Google
Demasiado
compuesta Muchas características deseables de la arquitectura comprenden muchas otras en una escala
más pequeña. Por ejemplo, los desarrolladores pueden descomponer la agilidad en características como
modularidad, capacidad de implementación y capacidad de prueba.
Las definiciones objetivas de las características de la arquitectura resuelven los tres problemas: al acordar
definiciones concretas de las características de la arquitectura en toda la organización, los equipos crean un
lenguaje ubicuo en torno a la arquitectura. Además, al fomentar las definiciones objetivas, los equipos pueden
descomponer las características compuestas para descubrir características mensurables que pueden definir
objetivamente.
características de la arquitectura tienen mediciones directas obvias, como el rendimiento o la escalabilidad. Sin
embargo, incluso estas ofrecen muchas interpretaciones matizadas, según los objetivos del equipo. Por ejemplo,
tal vez un equipo mida el tiempo de respuesta promedio para ciertas solicitudes, un buen ejemplo de una medida
de características de la arquitectura operativa. Pero si los equipos solo miden el promedio, ¿qué sucede si alguna
condición límite hace que el 1% de las solicitudes tarden 10 veces más que otras? Si el sitio tiene suficiente tráfico,
es posible que los valores atípicos ni siquiera aparezcan. Por lo tanto, un equipo también puede querer medir los
tiempos de respuesta máximos para detectar valores atípicos.
Los equipos de alto nivel no se limitan a establecer cifras de rendimiento exactas, sino que basan sus
definiciones en análisis estadísticos. Por ejemplo, supongamos que un servicio de transmisión de vídeo
desea supervisar la escalabilidad. En lugar de establecer una cifra arbitraria como objetivo, los ingenieros
miden la escala a lo largo del tiempo y crean modelos estadísticos, y luego dan la alarma si las métricas
en tiempo real quedan fuera de los modelos de predicción. Una falla puede significar dos cosas: el modelo
es incorrecto (algo que a los equipos les gusta saber) o algo no va bien (algo que a los equipos también
les gusta saber).
Los tipos de características que los equipos pueden medir ahora están evolucionando rápidamente, junto
con las herramientas y la comprensión matizada. Por ejemplo, muchos equipos recientemente se centraron
en los presupuestos de rendimiento para métricas como la primera pintura con contenido y la primera
CPU inactiva, que dicen mucho sobre los problemas de rendimiento de los usuarios de páginas web en
dispositivos móviles. A medida que cambien los dispositivos, los objetivos, las capacidades y una infinidad
de otras cosas, los equipos encontrarán nuevas cosas y formas de medir.
Medidas estructurales
Algunas medidas objetivas no son tan obvias como el rendimiento. ¿Qué sucede con las características
estructurales internas, como la modularidad bien definida? Lamentablemente, aún no existen métricas
integrales para la calidad interna del código. Sin embargo, algunas métricas y herramientas comunes
permiten a los arquitectos abordar algunos aspectos críticos de la estructura del código, aunque en
dimensiones limitadas.
Un aspecto medible obvio del código es la complejidad, definida por la métrica de complejidad ciclomática.
Complejidad ciclomática
Complejidad ciclomática (CC) es una métrica a nivel de código diseñada para proporcionar una
medida de objeto para la complejidad del código, a nivel de función/método, clase o aplicación,
desarrollada por Thomas McCabe, Sr., en 1976.
Se calcula aplicando la teoría de grafos al código, específicamente a los puntos de decisión, que causan
diferentes rutas de ejecución. Por ejemplo, si una función no tiene instrucciones de decisión (como
instrucciones if ), entonces CC = 1. Si la función tenía una sola condición, entonces CC = 2 porque existen
dos posibles rutas de ejecución.
La fórmula para calcular el CC para una sola función o método es CC = E − N + 2, donde N representa
nodos (líneas de código) y E representa aristas (posibles decisiones).
Considere el código tipo C que se muestra en el Ejemplo 61.
public void decision(int c1, int c2) { si (c1 < 100) devuelve
0; de lo contrario si
(c1 + C2 >
500) devuelve 1; de lo contrario
devuelve 1;
La complejidad ciclomática del Ejemplo 61 es 3 (=3 – 2 + 2); el gráfico aparece en la Figura
61.
Los arquitectos y desarrolladores coinciden en que un código demasiado complejo es un mal olor de código;
perjudica prácticamente todas las características deseables de las bases de código: modularidad, capacidad de
prueba, capacidad de implementación, etc. Sin embargo, si los equipos no controlan la creciente complejidad,
esa complejidad dominará la base de código.
Una pregunta habitual que reciben los autores cuando hablan sobre este tema es: ¿cuál es un buen valor
umbral para CC? Por supuesto, como todas las respuestas en la arquitectura de software: ¡depende! Depende
de la complejidad del dominio del problema. Por ejemplo, si tienes un problema algorítmicamente complejo, la
solución producirá funciones complejas.
Algunos de los aspectos clave de CC que los arquitectos deben controlar: ¿las funciones son complejas
debido al dominio del problema o debido a una codificación deficiente? Alternativamente, ¿el código está mal
dividido? En otras palabras, ¿se podría dividir un método grande en fragmentos lógicos más pequeños,
distribuyendo el trabajo (y la complejidad) en métodos mejor factorizados?
En general, los umbrales de la industria para CC sugieren que un valor inferior a 10 es aceptable, salvo otras
consideraciones como dominios complejos. Consideramos que ese umbral es muy alto y preferiríamos que el
código se encuentre por debajo de cinco, lo que indica un código coherente y bien factorizado. Una herramienta
de métricas en el mundo de Java, Crap4J, intenta determinar cuán malo (de mala calidad) es su código
evaluando una combinación de CC y cobertura de código; si el CC crece a más de 50, ninguna cantidad de
cobertura de código rescata ese código de la mala calidad. El artefacto profesional más aterrador con el que
se encontró Neal fue una única función C que servía como el corazón de un paquete de software comercial
cuyo CC era de más de 800. Era una única función con más de 4000 líneas de código, incluido el uso liberal
de declaraciones GOTO (para escapar de bucles anidados de una profundidad imposible).
Las prácticas de ingeniería como el desarrollo basado en pruebas tienen el efecto secundario accidental (pero
positivo) de generar métodos más pequeños y menos complejos en promedio para un dominio de problemas
determinado. Al practicar TDD, los desarrolladores intentan escribir una prueba simple y luego escriben la
menor cantidad de código para pasar la prueba. Este enfoque en el comportamiento discreto y los buenos
límites de prueba fomenta métodos bien factorizados y altamente cohesivos que exhiben un bajo nivel de complejidad.
C.C.
Medidas de proceso
Algunas características de la arquitectura se entrecruzan con los procesos de desarrollo de software. Por ejemplo, la
agilidad suele aparecer como una característica deseable. Sin embargo, es una característica de arquitectura compuesta
que los arquitectos pueden descomponer en características como la capacidad de prueba y la capacidad de implementación.
La capacidad de prueba se puede medir a través de herramientas de cobertura de código para prácticamente todas las
plataformas que evalúan la integridad de las pruebas. Como todas las comprobaciones de software, no puede reemplazar
el pensamiento y la intención. Por ejemplo, una base de código puede tener una cobertura de código del 100% y, sin
embargo, afirmaciones deficientes que en realidad no brindan confianza en la corrección del código. Sin embargo, la
capacidad de prueba es claramente una característica medible de manera objetiva. De manera similar, los equipos pueden
medir la capacidad de implementación a través de una variedad de métricas: porcentaje de implementaciones exitosas y fallidas, cómo
Los tiempos de implementación, los problemas y errores que surgen durante la implementación y muchos
otros factores más. Cada equipo tiene la responsabilidad de llegar a un buen conjunto de mediciones que
capturen datos útiles para su organización, tanto en calidad como en cantidad. Muchas de estas mediciones
se reducen a las prioridades y objetivos del equipo.
gobernanza, derivada de la palabra griega kubernan (dirigir), es una responsabilidad importante del rol del
arquitecto. Como su nombre lo indica, el alcance de la gobernanza de la arquitectura cubre cualquier
aspecto del proceso de desarrollo de software en el que los arquitectos (incluidos roles como los arquitectos
empresariales) quieran ejercer influencia. Por ejemplo, asegurar la calidad del software dentro de una
organización cae bajo el encabezado de gobernanza arquitectónica porque cae dentro del alcance de la
arquitectura, y la negligencia puede llevar a problemas de calidad desastrosos.
Afortunadamente, existen soluciones cada vez más sofisticadas para aliviar este problema de los
arquitectos, un buen ejemplo del crecimiento incremental de las capacidades dentro del ecosistema de
desarrollo de software. El impulso hacia la automatización de proyectos de software generado por la
Programación Extrema Se creó una integración continua que condujo a una mayor automatización de las
operaciones, lo que ahora llamamos DevOps, y que continuó hasta la gobernanza arquitectónica. El libro
Building Evolutionary Architectures (O'Reilly) describe una familia de técnicas, llamadas funciones de
aptitud, utilizadas para automatizar muchos aspectos de la gobernanza de la arquitectura.
Funciones de fitness
La palabra “evolutivo” en Building Evolutionary Architectures proviene más de la computación evolutiva que de la
biología. Una de las autoras, la Dra. Rebecca Parsons, pasó algún tiempo en el espacio de la computación
evolutiva, incluidas herramientas como los algoritmos genéticos. Un algoritmo genético se ejecuta y produce una
respuesta y luego sufre una mutación mediante técnicas bien conocidas definidas dentro del mundo de la
computación evolutiva. Si un desarrollador intenta diseñar un algoritmo genético para producir algún resultado
beneficioso, a menudo desea guiar el algoritmo, proporcionando una medida objetiva que indique la calidad del
resultado. Ese mecanismo de guía se llama función de aptitud: una función de objeto utilizada para evaluar qué
tan cerca está el resultado de lograr el objetivo. Por ejemplo, supongamos que un desarrollador necesita resolver
el problema del viajante de comercio , Un problema famoso que se utiliza como base para el aprendizaje
automático. Dado un vendedor y una lista de ciudades que debe visitar, con las distancias entre ellas, ¿cuál es la
ruta óptima? Si un desarrollador diseña un algoritmo genético para resolver este problema, una función de aptitud
podría evaluar la longitud de la ruta, ya que la más corta posible representa el mayor éxito. Otra función de aptitud
podría ser evaluar el costo general asociado con la ruta e intentar mantener el costo al mínimo. Otra podría ser
evaluar el tiempo que el vendedor viajero está fuera y optimizar para acortar el tiempo total de viaje.
Las prácticas de arquitectura evolutiva toman prestado este concepto para crear una función de aptitud
arquitectónica:
Las funciones de aptitud no son un nuevo marco de trabajo que los arquitectos puedan descargar, sino más bien
una nueva perspectiva sobre muchas herramientas existentes. Observe en la definición la frase cualquier
mecanismo: las técnicas de verificación de las características de la arquitectura son tan variadas como las
características. Las funciones de aptitud se superponen con muchos mecanismos de verificación existentes,
dependiendo de la forma en que se utilicen: como métricas, monitores, bibliotecas de pruebas unitarias, ingeniería
del caos, etc., como se ilustra en la Figura 62.
Se pueden utilizar muchas herramientas diferentes para implementar funciones de aptitud, según las
características de la arquitectura. Por ejemplo, en “Acoplamiento” en la página 44, presentamos métricas
para permitir que los arquitectos evalúen la modularidad. A continuación, se muestran un par de ejemplos
de funciones de aptitud que prueban varios aspectos de la modularidad.
Dependencias cíclicas
La modularidad es una característica arquitectónica implícita que preocupa a la mayoría de los arquitectos,
porque una modularidad mal mantenida daña la estructura de una base de código; por lo tanto, los
arquitectos deberían dar una alta prioridad al mantenimiento de una buena modularidad. Sin embargo, las
fuerzas trabajan en contra de las buenas intenciones del arquitecto en muchas plataformas. Por ejemplo,
al codificar en cualquier entorno de desarrollo Java o .NET popular, tan pronto como un desarrollador hace
referencia a una clase que aún no se ha importado, el IDE presenta amablemente un diálogo que pregunta
a los desarrolladores si les gustaría importar automáticamente la referencia. Esto ocurre tan a menudo
que la mayoría de los programadores desarrollan el hábito de rechazar el diálogo de importación
automática como un acto reflejo. Sin embargo, importar arbitrariamente clases o componentes entre sí
significa un desastre para la modularidad. Por ejemplo, la Figura 63 ilustra un antipatrón particularmente
dañino que los arquitectos aspiran a evitar.
En la Figura 63, cada componente hace referencia a algo de los demás. Tener una red de componentes
como ésta perjudica la modularidad porque un desarrollador no puede reutilizar un solo componente sin
incorporar también 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 la Gran Bola de Lodo. antipatrón. ¿Cómo pueden
los arquitectos controlar este comportamiento sin tener que estar constantemente vigilando a los
desarrolladores impulsivos? Las revisiones de código ayudan, pero se realizan demasiado tarde en el ciclo
de desarrollo para ser efectivas. Si un arquitecto permite que un equipo de desarrollo importe
desenfrenadamente en toda la base de código durante una semana hasta la revisión de código, ya se han
producido daños graves en la base de código.
La solución a este problema es escribir una función de aptitud para cuidar los ciclos, como se muestra en
el Ejemplo 62.
@BeforeEach
void init() { jdepend
= new JDepend();
jdepend.addDirectory("/ruta/al/proyecto/persistencia/clases"); jdepend.addDirectory("/
ruta/al/proyecto/web/clases"); jdepend.addDirectory("/ruta/al/proyecto/
jars/de/terceros");
}
@Test
void testAllPackages() { Colección
paquetes = jdepend.analyze(); assertEquals(" Existen
ciclos", 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 existen ciclos.
Un arquitecto puede conectar esta prueba a la compilación continua de un proyecto y dejar de preocuparse
por la introducción accidental de ciclos por parte de desarrolladores impulsivos. Este es un gran ejemplo de
una función de aptitud que protege las prácticas importantes en lugar de las urgentes del desarrollo de
software: es una preocupación importante para los arquitectos pero tiene poco impacto en la codificación del
día a día.
principal En “Acoplamiento” en la página 44, presentamos la métrica más esotérica de la distancia desde la
secuencia principal, que los arquitectos también pueden verificar utilizando funciones de aptitud, como se
muestra en el Ejemplo 63.
@Test
void AllPackages() { double
ideal = 0.0; double
tolerancia = 0.5; // Colección dependiente del proyecto
packages = jdepend.analyze(); Iterador iter =
packages.iterator(); while (iter.hasNext())
{ JavaPackage p =
(JavaPackage)iter.next(); assertEquals("Distancia
excedida: " + p.getName(),
ideal, p.distancia(), tolerancia);
}
}
En el código, el arquitecto utiliza JDepend para establecer un umbral de valores aceptables y falla la prueba
si una clase cae fuera del rango.
La sofisticación de las herramientas de funciones de fitness ha aumentado en los últimos años, incluidas
algunas herramientas para fines especiales. Una de esas herramientas es ArchUnit, Un marco de pruebas
Java inspirado en varias partes de JUnit y que las utiliza Ecosistema. ArchUnit proporciona una variedad de
reglas de gobernanza predefinidas codificadas como pruebas unitarias y permite a los arquitectos escribir
pruebas específicas que aborden la modularidad. Considere la arquitectura en capas ilustrada en la Figura 64.
Al diseñar un monolito en capas como el de la Figura 64, el arquitecto define las capas por una buena razón
(las motivaciones, las compensaciones y otros aspectos de la arquitectura en capas se describen en el
Capítulo 10). Sin embargo, ¿cómo puede el arquitecto asegurarse de que los desarrolladores respeten esas
capas? Algunos desarrolladores pueden no entender 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 daña la
salud a largo plazo de la arquitectura.
ArchUnit permite a los arquitectos abordar este problema a través de una función de aptitud, que se muestra
en el Ejemplo 64.
.whereLayer("Controlador").mayNotBeAccessedByAnyLayer() .whereLayer("Servicio").mayOnlyBeAccessedByLayers("C
En el Ejemplo 64, el arquitecto define la relación deseable entre capas y escribe una función de aptitud de
verificación para gobernarla.
Una herramienta similar en el espacio .NET, NetArchTest, permite pruebas similares para esa plataforma;
una verificación de capa en C# aparece en el Ejemplo 65.
// Las clases en la presentación no deben hacer referencia directa a los repositorios var
result = Types.InCurrentDomain()
.Eso()
.ResideInNamespace("NetArchTest.SampleLibrary.Presentación")
.No debería()
.HaveDependencyOn("NetArchTest.SampleLibrary.Data")
.Obtener resultado()
.Es exitoso;
Otro ejemplo de funciones de fitness es Chaos Monkey de Netflix y el Simian Army que lo acompaña. En
particular, los monos Conformity, Security y Janitor son un ejemplo de este enfoque. El mono Conformity
permite a los arquitectos de Netflix definir reglas de gobernanza que el mono aplica en producción. Por
ejemplo, si los arquitectos deciden que cada servicio debe responder de manera útil a todos los verbos
RESTful, incorporan esa comprobación en el mono Conformity. De manera similar, el mono Security
comprueba cada servicio en busca de defectos de seguridad conocidos, como puertos que no deberían
estar activos y errores de configuración. Finalmente, el mono Janitor busca instancias a las que ya no se
dirigen otros servicios. Netflix tiene una arquitectura evolutiva, por lo que los desarrolladores migran
rutinariamente a servicios más nuevos, dejando los servicios antiguos en funcionamiento sin colaboradores.
Debido a que los servicios que se ejecutan en la nube consumen dinero, el mono Janitor busca servicios
huérfanos y los desintegra fuera de producción.
La ingeniería del caos ofrece una perspectiva nueva e interesante sobre la arquitectura: no se trata
de si algo se romperá en algún momento, sino de cuándo. Anticipar esas roturas y realizar pruebas
para prevenirlas hace que los sistemas sean mucho más robustos.
Hace unos años se publicó el influyente libro The Checklist Manifesto Atul Gawande (Picador)
describió cómo profesiones como los pilotos de aerolíneas y los cirujanos utilizan listas de
verificación (a veces obligatorias por ley). No es porque esos profesionales no conozcan su trabajo
o sean olvidadizos. Más bien, cuando los profesionales hacen un trabajo altamente detallado una y
otra vez, se vuelve fácil que los detalles se pasen por alto; una lista de verificación sucinta constituye
un recordatorio eficaz. Esta es la perspectiva correcta sobre las funciones de aptitud: en lugar de
un mecanismo de gobernanza de peso pesado, las funciones de aptitud proporcionan un mecanismo
para que los arquitectos expresen principios arquitectónicos importantes y los verifiquen
automáticamente. Los desarrolladores saben que no deben publicar código inseguro, pero esa
prioridad compite con docenas o cientos de otras prioridades para los desarrolladores ocupados.
Herramientas como Security Monkey específicamente, y las funciones de aptitud en general,
permiten a los arquitectos codificar controles de gobernanza importantes en el sustrato de la arquitectura.
CAPÍTULO 7
Durante la redacción de Construyendo arquitecturas evolutivas En este libro, los autores necesitaban
una técnica para medir la capacidad de evolución estructural de estilos arquitectónicos particulares.
Ninguna de las medidas existentes ofrecía el nivel correcto de detalle. En “Medidas estructurales” en
la página 79, analizamos una variedad de métricas a nivel de código que permiten a los arquitectos
analizar aspectos estructurales de una arquitectura. Sin embargo, todas estas métricas solo revelan
detalles de bajo nivel sobre el código y no pueden evaluar componentes dependientes (como bases
de datos) fuera de la base de código que aún impactan en muchas características de la arquitectura,
especialmente las operativas. Por ejemplo, no importa cuánto esfuerzo ponga un arquitecto en
diseñar una base de código elástica o de alto rendimiento, si el sistema usa una base de datos que
no coincide con esas características, la aplicación no tendrá éxito.
91
Machine Translated by Google
Acoplamiento y connascencia
Muchas de las métricas de acoplamiento a nivel de código, como el acoplamiento aferente y eferente
(descrito en “Medidas estructurales” en la página 79), revelan detalles a un nivel demasiado fino para el
análisis arquitectónico. En 1996, Meilir PageJones publicó un libro titulado What Every Programmer Should
Know About Object Oriented Design (Lo que todo programador debería saber sobre el diseño orientado a
objetos) (Dorset House) que incluía varias nuevas medidas de acoplamiento que él llamó connascence, que
se define de la siguiente manera:
Conocimiento
Dos componentes son connascentes si un cambio en uno requeriría que se modificara el otro para
mantener la corrección general del sistema.
Definió dos tipos de connascencia: estática, detectable mediante análisis de código estático, y dinámica,
relacionada con el comportamiento en tiempo de ejecución. Para definir la arquitectura cuántica, necesitábamos
una medida de cómo se “conectan” entre sí los componentes, lo que corresponde al concepto de connascencia.
Por ejemplo, si dos servicios en una arquitectura de microservicios comparten la misma definición de clase de
alguna clase, como la dirección, decimos que son estáticamente connascentes entre sí; cambiar la clase
compartida requiere cambios en ambos servicios.
Para la conexión dinámica, definimos dos tipos: sincrónica y asincrónica. Las llamadas sincrónicas entre
dos servicios distribuidos hacen que el que llama espere la respuesta del que recibe la llamada. Por otro
lado, las llamadas asincrónicas permiten una semántica de "disparar y olvidar" en arquitecturas basadas en
eventos, lo que permite que dos servicios diferentes difieran en la arquitectura operativa.
Muchos desarrolladores con conocimientos científicos conocen el concepto de cuántico, que se refiere a la
cantidad mínima de cualquier entidad física involucrada en una interacción. La palabra cuántico deriva del
latín y significa “cuánto” o “cuánto”. Hemos adoptado esta noción para definir una arquitectura cuántica:
Arquitectura cuántica
Un artefacto desplegable de forma independiente con alta cohesión funcional y conexión sincrónica.
Desplegable de forma
independiente Una arquitectura cuántica incluye todos los componentes necesarios para funcionar
independientemente de otras partes de la arquitectura. Por ejemplo, si una aplicación utiliza una base de
datos, es parte de la cuántica porque el sistema no funcionará sin ella. Este requisito significa que
prácticamente todos los sistemas heredados implementados utilizando una única base de datos forman, por
definición, un quantum de uno. Sin embargo, en el estilo de arquitectura de microservicios, cada servicio
incluye su propia base de datos (parte de la filosofía de contexto limitado que impulsa los microservicios,
que se describe en detalle en el Capítulo 17), lo que crea múltiples quanta dentro de esa arquitectura.
Una alta cohesión funcional implica que una arquitectura cuántica hace algo con un propósito. Esta distinción
importa poco en aplicaciones monolíticas tradicionales con una única base de datos. Sin embargo, en las
arquitecturas de microservicios, los desarrolladores suelen diseñar cada servicio para que coincida con un
único flujo de trabajo (un contexto delimitado, como se describe en “Contexto delimitado del diseño basado
en dominios” en la página 94), lo que muestra una alta cohesión funcional.
Connascence sincrónico El
connascence sincrónico implica llamadas sincrónicas dentro de un contexto de aplicación o
entre servicios distribuidos que forman este quantum de arquitectura. Por ejemplo, si un servicio
en una arquitectura de microservicios llama a otro sincrónicamente, cada servicio no puede
exhibir diferencias extremas en las características de la arquitectura operativa. Si el que llama
es mucho más escalable que el que recibe la llamada, se producirán tiempos de espera y otros
problemas de confiabilidad. Por lo tanto, las llamadas sincrónicas crean connascence dinámico
durante la duración de la llamada: si uno está esperando al otro, sus características de
arquitectura operativa deben ser las mismas durante la duración de la llamada.
En el Capítulo 6, definimos la relación entre las métricas de acoplamiento tradicionales y la connascencia, que no
incluía nuestra nueva medida de connascencia de comunicación.
Actualizamos este diagrama en la Figura 71.
Para otro ejemplo, considere una arquitectura de microservicios con un servicio de Pago y
un servicio de Subasta . Cuando finaliza una subasta, el servicio de Subasta envía
información de pago al servicio de Pago . Sin embargo, digamos que el servicio de pago
solo puede manejar un pago cada 500 ms: ¿qué sucede cuando finaliza una gran cantidad
de subastas a la vez? Una arquitectura mal diseñada permitiría que la primera llamada se
realice y permitiría que las demás agoten el tiempo de espera. Alternativamente, un
arquitecto podría diseñar un enlace de comunicación asincrónico entre Pago y Subasta, lo
que permitiría que la cola de mensajes almacene temporalmente las diferencias. En este
caso, la conexión asincrónica crea una arquitectura más flexible. Cubrimos este tema en
gran detalle en el Capítulo 14.
El concepto de arquitectura cuántica proporciona un nuevo alcance para las características de la arquitectura. En
los sistemas modernos, los arquitectos definen las características de la arquitectura a nivel cuántico en lugar de a
nivel del sistema. Al considerar un alcance más estrecho para las preocupaciones operativas importantes, los
arquitectos pueden identificar los desafíos arquitectónicos de manera temprana, lo que conduce a arquitecturas
híbridas. Para ilustrar el alcance proporcionado por la medida cuántica de la arquitectura, considere otro kata de
arquitectura: Going, Going, Gone.
5, presentamos el concepto de kata de arquitectura. Consideremos este caso, relacionado con una empresa de
subastas en línea. Aquí está la descripción del kata de arquitectura:
Descripción
Una empresa de subastas quiere llevar sus subastas en línea a escala nacional. Los clientes eligen la
subasta en la que participarán, esperan hasta que comience y luego pujan como si estuvieran en la sala con
el subastador.
Usuarios
Amplíe hasta cientos de participantes por subasta, potencialmente hasta miles de participantes y tantas
subastas simultáneas como sea posible.
Requisitos • Las
subastas deben ser lo más en tiempo real posible. • Los
postores se registran con una tarjeta de crédito; el sistema carga automáticamente la tarjeta si
El postor gana.
reputación. • Los postores pueden ver una transmisión de video en vivo de la subasta y todas las
ofertas a medida que ocurren. • Las ofertas en línea y en vivo deben recibirse en el orden en que se realizan.
Contexto adicional
• La empresa de subastas se está expandiendo agresivamente fusionándose con empresas más pequeñas.
competidores.
La empresa acaba de salir de un proceso judicial en el que se llegó a un acuerdo por fraude.
Tal como se muestra en el “Estudio de caso: Sándwiches de silicio” en la página 69, un arquitecto debe considerar
cada uno de estos requisitos para determinar las características de la arquitectura:
1. “Escala nacional”, “escalar hasta cientos de participantes por subasta, potencialmente hasta miles de
participantes y tantas subastas simultáneas como sea posible”, “las subastas deben ser lo más en tiempo
real posible”.
Cada uno de estos requisitos implica tanto la escalabilidad para soportar la gran cantidad de usuarios como la
elasticidad para soportar la naturaleza explosiva de las subastas. Si bien los requisitos mencionan explícitamente
la escalabilidad, la elasticidad representa una característica implícita basada en el dominio del problema. Al
considerar las subastas, ¿los usuarios se distribuyen educadamente durante el curso de la puja o se vuelven más
frenéticos cerca del final? El conocimiento del dominio es crucial para que los arquitectos capten las características
implícitas de la arquitectura. Dada la naturaleza en tiempo real de las subastas, un arquitecto sin duda considerará
el rendimiento como una característica clave de la arquitectura.
2. “Los postores se registran con una tarjeta de crédito; el sistema carga automáticamente la tarjeta si el postor gana”,
“la empresa acaba de salir de una demanda en la que se llegó a un acuerdo por una supuesta estafa”.
Sin embargo, la segunda frase debería hacer que el arquitecto se detuviera y pidiera más aclaraciones. Es evidente
que algún aspecto de la seguridad (el fraude) fue un problema en el pasado, por lo que el arquitecto debería pedir
más información sin importar el nivel de seguridad que diseñe.
Este requisito sugiere algunos nombres extravagantes como “antitrollability”, pero la parte del requisito relacionada
con el seguimiento puede sugerir algunas características de la arquitectura como la auditabilidad y la registrabilidad.
El factor decisivo vuelve a ser la característica definitoria: ¿está fuera del alcance del dominio del problema? Los
arquitectos deben recordar que el análisis para obtener características de la arquitectura representa solo una
pequeña parte del esfuerzo general para diseñar e implementar una aplicación; ¡gran parte del trabajo de diseño
ocurre más allá de esta fase! Durante esta parte de la definición de la arquitectura, los arquitectos buscan requisitos
con impacto estructural que no estén cubiertos por el dominio.
He aquí una prueba de fuego útil que los arquitectos utilizan para determinar entre
La diferencia entre las características de dominio y arquitectura es: ¿requiere conocimiento del dominio para
implementarlo o es una característica abstracta de la arquitectura? En el kata Going, Going, Gone, un arquitecto al
encontrarse con la frase “índice de reputación”
Busque un analista de negocios u otro experto en la materia para que le explique lo que tenían
en mente. En otras palabras, la frase "índice de reputación" no es una definición estándar como
las características de arquitectura más comunes. Como contraejemplo, cuando los arquitectos
hablan de elasticidad, la capacidad de manejar ráfagas de usuarios, pueden hablar de la
característica de arquitectura puramente en abstracto, sin importar qué tipo de aplicación
consideren: banca, sitio de catálogo, transmisión de video, etc. Los arquitectos deben determinar
si un requisito no está ya abarcado por el dominio y requiere una estructura particular, lo que
eleva una consideración a la característica de arquitectura.
4. “La empresa de subastas se está expandiendo agresivamente fusionándose con empresas más pequeñas
competidores.”
Si bien este requisito puede no tener un impacto inmediato en el diseño de la aplicación, puede
convertirse en el factor determinante en una disyuntiva entre varias opciones. Por ejemplo, los arquitectos
a menudo deben elegir detalles como los protocolos de comunicación para la arquitectura de integración:
si la integración con empresas recién fusionadas no es una preocupación, el arquitecto puede elegir algo
muy específico para el problema. Por otro lado, un arquitecto puede elegir algo que no sea perfecto para
dar cabida a alguna disyuntiva adicional, como la interoperabilidad. Las características arquitectónicas
implícitas sutiles como esta impregnan la arquitectura, lo que ilustra por qué hacer bien el trabajo
presenta desafíos.
Algunas katas de arquitectura imponen restricciones presupuestarias a la solución para representar una
solución intermedia común en el mundo real. Sin embargo, en la kata Going, Going, Gone, esto no es
así. Esto permite al arquitecto elegir arquitecturas más elaboradas o con propósitos especiales, que
serán beneficiosas dados los próximos requisitos.
6. “Los postores pueden ver una transmisión de video en vivo de la subasta y todas las ofertas a medida que
ocurren”, “las ofertas tanto en línea como en vivo deben recibirse en el orden en que se realizan”.
Este requisito presenta un desafío arquitectónico interesante, que definitivamente afecta la estructura de
la aplicación y expone la inutilidad de tratar las características de la arquitectura como una evaluación de
todo el sistema. Considere la disponibilidad: ¿es esa necesidad uniforme en toda la arquitectura? En
otras palabras, ¿es la disponibilidad de un postor más importante que la disponibilidad de uno de los
cientos de postores? Obviamente, el arquitecto desea buenas medidas para ambos, pero una es
claramente más crítica: si el subastador no puede acceder al sitio, no se pueden realizar ofertas en línea
para nadie. La confiabilidad aparece comúnmente con la disponibilidad; aborda aspectos operativos
como el tiempo de actividad, así como la integridad de los datos y otras medidas de cuán confiable es
una aplicación. Por ejemplo, en un sitio de subastas, el arquitecto debe asegurarse de que el orden de
los mensajes sea confiablemente correcto, eliminando las condiciones de carrera y otros problemas.
Este último requisito en el kata Going, Going, Gone destaca la necesidad de un alcance más granular en la
arquitectura que el nivel del sistema. Al utilizar la medida cuántica de la arquitectura, los arquitectos delimitan
las características de la arquitectura a nivel cuántico. Por ejemplo, en Going, Going, Gone, un arquitecto
notaría que diferentes partes de esta arquitectura necesitan diferentes características: las ofertas en
streaming, los postores en línea y el subastador son tres opciones obvias. Los arquitectos utilizan la medida
cuántica de la arquitectura como una forma de pensar en la implementación, el acoplamiento, dónde deben
residir los datos y los estilos de comunicación dentro de las arquitecturas. En este kata, un arquitecto puede
analizar las diferentes características de la arquitectura por quantum de arquitectura, lo que lleva al diseño
de la arquitectura híbrida en una etapa más temprana del proceso.
Así, para Going, Going, Gone, identificamos los siguientes cuantos y las características de arquitectura
correspondientes:
• Disponibilidad •
Escalabilidad
• Actuación
Subastador
El subastador en vivo
• Disponibilidad •
Confiabilidad •
Escalabilidad •
Elasticidad •
Rendimiento
• Seguridad
Licitador
• Confiabilidad
• Disponibilidad •
Escalabilidad •
Elasticidad
CAPÍTULO 8
En el Capítulo 3, analizamos los módulos como una colección de código relacionado. Sin embargo, los
arquitectos suelen pensar en términos de componentes, la manifestación física de un módulo.
Los desarrolladores empaquetan físicamente los módulos de diferentes maneras, a veces dependiendo de
su plataforma de desarrollo. Llamamos empaquetado físico de módulos a los componentes. La mayoría de
los lenguajes también admiten el empaquetado físico: archivos jar en Java, dll en .NET, gem en Ruby, etc.
En este capítulo, analizamos las consideraciones arquitectónicas en torno a los componentes, que van desde
el alcance hasta el descubrimiento.
A los desarrolladores les resulta útil subdividir el concepto de componente en función de una amplia gama
de factores, algunos de los cuales aparecen en la Figura 81.
Los componentes ofrecen un mecanismo específico del lenguaje para agrupar artefactos, a menudo
anidándolos para crear estratificación. Como se muestra en la Figura 81, el componente más simple
envuelve el código a un nivel de modularidad más alto que las clases (o funciones, en lenguajes no
orientados a objetos). Este envoltorio simple a menudo se denomina biblioteca, que tiende a ejecutarse en la
misma dirección de memoria que el código que realiza la llamada y comunicarse a través de mecanismos de
llamada a funciones del lenguaje. Las bibliotecas suelen ser dependencias en tiempo de compilación (con
notables excepciones como las bibliotecas de vínculos dinámicos [DLL] que fueron la pesadilla de los
usuarios de Windows durante muchos años).
99
Machine Translated by Google
Los componentes también aparecen como subsistemas o capas en la arquitectura, como la unidad de
trabajo implementable para muchos procesadores de eventos. Otro tipo de componente, un servicio,
tiende a ejecutarse en su propio espacio de direcciones y se comunica a través de protocolos de red de
bajo nivel como TCP/IP o formatos de nivel superior como REST o colas de mensajes, formando
unidades independientes implementables en arquitecturas como los microservicios.
Nada obliga a un arquitecto a utilizar componentes, simplemente sucede que a menudo resulta útil tener
un nivel de modularidad más alto que el nivel más bajo que ofrece el lenguaje. Por ejemplo, en las
arquitecturas de microservicios, la simplicidad es uno de los principios arquitectónicos. Por lo tanto, un
servicio puede constar de suficiente código para justificar componentes o puede ser lo suficientemente
simple como para contener solo un pequeño fragmento de código, como se ilustra en la Figura 82.
Los componentes forman el bloque de construcción modular fundamental en la arquitectura, lo que los
convierte en un elemento fundamental para los arquitectos. De hecho, una de las principales decisiones
que debe tomar un arquitecto se refiere a la partición de alto nivel de los componentes en la arquitectura.
Figura 82. Un microservicio puede tener tan poco código que los componentes no sean necesarios
Por lo general, el arquitecto define, perfecciona, administra y gobierna los componentes dentro de una
arquitectura. Los arquitectos de software, en colaboración con analistas de negocios, expertos en la
materia, desarrolladores, ingenieros de control de calidad, operaciones y arquitectos empresariales,
crean el diseño inicial del software, incorporando las características de la arquitectura analizadas en el
Capítulo 4 y los requisitos del sistema de software.
Prácticamente todos los detalles que cubrimos en este libro existen independientemente del proceso
de desarrollo de software que utilicen los equipos: la arquitectura es independiente del proceso de
desarrollo. La principal excepción a esta regla son las prácticas de ingeniería que se iniciaron en los
distintos tipos de desarrollo de software ágil, en particular en las áreas de implementación y
automatización de la gobernanza. Sin embargo, en general, la arquitectura de software existe
separada del proceso. Por lo tanto, a los arquitectos, en última instancia, no les importa dónde se
originan los requisitos: un proceso formal de diseño conjunto de aplicaciones (JAD), un análisis y
diseño extensos en cascada, tarjetas de historias ágiles... o cualquier variación híbrida de ellos.
Generalmente, el componente es el nivel más bajo del sistema de software con el que interactúa
directamente un arquitecto, con la excepción de muchas de las métricas de calidad del código analizadas
en el Capítulo 6 que afectan a las bases de código de manera holística. Los componentes consisten en
clases o funciones (dependiendo de la plataforma de implementación), cuyo diseño es responsabilidad
de los líderes técnicos o desarrolladores. No es que los arquitectos no deban involucrarse en el diseño
de clases (particularmente cuando descubren o aplican patrones de diseño), pero deben evitar
microgestionar cada decisión de arriba a abajo en el sistema. Si los arquitectos nunca permiten que
otros roles tomen decisiones importantes, la organización tendrá dificultades para empoderar a la
próxima generación de arquitectos.
Un arquitecto debe identificar los componentes como una de las primeras tareas de un nuevo
proyecto. Pero antes de poder identificarlos, debe saber cómo dividir la arquitectura.
Particionado de la arquitectura La
primera ley de la arquitectura de software establece que todo en el software es un equilibrio, incluida la
forma en que los arquitectos crean componentes en una arquitectura. Debido a que los componentes
representan un mecanismo general de contenedorización, un arquitecto puede crear cualquier tipo de
particionamiento que desee. Existen varios estilos comunes, con diferentes conjuntos de compensaciones.
Analizamos los estilos de arquitectura en profundidad en la Parte II. Aquí analizamos un aspecto importante
de los estilos, el particionamiento de nivel superior en una arquitectura.
Considere los dos tipos de estilos de arquitectura que se muestran en la Figura 83.
Figura 83. Dos tipos de particionamiento de arquitectura de nivel superior: en capas y modular
En la Figura 83, un tipo de arquitectura que resulta familiar para muchos es el monolito en capas (que se
analiza en detalle en el Capítulo 10). El otro es un estilo arquitectónico popularizado por Simon Brown. Se
denomina monolito modular a una unidad de implementación única asociada a una base de datos y dividida
en dominios en lugar de en capacidades técnicas. Estos dos estilos representan diferentes formas de dividir
la arquitectura en el nivel superior. Tenga en cuenta que en cada variación, cada uno de los componentes de
nivel superior (capas o componentes) probablemente tenga otros componentes integrados en su interior. La
partición de nivel superior es de particular interés para los arquitectos porque define el estilo de arquitectura
fundamental y la forma de dividir el código.
La arquitectura organizativa basada en capacidades técnicas, como el monolito en capas, representa una
partición técnica de nivel superior. Una versión común de esto aparece en la Figura 84.
En la Figura 84, el arquitecto ha dividido la funcionalidad del sistema en capacidades técnicas: presentación,
reglas de negocio, servicios, persistencia, etc. Esta forma de organizar una base de código tiene sentido. Todo
el código de persistencia reside en una capa de la arquitectura, lo que facilita a los desarrolladores encontrar
el código relacionado con la persistencia. Aunque el concepto básico de la arquitectura en capas es anterior a
ella en décadas, el patrón de diseño ModeloVistaControlador coincide con este patrón arquitectónico, lo que
facilita su comprensión por parte de los desarrolladores. Por lo tanto, a menudo es la arquitectura
predeterminada en muchas organizaciones.
Un efecto secundario interesante del predominio de la arquitectura en capas se relaciona con la forma en que
las empresas asignan los distintos roles de proyecto. Cuando se utiliza una arquitectura en capas, tiene cierto
sentido que todos los desarrolladores de backend se sienten juntos en un departamento, los administradores
de bases de datos en otro, el equipo de presentación en otro, y así sucesivamente. Debido a la ley de Conway,
esto tiene cierto sentido en esas organizaciones.
Ley de Conway
A finales de la década de 1960, Melvin Conway Hizo una observación que se conoció como
la ley de Conway:
Las organizaciones que diseñan sistemas… están limitadas a producir diseños que son copias de las
estructuras de comunicación de esas organizaciones.
Parafraseada, esta ley sugiere que cuando un grupo de personas diseña algún artefacto
técnico, las estructuras de comunicación entre las personas terminan replicadas en el
Diseño. Las personas en todos los niveles de las organizaciones ven esta ley en acción y, a veces, toman
decisiones basadas en ella. Por ejemplo, es común que las organizaciones dividan a los trabajadores en
función de sus capacidades técnicas, lo que tiene sentido desde un sentido puramente organizacional, pero
dificulta la colaboración debido a la separación artificial de las capacidades comunes.
preocupaciones.
Una observación relacionada acuñada por Jonny Leroy de ThoughtWorks es la Maniobra Inversa de Conway ,
lo que sugiere evolucionar el equipo y la estructura organizacional en conjunto para promover la arquitectura
deseada.
La otra variación arquitectónica en la Figura 84 representa la partición de dominios, inspirada en el libro de
Eric Evan DomainDriven Design, que es una técnica de modelado para descomponer sistemas de software
complejos. En DDD, el arquitecto identifica dominios o flujos de trabajo independientes y desacoplados
entre sí. El estilo de arquitectura de microservicios (discutido en el Capítulo 17) se basa en esta filosofía. En
un monolito modular, el arquitecto particiona la arquitectura en torno a dominios o flujos de trabajo en lugar
de capacidades técnicas. Como los componentes a menudo se anidan unos dentro de otros, cada uno de
los componentes en la Figura 84 en la partición de dominios (por ejemplo, CatalogCheckout) puede usar
una biblioteca de persistencia y tener una capa separada para reglas comerciales, pero la partición de nivel
superior gira en torno a dominios.
Una de las distinciones fundamentales entre los diferentes patrones de arquitectura es el tipo de partición
de nivel superior que cada uno admite, que abordamos para cada patrón individual. También tiene un gran
impacto en cómo un arquitecto decide cómo identificar inicialmente los componentes: ¿el arquitecto desea
dividir las cosas técnicamente o por dominio?
Los arquitectos que utilizan particionamiento técnico organizan los componentes del sistema según sus
capacidades técnicas: presentación, reglas de negocio, persistencia, etc. Por lo tanto, uno de los principios
organizadores de esta arquitectura es la separación de las preocupaciones técnicas.
Esto, a su vez, crea niveles útiles de desacoplamiento: si la capa de servicio solo está conectada a la capa
de persistencia que se encuentra debajo y a la capa de reglas de negocios que se encuentra arriba,
entonces los cambios en la persistencia solo afectarán potencialmente a esas capas. Este estilo de partición
proporciona una técnica de desacoplamiento, lo que reduce los efectos secundarios de propagación en los
componentes dependientes. Tratamos más detalles de este estilo de arquitectura en el patrón de arquitectura
en capas del Capítulo 10. Sin duda, es lógico organizar los sistemas utilizando particiones técnicas, pero,
como todo en la arquitectura de software, esto ofrece algunas desventajas.
La separación que impone la partición técnica permite a los desarrolladores encontrar rápidamente
determinadas categorías de la base de código, ya que está organizada por capacidades. Sin embargo, la
mayoría de los sistemas de software realistas requieren flujos de trabajo que abarquen todas las capacidades técnicas.
Considere el flujo de trabajo empresarial común de CatalogCheckout. El código para gestionar
CatalogCheckout en la arquitectura técnica en capas aparece en todas las capas, como se muestra en la
Figura 85.
Figura 85. Dónde aparecen los dominios y flujos de trabajo en arquitecturas particionadas por
dominios y técnicas
Ninguno de estos estilos es más correcto que el otro (consulte la Primera Ley de la Arquitectura de
Software). Dicho esto, hemos observado una marcada tendencia en la industria durante los últimos años
hacia la partición de dominios para las arquitecturas monolíticas y distribuidas (por ejemplo,
microservicios). Sin embargo, es una de las primeras decisiones que debe tomar un arquitecto.
el caso de uno de nuestros katas de ejemplo, “Estudio de caso: sándwiches de silicio” en la página 69.
Al derivar componentes, una de las decisiones fundamentales que enfrenta un arquitecto es la partición
de nivel superior. Considere la primera de dos posibilidades diferentes para sándwiches de silicio, una
partición de dominio, ilustrada en la Figura 86.
Un diseño alternativo aísla las partes comunes y locales en su propia partición, como se ilustra en la
Figura 87. Las partes comunes y locales representan los componentes de nivel superior, y las partes
de compra y entrega se encargan de gestionar el flujo de trabajo.
Particionado de
dominios Las arquitecturas particionadas por dominios separan los componentes de nivel superior por
flujos de trabajo y/o dominios.
Ventajas •
Modelado más de cerca hacia cómo funciona el negocio en lugar de una implementación.
Detalle de la mentación
• Es más fácil utilizar la maniobra de Conway inversa para crear equipos multifuncionales.
alrededor de dominios
Desventaja • El
código de personalización aparece en varios lugares.
arquitecturas particionadas técnicamente separan los componentes de nivel superior en función de las
capacidades técnicas en lugar de flujos de trabajo discretos. Esto puede manifestarse como capas
inspiradas en la separación ModeloVistaControlador o alguna otra partición técnica ad hoc.
La Figura 87 separa los componentes según la personalización.
Ventajas •
Separa claramente el código de personalización. • Se
Desventajas • Mayor
grado de acoplamiento global. Los cambios en los componentes comunes o locales pueden
Es probable que el cambio afecte a todos los demás componentes.
• Los desarrolladores pueden tener que duplicar conceptos de dominio tanto en dominios comunes como locales.
Capas.
• Normalmente, el acoplamiento a nivel de datos es mayor. En un sistema como este, los arquitectos de datos y de
aplicaciones probablemente colaborarían para crear una única base de datos, que incluyera la personalización y los
dominios. Eso, a su vez, genera dificultades para desenredar las relaciones de datos si los arquitectos desean migrar
más adelante esta arquitectura a un sistema distribuido.
Muchos otros factores influyen en la decisión de un arquitecto sobre en qué estilo arquitectónico basar su diseño, los
cuales se tratan en la Parte II.
Rol de desarrollador
Los desarrolladores suelen tomar componentes, diseñados en conjunto con el rol de arquitecto, y
subdividirlos en clases, funciones o subcomponentes. En general, el diseño de clases y funciones es
responsabilidad compartida de arquitectos, líderes técnicos y desarrolladores, y la mayor parte corresponde
a los roles de desarrollador.
Los desarrolladores nunca deben tomar los componentes diseñados por los arquitectos como la última
palabra; todo diseño de software se beneficia de la iteración. En cambio, ese diseño inicial debe verse
como un primer borrador, donde la implementación revelará más detalles y mejoras.
Este ciclo describe un ciclo de exposición de arquitectura genérica. Ciertos dominios especializados pueden
insertar otros pasos en este proceso o cambiarlo por completo. Por ejemplo, en algunos dominios, parte
del código debe someterse a pasos de seguridad o auditoría en este proceso.
Las descripciones de cada paso de la Figura 88 aparecen en las siguientes secciones.
Antes de que exista cualquier código para un proyecto de software, el arquitecto debe determinar de alguna
manera con qué componentes de nivel superior comenzar, en función del tipo de partición de nivel superior
que elija. Más allá de eso, un arquitecto tiene la libertad de crear los componentes que desee y luego
asignarles la funcionalidad del dominio para ver dónde debería residir el comportamiento. Si bien esto
puede parecer arbitrario, es difícil comenzar con algo más concreto si un arquitecto diseña un sistema
desde cero. La probabilidad de lograr un buen diseño a partir de este conjunto inicial de componentes es
despectivamente pequeña, por lo que los arquitectos deben iterar sobre el diseño de componentes para
mejorarlo.
arquitecto ha identificado los componentes iniciales, el siguiente paso es alinear los requisitos (o historias
de usuario) con esos componentes para ver qué tan bien encajan. Esto puede implicar crear nuevos
componentes, consolidar los existentes o desmantelar componentes porque tienen demasiada
responsabilidad. Este mapeo no tiene que ser exacto: el arquitecto está intentando encontrar un buen
sustrato de grano grueso para permitir un mayor diseño y refinamiento por parte de arquitectos, líderes
técnicos y/o desarrolladores.
historias a los componentes, el arquitecto también analiza los roles y las responsabilidades que se
explicaron durante los requisitos para asegurarse de que la granularidad coincida. Pensar en los roles y
los comportamientos que debe admitir la aplicación le permite al arquitecto alinear la granularidad del
componente y del dominio. Uno de los mayores desafíos para los arquitectos implica descubrir la
granularidad correcta para los componentes, lo que fomenta el enfoque iterativo descrito aquí.
asignar requisitos a los componentes, el arquitecto también debe observar las características de la
arquitectura descubiertas anteriormente para pensar en cómo podrían afectar la división y granularidad
de los componentes. Por ejemplo, mientras que dos partes de un sistema pueden lidiar con la entrada
del usuario, la parte que se ocupa de cientos de usuarios simultáneos necesitará características de
arquitectura diferentes a otra parte que necesita soportar solo unos pocos. Por lo tanto, mientras que
una vista puramente funcional del diseño de componentes puede producir un solo componente para
manejar la interacción del usuario, el análisis de las características de la arquitectura conducirá a una
subdivisión.
retroalimentación es fundamental en el diseño de software. Por lo tanto, los arquitectos deben iterar
continuamente el diseño de sus componentes con los desarrolladores. El diseño de software presenta
todo tipo de dificultades inesperadas: nadie puede anticipar todos los problemas desconocidos que
suelen ocurrir durante los proyectos de software. Por lo tanto, un enfoque iterativo para el diseño de
componentes es clave. En primer lugar, es prácticamente imposible tener en cuenta todos los diferentes
descubrimientos y casos extremos que surgirán y que fomentarán el rediseño. En segundo lugar, a
medida que la arquitectura y los desarrolladores profundizan más en la creación de la aplicación, obtienen
una comprensión más matizada de dónde deberían ubicarse el comportamiento y los roles.
Granularidad de componentes
Encontrar la granularidad adecuada para los componentes es una de las tareas más difíciles de un
arquitecto. Un diseño de componentes demasiado detallado genera demasiada comunicación entre los
componentes para lograr resultados. Los componentes demasiado detallados fomentan un alto acoplamiento
interno, lo que genera dificultades en la capacidad de implementación y de prueba, así como efectos
secundarios negativos relacionados con la modularidad.
Diseño de componentes
No existe una forma “correcta” aceptada de diseñar componentes. Más bien, existe una amplia variedad de
técnicas, todas con diferentes ventajas y desventajas. En todos los procesos, un arquitecto toma los
requisitos e intenta determinar qué bloques de construcción de grano grueso conformarán la aplicación.
Existen muchas técnicas diferentes, todas con diferentes ventajas y desventajas y acopladas al proceso de
desarrollo de software utilizado por el equipo y la organización.
Aquí hablamos de algunas formas generales de descubrir componentes y trampas a evitar.
arquitectos, a menudo en colaboración con otros roles como desarrolladores, analistas de negocios y
expertos en la materia, crean un diseño de componente inicial basado en el conocimiento general del
sistema y en cómo deciden descomponerlo, según la partición técnica o de dominio. El objetivo del equipo
es un diseño inicial que divida el espacio del problema en fragmentos gruesos que tengan en cuenta las
diferentes características de la arquitectura.
Trampa de
entidad Si bien no existe una única forma verdadera de determinar los componentes, acecha un antipatrón
común: la trampa de entidad. Supongamos que un arquitecto está trabajando en el diseño de componentes
para nuestro kata Going, Going, Gone y termina con un diseño similar a la Figura 89.
En la Figura 89, el arquitecto básicamente ha tomado cada entidad identificada en los requisitos y
ha creado un componente Manager basado en esa entidad. Esto no es una arquitectura; es un
mapeo relacional de objetos (ORM) de un marco a una base de datos. En otras palabras, si un
sistema solo necesita operaciones CRUD simples de base de datos (crear, leer, actualizar, eliminar),
entonces el arquitecto puede descargar un marco para crear interfaces de usuario directamente
desde la base de datos. Existen muchos marcos ORM populares para resolver este comportamiento
CRUD común.
década, apareció una familia de frameworks que hacen que la creación de aplicaciones CRUD simples
sea trivial, ejemplificada por Naked Objects (que desde entonces se ha dividido en dos proyectos, una
versión .NET todavía llamada NakedObjects, y una versión Java que se trasladó a la fundación de
código abierto Apache bajo el nombre Isis). La premisa detrás de estos frameworks es construir una
interfaz de usuario basada en entidades de bases de datos. Por ejemplo, en Naked Objects, el
desarrollador apunta el framework a las tablas de la base de datos y el framework construye una
interfaz de usuario basada en las tablas y sus relaciones definidas.
Existen otros marcos populares que básicamente proporcionan una interfaz de usuario predeterminada
basada en la estructura de la tabla de la base de datos: la función de andamiaje de Ruby on Rails El
marco proporciona el mismo tipo de asignaciones predeterminadas del sitio web a la base de datos
(con muchas opciones para ampliar y agregar sofisticación a la aplicación resultante).
Si las necesidades de un arquitecto requieren simplemente un mapeo simple de una base de datos a
una interfaz de usuario, no es necesaria una arquitectura completa; uno de estos marcos será suficiente.
Enfoque de actores/
acciones El enfoque de actores/acciones es una forma popular que utilizan los arquitectos para
asignar requisitos a componentes. En este enfoque, definido originalmente por el Proceso
Unificado Racional, los arquitectos identifican a los actores que realizan actividades con la
aplicación y las acciones que esos actores pueden realizar. Proporciona una técnica para
descubrir los usuarios típicos del sistema y qué tipo de cosas podrían hacer con el sistema.
ción del diseño inicial. Sigue siendo popular y funciona bien cuando los requisitos presentan roles
diferenciados y los tipos de acciones que pueden realizar. Este estilo de descomposición de
componentes funciona bien para todo tipo de sistemas, monolíticos o distribuidos.
Event storming
El evento storming como técnica de descubrimiento de componentes proviene del diseño impulsado
por el dominio (DDD) y comparte popularidad con los microservicios, también fuertemente
influenciados por DDD. En el evento storming, el arquitecto asume que el proyecto usará mensajes
y/o eventos para comunicarse entre los diversos componentes. Para ello, el equipo intenta
determinar qué eventos ocurren en el sistema en función de los requisitos y roles identificados, y
construye componentes en torno a esos controladores de eventos y mensajes. Esto funciona bien
en arquitecturas distribuidas como los microservicios que usan eventos y mensajes, porque ayuda
a los arquitectos a definir los mensajes utilizados en el sistema final.
Enfoque de flujo de
trabajo Una alternativa al método de tormenta de eventos ofrece un enfoque más genérico para los
arquitectos que no utilizan DDD ni mensajería. El enfoque de flujo de trabajo modela los componentes en
torno a flujos de trabajo, de forma muy similar al método de tormenta de eventos, pero sin las restricciones
explícitas de la creación de un sistema basado en mensajes. Un enfoque de flujo de trabajo identifica los
roles clave, determina los tipos de flujos de trabajo en los que participan estos roles y crea componentes
en torno a las actividades identificadas.
Ninguna de estas técnicas es superior a las demás; todas ofrecen un conjunto diferente de
ventajas y desventajas. Si un equipo utiliza un enfoque en cascada u otros procesos de desarrollo
de software más antiguos, es posible que prefiera el enfoque Actor/Acciones porque es general.
Cuando se utiliza DDD y arquitecturas correspondientes como microservicios, la tormenta de
eventos coincide exactamente con el proceso de desarrollo de software.
En el Capítulo 7, presentamos la arquitectura kata para Going, Going, Gone (GGG) y descubrimos
las características de la arquitectura para este sistema. Este sistema tiene tres roles obvios: el
postor, el subastador y un participante frecuente en esta técnica de modelado, el sistema, para
acciones internas. Los roles interactúan con la aplicación, representada aquí por el sistema, que
identifica cuándo la aplicación inicia un evento en lugar de uno de los roles. Por ejemplo, en GGG,
una vez que se completa la subasta, el sistema activa el sistema de pago para procesar los pagos.
También podemos identificar un conjunto inicial de acciones para cada uno de estos roles:
Licitador
Ver transmisión de video en vivo, ver transmisión de oferta en vivo, realizar una oferta
Subastador
Ingrese ofertas en vivo en el sistema, reciba ofertas en línea, marque el artículo como vendido
Sistema
Iniciar subasta, realizar pago, realizar seguimiento de la actividad del postor
Dadas estas acciones, podemos construir iterativamente un conjunto de componentes iniciales para GGG; una de estas soluciones
En la Figura 810, cada uno de los roles y acciones se asigna a un componente, que a su vez puede
necesitar colaborar en la obtención de información. Estos son los componentes que identificamos para
esta solución:
VideoStreamer transmite
Oferta Streamer
Transmite las ofertas a medida que se presentan a los usuarios. Tanto VideoStreamer como BidStreamer ofrecen vistas de
BidCapture
Este componente captura ofertas tanto del subastador como de los postores.
rastreador de ofertas
AuctionSession Inicia
y detiene una subasta. Cuando el postor finaliza la subasta, realiza los pasos de pago y resolución, incluida
la notificación a los postores sobre la finalización.
Pago
Procesador de pagos de terceros para pagos con tarjeta de crédito.
Debido a que tienen diferentes niveles de características de arquitectura, el arquitecto decide dividir el
componente Captura de ofertas en Captura de ofertas y Captura de subastador para que cada uno de
los dos componentes pueda admitir diferentes características de arquitectura.
El diseño actualizado aparece en la Figura 811.
El arquitecto crea un nuevo componente para Auctioneer Capture y actualiza los vínculos de información
tanto con Bid Streamer (para que los postores en línea vean las ofertas en vivo) como con Bid Tracker,
que administra los flujos de ofertas. Tenga en cuenta que Bid Tracker es ahora el componente que
unificará los dos flujos de información muy diferentes: el flujo único de información del subastador y los
flujos múltiples de los postores.
Es probable que el diseño que se muestra en la Figura 811 no sea el diseño final. Se deben descubrir
más requisitos (cómo se registran las personas, funciones administrativas relacionadas con los pagos,
etc.). Sin embargo, este ejemplo proporciona un buen punto de partida para comenzar a iterar más
sobre el diseño.
Este es un conjunto posible de componentes para resolver el problema GGG, pero no es necesariamente
correcto ni es el único. Pocos sistemas de software tienen una sola forma en que los desarrolladores
pueden implementarlos; cada diseño tiene diferentes conjuntos de compensaciones. Como arquitecto,
no te obsesiones por encontrar el único diseño verdadero, porque muchos serán suficientes (y menos
probables que sean sobrediseñados). En lugar de eso, intenta evaluar objetivamente las
compensaciones entre diferentes decisiones de diseño y elige la que tenga el conjunto de
compensaciones menos desfavorable.
Una arquitectura monolítica normalmente incluye una única unidad implementable, que incluye toda
la funcionalidad del sistema que se ejecuta en el proceso, normalmente conectada a una única base
de datos. Los tipos de arquitecturas monolíticas incluyen el monolito en capas y modular, que se
analizan en detalle en el Capítulo 10. Una arquitectura distribuida es lo opuesto: la aplicación consta
de múltiples servicios que se ejecutan en su propio ecosistema y se comunican a través de protocolos
de red. Las arquitecturas distribuidas pueden incluir modelos de implementación más detallados,
donde cada servicio puede tener su propia cadencia de lanzamiento y prácticas de ingeniería, según
el equipo de desarrollo y sus prioridades.
Cada estilo de arquitectura ofrece una variedad de ventajas y desventajas, que se tratan en la Parte
II. Sin embargo, la decisión fundamental se basa en cuántos cuantos descubre la arquitectura durante
el proceso de diseño. Si el sistema puede funcionar con un solo cuanto (en otras palabras, un
conjunto de características de arquitectura), entonces una arquitectura monolítica ofrece muchas
ventajas. Por otro lado, las diferentes características de arquitectura de los componentes, como se
ilustra en el análisis de componentes de GGG, requieren una arquitectura distribuida para adaptarse
a las diferentes características de arquitectura. Por ejemplo, tanto VideoStreamer como BidStreamer
ofrecen vistas de solo lectura de la subasta a los postores. Desde el punto de vista del diseño, un
arquitecto preferiría no lidiar con la transmisión de solo lectura mezclada con actualizaciones a gran
escala. Junto con las diferencias mencionadas anteriormente entre el postor y el subastador, estas
diferentes características llevan a un arquitecto a elegir una arquitectura distribuida.
PARTE II
Estilos de arquitectura
La diferencia entre un estilo de arquitectura y un patrón de arquitectura puede ser confusa. Definimos
un estilo de arquitectura como la estructura general de cómo se organizan la interfaz de usuario y el
código fuente del backend (por ejemplo, dentro de las capas de una implementación monolítica o
servicios implementados por separado) y cómo ese código fuente interactúa con un almacén de
datos. Los patrones de arquitectura, por otro lado, son estructuras de diseño de nivel inferior que
ayudan a formar soluciones específicas dentro de un estilo de arquitectura (por ejemplo, cómo lograr
una alta escalabilidad o un alto rendimiento dentro de un conjunto de operaciones o entre conjuntos
de servicios).
Comprender los estilos arquitectónicos requiere mucho tiempo y esfuerzo para los arquitectos
noveles, ya que todos ellos son importantes y abundantes. Los arquitectos deben comprender los
distintos estilos y las ventajas y desventajas que conlleva cada uno para tomar decisiones eficaces;
cada estilo arquitectónico incorpora un conjunto bien conocido de ventajas y desventajas que ayudan
a un arquitecto a tomar la decisión correcta para un problema empresarial en particular.
Machine Translated by Google
Machine Translated by Google
CAPÍTULO 9
Cimientos
Los estilos de arquitectura, a veces llamados patrones de arquitectura, describen una relación de
componentes con nombre que abarca una variedad de características de la arquitectura. Un
nombre de estilo de arquitectura, similar a los patrones de diseño, crea un nombre único que actúa
como abreviatura entre arquitectos experimentados. Por ejemplo, cuando un arquitecto habla
sobre un monolito en capas, su destinatario en la conversación comprende aspectos de la
estructura, qué tipos de características de la arquitectura funcionan bien (y cuáles pueden causar
problemas), modelos de implementación típicos, estrategias de datos y una gran cantidad de otra
información. Por lo tanto, los arquitectos deben estar familiarizados con los nombres básicos de
los estilos de arquitectura genéricos fundamentales.
Cada nombre captura una gran cantidad de detalles, uno de los propósitos de los patrones de
diseño. Un estilo arquitectónico describe la topología, las características arquitectónicas asumidas
y predeterminadas, tanto beneficiosas como perjudiciales. Cubrimos muchos patrones
arquitectónicos modernos comunes en el resto de esta sección del libro (Parte II). Sin embargo,
los arquitectos deben estar familiarizados con varios patrones fundamentales que aparecen
integrados dentro de los patrones más grandes.
Patrones fundamentales
Varios patrones fundamentales aparecen una y otra vez a lo largo de la historia de la arquitectura
de software porque proporcionan una perspectiva útil para organizar el código, las implementaciones
u otros aspectos de la arquitectura. Por ejemplo, el concepto de capas en la arquitectura, que
separa diferentes aspectos en función de la funcionalidad, es tan antiguo como el software mismo.
Sin embargo, el patrón de capas continúa manifestándose en diferentes formas, incluidas las
variantes modernas que se analizan en el Capítulo 10.
119
Machine Translated by Google
Los arquitectos se refieren a la ausencia de cualquier estructura arquitectónica discernible como una Gran Bola de
El barro, llamado así por el antipatrón homónimo definido en un artículo publicado en 1997 por
Brian Foote y Joseph Yoder:
Una gran bola de barro es una jungla de códigos desordenados, desordenada, extensa y llena de
cinta adhesiva y alambre de embalar. Estos sistemas muestran signos inequívocos de crecimiento
descontrolado y de reparaciones repetidas y oportunas. La información se comparte de forma
promiscua entre elementos distantes del sistema, a menudo hasta el punto en que casi toda la
información importante se vuelve global o duplicada.
Es posible que la estructura general del sistema nunca haya estado bien definida.
Si así fuera, es posible que se haya erosionado hasta el punto de no ser reconocible. Los
programadores con un mínimo de sensibilidad arquitectónica evitan estos atolladeros. Sólo aquellos a
quienes no les preocupa la arquitectura y, tal vez, se sienten cómodos con la inercia de la tarea
cotidiana de tapar los agujeros de estos diques defectuosos, se conforman con trabajar en estos sistemas.
En términos modernos, una gran bola de barro podría describir una aplicación de scripting simple con controladores
de eventos conectados directamente a llamadas de base de datos, sin una estructura interna real. Muchas
aplicaciones triviales comienzan así y luego se vuelven difíciles de manejar a medida que continúan creciendo.
En general, los arquitectos quieren evitar este tipo de arquitectura a toda costa. La falta de estructura hace que
los cambios sean cada vez más difíciles. Este tipo de arquitectura también sufre problemas de implementación,
capacidad de prueba, escalabilidad y rendimiento.
Lamentablemente, este antipatrón arquitectónico es bastante común en el mundo real. Pocos arquitectos tienen
la intención de crear uno, pero muchos proyectos, sin darse cuenta, logran crear un caos debido a la falta de
control en torno a la calidad y la estructura del código. Por ejemplo, Neal trabajó con un proyecto de un cliente
cuya estructura aparece en la Figura 91.
El cliente (cuyo nombre se omite por razones obvias) creó una aplicación web basada en Java lo más rápido
posible a lo largo de varios años. La visualización técnica1 muestra su acoplamiento arquitectónico: cada punto
en el perímetro del círculo representa una clase y cada línea representa conexiones entre las clases, donde las
líneas más gruesas indican conexiones más fuertes. En esta base de código, cualquier cambio en una clase hace
que sea difícil predecir los efectos secundarios en cadena para otras clases, lo que hace que el cambio sea un
asunto aterrador.
1 Realizado con una herramienta ahora retirada llamada XRay, un complemento de Eclipse.
Figura 91. Arquitectura de una gran bola de barro visualizada a partir de una base de código real
Existen pocas arquitecturas unitarias fuera de los sistemas integrados y otros entornos con grandes restricciones.
En general, los sistemas de software tienden a aumentar su funcionalidad con el tiempo, lo que requiere la
separación de preocupaciones para mantener las características de la arquitectura operativa, como el rendimiento
y la escala.
Cliente/Servidor
Con el tiempo, diversas fuerzas exigieron separar las partes de un sistema único; la forma de hacerlo constituye la
base de muchos de estos estilos. Muchos estilos de arquitectura tratan de cómo separar eficientemente las partes
del sistema.
Un estilo fundamental en la arquitectura separa la funcionalidad técnica entre el frontend y el backend, llamada
arquitectura de dos niveles o cliente/servidor. Existen muchos estilos diferentes de esta arquitectura, según la era
y las capacidades informáticas.
datos Una arquitectura temprana de computadoras personales alentó a los desarrolladores a escribir aplicaciones
de escritorio sofisticadas en interfaces de usuario como Windows, separando los datos en un servidor de base de
datos separado. Esta arquitectura coincidió con la aparición de servidores de base de datos independientes que
podían conectarse a través de protocolos de red estándar. Permitió que la lógica de presentación residiera en el
escritorio, mientras que la acción computacionalmente más intensa (tanto en volumen como en complejidad)
ocurría en servidores de base de datos más robustos.
Una vez que llegó el desarrollo web moderno, la división común pasó a ser la de navegador web conectado a
servidor web (que a su vez estaba conectado a un servidor de base de datos). La separación de responsabilidades
era similar a la variante de escritorio, pero con clientes más ligeros como navegadores, lo que permitía una
distribución más amplia tanto dentro como fuera de los firewalls.
Aunque la base de datos está separada del servidor web, los arquitectos a menudo todavía consideran que
se trata de una arquitectura de dos niveles porque los servidores web y de base de datos se ejecutan en
una clase de máquina dentro del centro de operaciones y la interfaz de usuario se ejecuta en el navegador
del usuario.
Tres niveles
Una arquitectura que se hizo muy popular a finales de los años 90 fue la arquitectura de tres niveles, que
proporcionaba incluso más capas de separación. A medida que herramientas como los servidores de aplicaciones
se hicieron populares en Java y .NET, las empresas comenzaron a construir incluso más capas en su topología: un
nivel de base de datos que utiliza un servidor de base de datos de nivel industrial, un nivel de aplicación gestionado
por un servidor de aplicaciones, un frontend codificado en HTML generado y, cada vez más, JavaScript, a medida
que sus capacidades se expandían.
La arquitectura de tres niveles se correspondía con protocolos a nivel de red como Common Object Request Broker
Architecture (CORBA). y el modelo de objetos componentes distribuidos (DCOM) que facilitó la construcción de
arquitecturas distribuidas.
De la misma manera que hoy en día los desarrolladores no se preocupan por cómo funcionan los protocolos de red
como TCP/IP (simplemente funcionan), la mayoría de los arquitectos no tienen que preocuparse por este nivel de
complejidad en las arquitecturas distribuidas. Las capacidades que ofrecían esas herramientas en esa época existen
hoy en día como herramientas (como las colas de mensajes) o como patrones de arquitectura (como la arquitectura
basada en eventos, que se trata en el Capítulo 14).
Tres niveles, diseño del lenguaje e implicaciones a largo plazo Durante la era en la que se
diseñó el lenguaje Java, la computación de tres niveles estaba de moda. Por lo tanto, se suponía que, en el
futuro, todos los sistemas serían arquitecturas de tres niveles. Uno de los dolores de cabeza comunes con los
lenguajes existentes como C++ era lo engorroso que era mover objetos a través de la red de una manera
consistente entre sistemas. Por lo tanto, los diseñadores de Java decidieron construir esta capacidad en el
núcleo del lenguaje utilizando un mecanismo llamado serialización. Cada objeto en Java implementa una
interfaz que requiere que admita serialización. Los diseñadores pensaron que, dado que la arquitectura de
tres niveles siempre sería el estilo de arquitectura, integrarla en el lenguaje ofrecería una gran comodidad. Por
supuesto, ese estilo arquitectónico vino y se fue, pero los restos aparecen en Java hasta el día de hoy,
frustrando enormemente al diseñador del lenguaje que quiere agregar características modernas que, para la
compatibilidad con versiones anteriores, deben admitir serialización, que prácticamente nadie usa hoy.
En el campo del software, como en otras disciplinas de ingeniería, siempre nos ha resultado difícil comprender
las consecuencias a largo plazo de las decisiones de diseño. El consejo constante de favorecer los diseños
simples es, en muchos sentidos, una defensa contra las consecuencias futuras.
Los estilos de arquitectura se pueden clasificar en dos tipos principales: monolíticos (una única unidad
de implementación de todo el código) y distribuidos (varias unidades de implementación conectadas a
través de protocolos de acceso remoto). Si bien ningún esquema de clasificación es perfecto, todas las
arquitecturas distribuidas comparten un conjunto común de desafíos y problemas que no se encuentran
en los estilos de arquitectura monolíticos, lo que hace que este esquema de clasificación sea una buena
separación entre los diversos estilos de arquitectura. En este libro, describiremos en detalle los siguientes
estilos de arquitectura:
Monolítico •
Arquitectura en capas (Capítulo 10) •
Distribuida •
Arquitectura basada en servicios (Capítulo 13) •
Los estilos de arquitectura distribuida, si bien son mucho más potentes en términos de rendimiento,
escalabilidad y disponibilidad que los estilos de arquitectura monolítica, tienen desventajas
significativas por esta potencia. El primer grupo de problemas que enfrentan todas las arquitecturas
distribuidas se describe en las falacias de la computación distribuida, acuñado por primera vez por L.
Peter Deutsch y otros colegas de Sun Microsystems en 1994. Una falacia es algo que se cree o
se supone que es cierto pero no lo es. Las ocho falacias de la computación distribuida se aplican
a las arquitecturas distribuidas actuales. Las siguientes secciones describen cada falacia.
Tanto los desarrolladores como los arquitectos asumen que la red es confiable, pero no lo es.
Si bien las redes se han vuelto más confiables con el tiempo, el hecho es que, en general, siguen
siendo poco confiables. Esto es importante para todas las arquitecturas distribuidas, ya que todos los
estilos de arquitectura distribuida dependen de la red para la comunicación hacia y desde los
servicios, así como entre servicios. Como se ilustra en la Figura 92, el Servicio B puede estar en
perfecto estado, pero el Servicio A no puede acceder a él debido a un problema de red; o peor aún,
el Servicio A realizó una solicitud al Servicio B para procesar algunos datos y no recibe una respuesta
debido a un problema de red. Es por eso que existen cosas como los tiempos de espera y los
disyuntores entre servicios. Cuanto más depende un sistema de la red (como la arquitectura de
microservicios), potencialmente menos confiable se vuelve.
Como muestra la Figura 93 , cuando se realiza una llamada local a otro componente a través de una
llamada a un método o función, ese tiempo (t_local) se mide en nanosegundos o microsegundos.
Sin embargo, cuando esa misma llamada se realiza a través de un protocolo de acceso remoto (como
REST, mensajería o RPC), el tiempo que se mide para acceder a ese servicio (t_remote) se mide en
milisegundos. Por lo tanto, t_remote siempre será mayor que t_local.
La latencia en cualquier arquitectura distribuida no es cero, pero la mayoría de los arquitectos ignoran
esta falacia e insisten en que tienen redes rápidas. Hágase esta pregunta: ¿sabe cuál es la latencia
promedio de ida y vuelta para una llamada RESTful en su entorno de producción? ¿Es 60
milisegundos? ¿Es 500 milisegundos?
Al utilizar cualquier arquitectura distribuida, los arquitectos deben conocer este promedio de latencia.
Es la única forma de determinar si una arquitectura distribuida es factible, en particular cuando se
consideran microservicios (consulte el Capítulo 17) debido a la naturaleza de granularidad fina de los
servicios y la cantidad de comunicación entre esos servicios. Suponiendo un promedio de 100
milisegundos de latencia por solicitud, ¡encadenar 10 llamadas de servicio para realizar una función
comercial particular agrega 1000 milisegundos a la solicitud!
Conocer la latencia promedio es importante, pero aún más importante es conocer también el percentil
95 al 99. Si bien una latencia promedio puede producir solo 60 milisegundos (lo cual es bueno), el
percentil 95 puede ser de 400 milisegundos. Por lo general, es esta latencia de "cola larga" la que
afectará el rendimiento en una arquitectura distribuida. En la mayoría de los casos, los arquitectos
pueden obtener valores de latencia de un administrador de red (consulte "Falacia n.° 6: solo hay un
administrador" en la página 129).
El ancho de banda no suele ser un problema en las arquitecturas monolíticas, porque una vez que el
procesamiento pasa a un monolito, se requiere poco o ningún ancho de banda para procesar esa
solicitud comercial. Sin embargo, como se muestra en la Figura 94, una vez que los sistemas se dividen
en unidades de implementación más pequeñas (servicios) en una arquitectura distribuida, como los
microservicios, la comunicación hacia y entre estos servicios utiliza significativamente el ancho de banda,
lo que hace que las redes se ralenticen, lo que afecta la latencia (falacia n.° 2) y la confiabilidad (falacia
n.° 1).
Para ilustrar la importancia de esta falacia, considere los dos servicios que se muestran en la Figura 94.
Digamos que el servicio de la izquierda administra los elementos de la lista de deseos para el sitio web
y el servicio de la derecha administra el perfil del cliente. Siempre que una solicitud de una lista de
deseos llega al servicio de la izquierda, debe realizar una llamada entre servicios al servicio de perfil del
cliente de la derecha para obtener el nombre del cliente porque esos datos son necesarios en el contrato
de respuesta para la lista de deseos, pero el servicio de lista de deseos en el lado izquierdo no tiene el
nombre. El servicio de perfil del cliente devuelve 45 atributos que suman 500 kb al servicio de lista de
deseos, que solo necesita el nombre (200 bytes). Esta es una forma de acoplamiento conocida como
acoplamiento de sellos. Esto puede no parecer significativo, pero las solicitudes de los elementos de la
lista de deseos ocurren aproximadamente 2000 veces por segundo. Esto significa que esta llamada
entre servicios del servicio de lista de deseos al servicio de perfil del cliente ocurre 2000 veces por
segundo. Con 500 kb por cada solicitud, la cantidad de ancho de banda utilizado para esa llamada entre
servicios (de los cientos que se realizan en ese segundo) es ¡1 Gb!
Independientemente de la técnica utilizada, garantizar que se transmita la mínima cantidad de datos entre
servicios o sistemas en una arquitectura distribuida es la mejor forma de abordar esta falacia.
La mayoría de los arquitectos y desarrolladores se sienten tan cómodos usando redes privadas virtuales
(VPN), redes confiables y firewalls que tienden a olvidarse de esta falacia de la computación distribuida: la
red no es segura. La seguridad se vuelve mucho más desafiante en una arquitectura distribuida. Como se
muestra en la Figura 95, todos y cada uno de los puntos finales de cada unidad de implementación
distribuida deben estar protegidos para que las solicitudes desconocidas o incorrectas no lleguen a ese
servicio. La superficie de las amenazas y los ataques aumenta en magnitudes cuando se pasa de una
arquitectura monolítica a una distribuida. Tener que proteger cada punto final, incluso cuando se realiza una
comunicación entre servicios, es otra razón por la que el rendimiento tiende a ser más lento en arquitecturas
sincrónicas y altamente distribuidas, como los microservicios o la arquitectura basada en servicios.
Esta falacia se refiere a la topología general de la red, incluidos todos los enrutadores, concentradores,
conmutadores, cortafuegos, redes y dispositivos utilizados dentro de la red general. Los arquitectos
suponen que la topología es fija y nunca cambia. Por supuesto que cambia. Cambia todo el tiempo.
¿Cuál es el significado de esta falacia?
Supongamos que un arquitecto llega a trabajar un lunes por la mañana y todo el mundo está corriendo
de un lado a otro como loco porque los servicios se agotan constantemente en producción. El arquitecto
trabaja con los equipos, tratando frenéticamente de averiguar por qué sucede esto. No se implementaron
nuevos servicios durante el fin de semana. ¿Qué podría ser? Después de varias horas, el arquitecto
descubre que se produjo una pequeña actualización de la red a las 2 de la mañana de esa mañana.
Esta actualización de red supuestamente “menor” invalidó todas las suposiciones de latencia, lo que
provocó tiempos de espera y disyuntores.
Los arquitectos deben estar en constante comunicación con los administradores de operaciones y de
red para saber qué está cambiando y cuándo, de modo que puedan hacer los ajustes necesarios para
reducir el tipo de sorpresas descritas anteriormente. Esto puede parecer obvio y fácil, pero no lo es.
De hecho, esta falacia conduce directamente a la siguiente falacia.
Los arquitectos caen todo el tiempo en esta falacia, suponiendo que solo necesitan
colaborar y comunicarse con un administrador. Como se muestra en la Figura 97, hay
docenas de administradores de red en una gran empresa típica. ¿Con quién debería hablar
el arquitecto en relación con la latencia (“Falacia n.° 2: La latencia es cero” en la página
125) o los cambios de topología (“Falacia n.° 5: La topología nunca cambia” en la página
128)? Esta falacia apunta a la complejidad de la arquitectura distribuida y la cantidad de
coordinación que debe ocurrir para que todo funcione correctamente. Las aplicaciones
monolíticas no requieren este nivel de comunicación y colaboración debido a las
características de unidad de implementación única de esos estilos de arquitectura.
Muchos arquitectos de software confunden esta falacia con la latencia (“Falacia n.° 2: la latencia es
cero” en la página 125). El costo de transporte aquí no se refiere a la latencia, sino al costo real en
términos de dinero asociado con hacer una “simple llamada RESTful”. Los arquitectos suponen
(incorrectamente) que la infraestructura necesaria está en su lugar y es suficiente para hacer una
simple llamada RESTful o desarmar una aplicación monolítica. Por lo general, no es así. Las
arquitecturas distribuidas cuestan significativamente más que las arquitecturas monolíticas,
principalmente debido a las mayores necesidades de hardware adicional, servidores, puertas de
enlace, cortafuegos, nuevas subredes, servidores proxy, etc.
Siempre que se emprende una arquitectura distribuida, alentamos a los arquitectos a analizar la
topología actual del servidor y la red con respecto a la capacidad, el ancho de banda, la latencia y
las zonas de seguridad para no caer en la trampa de la sorpresa con esta falacia.
La mayoría de los arquitectos y desarrolladores asumen que una red es homogénea, es decir, que
está formada por un solo proveedor de hardware de red. Nada más lejos de la realidad. La mayoría
de las empresas tienen varios proveedores de hardware de red en su infraestructura, si no más.
¿Y qué? La importancia de esta falacia es que no todos esos proveedores de hardware heterogéneos
funcionan bien juntos. La mayor parte funciona, pero ¿el hardware de Juniper se integra
perfectamente con el hardware de Cisco? Los estándares de redes han evolucionado con los años,
lo que hace que esto sea un problema menor, pero el hecho es que no todas las situaciones, cargas
y circunstancias se han probado por completo y, como tal, los paquetes de red ocasionalmente se
pierden. Esto, a su vez, afecta la confiabilidad de la red (“Falacia n.° 1: la red es confiable” en la
página 124), las suposiciones y afirmaciones sobre la latencia (“Falacia n.° 2: la latencia es cero” en
la página 125) y las suposiciones realizadas sobre el ancho de banda (“Falacia n.° 3: el ancho de
banda es infinito” en la página 126). En otras palabras, esta falacia se vincula con todas las demás
falacias, formando un bucle interminable de confusión y frustración al tratar con redes (lo cual es
necesario cuando se utilizan arquitecturas distribuidas).
Registro distribuido
Realizar un análisis de causa raíz para determinar por qué se canceló un pedido en particular es
muy difícil y requiere mucho tiempo en una arquitectura distribuida debido a la distribución de
registros de aplicaciones y sistemas. En una aplicación monolítica, normalmente solo hay un registro,
lo que facilita el seguimiento de una solicitud y la determinación del problema. Sin embargo, las
arquitecturas distribuidas contienen docenas o cientos de registros diferentes, todos ubicados en un solo registro.
lugares diferentes y todos con un formato diferente, lo que dificulta la localización de un problema.
Transacciones distribuidas
Los arquitectos y desarrolladores dan por sentado que las transacciones se llevan a cabo en un
mundo de arquitectura monolítica porque son muy sencillas y fáciles de gestionar. Las confirmaciones
y reversiones estándar ejecutadas desde marcos de persistencia aprovechan las transacciones ACID
(atomicidad, consistencia, aislamiento, durabilidad) para garantizar que los datos se actualicen de
forma correcta y garantizar una alta consistencia e integridad de los datos. Este no es el caso de las
arquitecturas distribuidas.
Las arquitecturas distribuidas dependen de lo que se denomina consistencia eventual para garantizar
que los datos procesados por unidades de implementación independientes estén sincronizados en un
estado consistente en algún momento no especificado. Esta es una de las ventajas y desventajas de
la arquitectura distribuida: alta escalabilidad, rendimiento y disponibilidad a costa de la consistencia y
la integridad de los datos.
Sagas transaccionales son una forma de gestionar transacciones distribuidas. Las sagas utilizan
fuentes de eventos para compensación o máquinas de estados finitos para gestionar el estado de la
transacción. Además de las sagas, se utilizan transacciones BASE. BASE significa (B)asic availability
(Disponibilidad básica), (S)oft state (Estado suave) y (E)ventual consistencia. Las transacciones BASE
no son una pieza de software, sino más bien una técnica. Por lo tanto, el estado en BASE se refiere
al tránsito de datos desde una fuente a un destino, así como a la inconsistencia entre fuentes de
datos. Según la disponibilidad básica de los sistemas o servicios involucrados, los sistemas
eventualmente se volverán consistentes mediante el uso de patrones de arquitectura y mensajería.
CAPÍTULO 10
La arquitectura en capas, también conocida como arquitectura de n niveles, es uno de los estilos
arquitectónicos más comunes. Este estilo de arquitectura es el estándar de facto para la mayoría
de las aplicaciones, principalmente por su simplicidad, familiaridad y bajo costo. También es una
forma muy natural de desarrollar aplicaciones debido a la ley de Conway, que establece que las
organizaciones que diseñan sistemas están limitadas a producir diseños que sean copias de las
estructuras de comunicación de estas organizaciones. En la mayoría de las organizaciones hay
desarrolladores de interfaz de usuario (UI), desarrolladores de backend, desarrolladores de reglas
y expertos en bases de datos (DBA). Estas capas organizativas encajan bien en los niveles de
una arquitectura en capas tradicional, lo que la convierte en una opción natural para muchas
aplicaciones comerciales. El estilo de arquitectura en capas también se incluye en varios
antipatrones arquitectónicos, incluido el antipatrón de arquitectura por implicación y el antipatrón
de arquitectura accidental. Si un desarrollador o arquitecto no está seguro de qué estilo de
arquitectura está utilizando, o si un equipo de desarrollo ágil "simplemente comienza a codificar",
es muy probable que sea el estilo de arquitectura en capas lo que están implementando.
Topología
Los componentes dentro del estilo de arquitectura en capas se organizan en capas horizontales
lógicas, y cada capa desempeña una función específica dentro de la aplicación (como la lógica de
presentación o la lógica empresarial). Aunque no existen restricciones específicas en términos de
la cantidad y los tipos de capas que deben existir, la mayoría de las arquitecturas en capas
constan de cuatro capas estándar: presentación, negocio, persistencia y base de datos, como se
ilustra en la Figura 101. En algunos casos, la capa empresarial y la capa de persistencia se
combinan en una sola capa empresarial, en particular cuando la lógica de persistencia (como SQL
o HSQL) está integrada dentro de los componentes de la capa empresarial. Por lo tanto, las
aplicaciones más pequeñas pueden tener solo tres capas, mientras que las aplicaciones
empresariales más grandes y complejas pueden contener cinco o más capas.
133
Machine Translated by Google
Figura 101. Capas lógicas estándar dentro del estilo de arquitectura en capas
La Figura 102 ilustra las distintas variantes de topología desde una perspectiva de capas físicas
(implementación). La primera variante combina las capas de presentación, negocio y persistencia
en una única unidad de implementación, con la capa de base de datos representada típicamente
como una base de datos física externa separada (o sistema de archivos). La segunda variante
separa físicamente la capa de presentación en su propia unidad de implementación, con las capas
de negocio y persistencia combinadas en una segunda unidad de implementación. Nuevamente,
con esta variante, la capa de base de datos generalmente está separada físicamente a través de
una base de datos externa o un sistema de archivos. Una tercera variante combina las cuatro capas
estándar en una única implementación, incluida la capa de base de datos. Esta variante puede ser
útil para aplicaciones más pequeñas con una base de datos incorporada internamente o una base de datos en memoria.
Muchos productos locales (“onprem”) se crean y se entregan a los clientes utilizando esta tercera
variante.
Cada capa del estilo de arquitectura en capas tiene una función y una responsabilidad específicas
dentro de la arquitectura. Por ejemplo, la capa de presentación sería responsable de gestionar toda
la lógica de comunicación de la interfaz de usuario y del navegador, mientras que la capa empresarial
sería responsable de ejecutar reglas empresariales específicas asociadas con la
Solicitud. Cada capa de la arquitectura forma una abstracción en torno al trabajo que se debe realizar
para satisfacer una solicitud empresarial en particular. Por ejemplo, la capa de presentación no
necesita saber ni preocuparse por cómo obtener los datos de los clientes; solo necesita mostrar esa
información en una pantalla en un formato particular. De manera similar, la capa empresarial no
necesita preocuparse por cómo formatear los datos de los clientes para mostrarlos en una pantalla o
incluso de dónde provienen los datos de los clientes; solo necesita obtener los datos de la capa de
persistencia, realizar una lógica empresarial con los datos (como calcular valores o agregar datos) y
pasar esa información a la capa de presentación.
Este concepto de separación de preocupaciones dentro del estilo de arquitectura en capas facilita la
creación de modelos de roles y responsabilidad efectivos dentro de la arquitectura. Los componentes
dentro de una capa específica tienen un alcance limitado y se ocupan únicamente de la lógica que
pertenece a esa capa. Por ejemplo, los componentes de la capa de presentación solo manejan la
lógica de presentación, mientras que los componentes que residen en la capa empresarial solo
manejan la lógica empresarial. Esto permite a los desarrolladores aprovechar su experiencia técnica
particular para centrarse en los aspectos técnicos del dominio (como la lógica de presentación o la
lógica de persistencia). Sin embargo, la contrapartida de este beneficio es la falta de agilidad general
(la capacidad de responder rápidamente al cambio).
Capas de aislamiento
Cada capa en el estilo de arquitectura en capas puede ser cerrada o abierta. Una capa cerrada
significa que, a medida que una solicitud se mueve de arriba hacia abajo de una capa a otra, no
puede omitir ninguna capa, sino que debe pasar por la capa inmediatamente inferior para llegar a la
siguiente (consulte la Figura 103). Por ejemplo, en una arquitectura de capas cerradas, una solicitud
que se origina en la capa de presentación primero debe pasar por la capa empresarial y luego por la
capa de persistencia antes de llegar finalmente a la capa de base de datos.
Observe que en la Figura 103 sería mucho más rápido y más fácil para la capa de presentación acceder
a la base de datos directamente para solicitudes de recuperación simples, evitando las capas innecesarias
(lo que solía conocerse a principios de la década de 2000 como el patrón de lectura de carril rápido). Para
que esto suceda, las capas de negocio y de persistencia tendrían que estar abiertas, lo que permitiría que
las solicitudes pasaran por alto otras capas. ¿Qué es mejor: las capas abiertas o las capas cerradas? La
respuesta a esta pregunta se encuentra en un concepto clave conocido como capas de aislamiento.
El concepto de capas de aislamiento significa que los cambios realizados en una capa de la arquitectura
generalmente no impactan ni afectan a los componentes de otras capas, siempre que los contratos entre
esas capas permanezcan inalterados. Cada capa es independiente de las otras capas, por lo que tiene
poco o ningún conocimiento del funcionamiento interno de otras capas en la arquitectura. Sin embargo,
para admitir capas de aislamiento, las capas involucradas con el flujo principal de la solicitud
necesariamente deben estar cerradas. Si la capa de presentación puede acceder directamente a la capa
de persistencia, entonces los cambios realizados en la capa de persistencia afectarían tanto a la capa de
negocios como a la capa de presentación, lo que produciría una aplicación muy estrechamente acoplada
con interdependencias de capas entre los componentes. Este tipo de arquitectura se vuelve entonces
muy frágil, así como difícil y costoso de cambiar.
El concepto de capas de aislamiento también permite reemplazar cualquier capa de la arquitectura sin
afectar a ninguna otra capa (nuevamente, asumiendo contratos bien definidos y el uso del patrón de
delegado comercial). Por ejemplo, puede aprovechar el concepto de capas de aislamiento dentro del
estilo de arquitectura en capas para reemplazar su antigua capa de presentación JavaServer Faces (JSF)
con React.js sin afectar ninguna otra capa de la aplicación.
Añadiendo capas
Si bien las capas cerradas facilitan las capas de aislamiento y, por lo tanto, ayudan a aislar los cambios
dentro de la arquitectura, hay ocasiones en las que tiene sentido que ciertas capas estén abiertas. Por
ejemplo, supongamos que hay objetos compartidos dentro de la capa empresarial que contienen una
funcionalidad común para los componentes empresariales (como la fecha y la utilidad de cadena).
Supongamos que hay una decisión de arquitectura que establece que la capa de presentación tiene
restricciones para usar estos objetos comerciales compartidos. Esta restricción se ilustra en la Figura 104,
con la línea de puntos que va desde un componente de presentación a un objeto comercial compartido en
la capa comercial. Este escenario es difícil de gobernar y controlar porque, arquitectónicamente, la capa de
presentación tiene acceso a la capa comercial y, por lo tanto, tiene acceso a los objetos compartidos dentro
de esa capa.
Una forma de imponer esta restricción arquitectónicamente es agregar a la arquitectura una nueva capa de
servicios que contenga todos los objetos comerciales compartidos. Agregar esta nueva capa ahora restringe
arquitectónicamente el acceso de la capa de presentación a los objetos comerciales compartidos porque la
capa comercial está cerrada (consulte la Figura 105). Sin embargo, la nueva capa de servicios debe
marcarse como abierta; de lo contrario, la capa comercial se vería obligada a pasar por la capa de servicios
para acceder a la capa de persistencia. Marcar la capa de servicios como abierta permite que la capa
comercial acceda a esa capa (como lo indica la flecha sólida) o la omita y vaya a la siguiente capa inferior
(como lo indica la flecha punteada en la Figura 105).
Aprovechar el concepto de capas abiertas y cerradas ayuda a definir la relación entre las capas de la
arquitectura y los flujos de solicitudes. También proporciona a los desarrolladores la información y la
orientación necesarias para comprender las distintas restricciones de acceso a las capas dentro de la
arquitectura. Si no se documentan o comunican adecuadamente qué capas de la arquitectura están
abiertas y cerradas (y por qué), generalmente se obtienen arquitecturas frágiles y estrechamente
acopladas que son muy difíciles de probar, mantener e implementar.
Otras consideraciones
La arquitectura en capas es un buen punto de partida para la mayoría de las aplicaciones cuando aún
no se sabe exactamente qué estilo de arquitectura se utilizará en última instancia. Esta es una práctica
común para muchos proyectos de microservicios cuando los arquitectos aún están determinando si los
microservicios son la opción de arquitectura adecuada, pero el desarrollo debe comenzar. Sin embargo,
al utilizar esta técnica, asegúrese de mantener la reutilización al mínimo y mantener las jerarquías de
objetos (profundidad del árbol de herencia) bastante superficiales para mantener un buen nivel de
modularidad. Esto ayudará a facilitar el cambio a otro estilo de arquitectura más adelante.
Una cosa a tener en cuenta con la arquitectura en capas es el antipatrón de sumidero de arquitectura.
Este antipatrón se produce cuando las solicitudes se mueven de una capa a otra como un simple
procesamiento de paso sin que se realice ninguna lógica empresarial dentro de cada capa. Por ejemplo,
supongamos que la capa de presentación responde a una solicitud simple del usuario para recuperar
datos básicos del cliente (como el nombre y la dirección).
pasa la solicitud a la capa empresarial, que no hace nada más que pasar la solicitud a la capa de reglas, que a su vez no
hace nada más que pasar la solicitud a la capa de persistencia, que luego realiza una simple llamada SQL a la capa de
base de datos para recuperar los datos del cliente. Luego, los datos se pasan de regreso a la pila sin procesamiento ni
lógica adicional para agregar, calcular, aplicar reglas o transformar los datos. Esto da como resultado una instanciación
y procesamiento de objetos innecesarios, lo que afecta tanto el consumo de memoria como el rendimiento.
Toda arquitectura en capas tendrá al menos algunos escenarios que caen dentro del antipatrón de
sumidero de arquitectura. La clave para determinar si el antipatrón de sumidero de arquitectura está
en juego es analizar el porcentaje de solicitudes que caen en esta categoría. La regla 8020 suele
ser una buena práctica a seguir. Por ejemplo, es aceptable si solo el 20 por ciento de las solicitudes
son sumidero. Sin embargo, si el 80 por ciento de las solicitudes son sumidero, es un buen indicador
de que la arquitectura en capas no es el estilo de arquitectura correcto para el dominio del problema.
Otro enfoque para resolver el antipatrón de sumidero de arquitectura es hacer que todas las capas
de la arquitectura sean abiertas, teniendo en cuenta, por supuesto, que la contrapartida es una mayor
dificultad para gestionar el cambio dentro de la arquitectura.
El estilo de arquitectura en capas es una buena opción para aplicaciones o sitios web pequeños y sencillos. También es
una buena opción arquitectónica, en particular como punto de partida, para situaciones con limitaciones de tiempo y
presupuesto muy ajustadas. Debido a la simplicidad y familiaridad entre desarrolladores y arquitectos, la arquitectura en
capas es quizás uno de los estilos arquitectónicos de menor costo, lo que promueve la facilidad de desarrollo para
aplicaciones más pequeñas. El estilo de arquitectura en capas también es una buena opción cuando un arquitecto
todavía está analizando las necesidades y requisitos comerciales y no está seguro de qué estilo de arquitectura sería el
mejor.
A medida que las aplicaciones que utilizan el estilo de arquitectura en capas crecen, las características como la capacidad
de mantenimiento, la agilidad, la capacidad de prueba y la capacidad de implementación se ven afectadas negativamente.
Por este motivo, las aplicaciones y los sistemas de gran tamaño que utilizan la arquitectura en capas pueden ser más
adecuados para otros estilos de arquitectura más modulares.
Una calificación de una estrella en la tabla de calificación de características (que se muestra en la Figura 106) significa
que la característica de arquitectura específica no está bien respaldada en la arquitectura, mientras que una calificación
de cinco estrellas significa que la característica de arquitectura es una de las características más sólidas del estilo de
arquitectura. La definición de cada característica identificada en la tarjeta de puntuación se puede encontrar en el Capítulo
4.
El costo general y la simplicidad son las principales fortalezas del estilo de arquitectura en capas.
Al ser monolíticas por naturaleza, las arquitecturas en capas no tienen las complejidades asociadas con los estilos de
arquitectura distribuida, son simples y fáciles de entender, y su construcción y mantenimiento tienen un costo
relativamente bajo. Sin embargo, como nota de advertencia, estas calificaciones comienzan a disminuir rápidamente a
medida que las arquitecturas en capas monolíticas se hacen más grandes y, en consecuencia, más complejas.
Tanto la capacidad de implementación como la capacidad de prueba tienen una calificación muy baja para este estilo
de arquitectura. La calificación de capacidad de implementación es baja debido a la ceremonia de implementación
(esfuerzo para implementar), el alto riesgo y la falta de implementaciones frecuentes. Un simple cambio de tres líneas
en un archivo de clase en el estilo de arquitectura en capas requiere que se vuelva a implementar toda la unidad de
implementación, lo que incluye posibles cambios en la base de datos, cambios de configuración u otros cambios de
codificación que se introducen junto con el cambio original. Además, este simple cambio de tres líneas suele estar
incluido con docenas de otros cambios, lo que aumenta aún más el riesgo de implementación (así como la frecuencia
de implementación). La calificación de capacidad de prueba baja
También refleja este escenario: con un simple cambio de tres líneas, la mayoría de los desarrolladores no
van a pasar horas ejecutando todo el conjunto de pruebas de regresión (incluso si tal cosa existiera en
primer lugar), en particular junto con docenas de otros cambios que se realizan a la aplicación monolítica al
mismo tiempo. Le otorgamos a la capacidad de prueba una calificación de dos estrellas (en lugar de una
estrella) debido a la capacidad de simular o crear componentes (o incluso una capa completa), lo que facilita
el esfuerzo de prueba general.
La confiabilidad general tiene una calificación media (tres estrellas) en este estilo de arquitectura,
principalmente debido a la falta de tráfico de red, ancho de banda y latencia que se encuentran en la mayoría
de las arquitecturas distribuidas. Solo le otorgamos tres estrellas a la arquitectura en capas por confiabilidad
debido a la naturaleza de la implementación monolítica, combinada con las bajas calificaciones de capacidad
de prueba (integridad de las pruebas) y riesgo de implementación.
La elasticidad y la escalabilidad tienen una calificación muy baja (una estrella) para la arquitectura en capas,
principalmente debido a las implementaciones monolíticas y la falta de modularidad arquitectónica. Si bien
es posible lograr que ciertas funciones dentro de un monolito se escalen más que otras, este esfuerzo
generalmente requiere técnicas de diseño muy complejas, como subprocesamiento múltiple, mensajería
interna y otras prácticas de procesamiento paralelo, técnicas para las que esta arquitectura no es adecuada.
Sin embargo, debido a que la arquitectura en capas siempre es un sistema cuántico único debido a la
interfaz de usuario monolítica, el procesamiento de backend y la base de datos monolítica, las aplicaciones
solo pueden escalar hasta cierto punto en función del cuántico único.
Las arquitecturas en capas no admiten la tolerancia a fallas debido a las implementaciones monolíticas y la
falta de modularidad arquitectónica. Si una pequeña parte de una arquitectura en capas provoca una
condición de falta de memoria, toda la unidad de aplicación se ve afectada y se bloquea. Además, la
disponibilidad general se ve afectada debido al alto tiempo medio de recuperación (MTTR) que suelen
experimentar la mayoría de las aplicaciones monolíticas, con tiempos de inicio que varían desde 2 minutos
para aplicaciones más pequeñas hasta 15 minutos o más para la mayoría de las aplicaciones grandes.
CAPÍTULO 11
Uno de los estilos fundamentales en la arquitectura de software que aparece una y otra vez es la
arquitectura de tuberías (también conocida como arquitectura de tuberías y filtros). Tan pronto como los
desarrolladores y arquitectos decidieron dividir la funcionalidad en partes discretas, este patrón siguió. La
mayoría de los desarrolladores conocen esta arquitectura como el principio subyacente detrás de los
lenguajes de shell de terminal de Unix, como Bash . y Zsh.
Los desarrolladores de muchos lenguajes de programación funcional verán paralelismos entre las
construcciones del lenguaje y los elementos de esta arquitectura. De hecho, muchas herramientas que
utilizan MapReduce El modelo de programación sigue esta topología básica. Si bien estos ejemplos
muestran una implementación de bajo nivel del estilo de arquitectura de canalización, también se puede
utilizar para aplicaciones comerciales de nivel superior.
Topología
La topología de la arquitectura de la tubería consta de tuberías y filtros, ilustrados en la Figura 111.
143
Machine Translated by Google
Las tuberías y los filtros se coordinan de una manera específica, y las tuberías forman una comunicación
unidireccional entre los filtros, generalmente de punto a punto.
Tuberías
Las tuberías en esta arquitectura forman el canal de comunicación entre filtros. Cada tubería es
típicamente unidireccional y punto a punto (en lugar de transmisión) por razones de rendimiento,
aceptando la entrada de una fuente y siempre dirigiendo la salida a otra. La carga útil transportada en
las tuberías puede ser cualquier formato de datos, pero los arquitectos prefieren cantidades más
pequeñas de datos para permitir un alto rendimiento.
Filtros
Los filtros son autónomos, independientes de otros filtros y, por lo general, sin estado. Los filtros deben
realizar una sola tarea. Las tareas compuestas deben ser manejadas por una secuencia de filtros en
lugar de uno solo.
Productor
El punto de inicio de un proceso, sólo de salida, a veces llamado fuente.
Transformador
Acepta la entrada, opcionalmente realiza una transformación en algunos o todos los datos y luego
los reenvía a la tubería de salida. Los defensores funcionales reconocerán esta característica como
mapa.
El
probador acepta la entrada, prueba uno o más criterios y, luego, opcionalmente, produce una salida en
función de la prueba. Los programadores funcionales reconocerán esto como algo similar a reducir.
Consumidor
El punto de terminación del flujo de la canalización. A veces, los consumidores conservan el
resultado final del proceso de canalización en una base de datos o pueden mostrar los resultados
finales en una pantalla de interfaz de usuario.
La naturaleza unidireccional y la simplicidad de cada una de las tuberías y filtros fomentan la reutilización
compositiva. Muchos desarrolladores han descubierto esta capacidad utilizando shells. Una historia
famosa del blog “More Shell, Less Egg” Un ejemplo de esto es el siguiente: se le pidió a Donald Knuth
que escribiera un programa para resolver este problema de manejo de texto: leer un archivo de texto,
determinar las n palabras más utilizadas e imprimir una lista ordenada de esas palabras junto con sus
frecuencias. Escribió un programa que constaba de más de 10 páginas de Pascal, diseñando (y
documentando) un nuevo algoritmo en el proceso. Luego, Doug McIlroy demostró un script de shell que
encajaría fácilmente en una publicación de Twitter que resolvía el problema de manera más simple,
elegante y comprensible (si entiendes los comandos de shell):
Incluso los diseñadores de shells de Unix a menudo se sorprenden de los usos innovadores que los
desarrolladores han hecho de sus abstracciones simples pero poderosamente compuestas.
Ejemplo
El patrón de arquitectura de canalización aparece en una variedad de aplicaciones, especialmente en tareas
que facilitan el procesamiento simple y unidireccional. Por ejemplo, muchas herramientas de intercambio
electrónico de datos (EDI) utilizan este patrón, creando transformaciones de un tipo de documento a otro
mediante canalizaciones y filtros. Las herramientas ETL (extracción, transformación y carga) también
aprovechan la arquitectura de canalización para el flujo y la modificación de datos de una base de datos o
fuente de datos a otra. Los orquestadores y mediadores como Apache Camel Utilice la arquitectura de
canalización para pasar información de un paso a otro en un proceso de negocio.
Para ilustrar cómo se puede utilizar la arquitectura de canalización, considere el siguiente ejemplo, como se
ilustra en la Figura 112, donde se envía diversa información de telemetría de servicios desde los servicios
mediante transmisión a Apache Kafka.
Ejemplo | 145
Machine Translated by Google
Observe en la Figura 112 el uso del estilo de arquitectura de canalización para procesar los diferentes
tipos de datos transmitidos a Kafka. El filtro de captura de información de servicio (filtro de productor) se
suscribe al tema de Kafka y recibe información de servicio. Luego envía estos datos capturados a un
filtro de prueba llamado Filtro de duración para determinar si los datos capturados de Kafka están
relacionados con la duración (en milisegundos) de la solicitud de servicio.
Observe la separación de preocupaciones entre los filtros; el filtro de captura de métricas de servicio
solo se ocupa de cómo conectarse a un tema de Kafka y recibir datos de transmisión, mientras que el
filtro de duración solo se ocupa de calificar los datos y, opcionalmente, enrutarlos a la siguiente tubería.
Si los datos están relacionados con la duración (en milisegundos) de la solicitud de servicio, entonces el
filtro de duración pasa los datos al filtro transformador de la calculadora de duración . De lo contrario, los
pasa al filtro de prueba del filtro de tiempo de actividad para verificar si los datos están relacionados con
las métricas de tiempo de actividad. Si no lo están, entonces la tubería finaliza: los datos no son de
interés para este flujo de procesamiento en particular. De lo contrario, si son métricas de tiempo de
actividad, entonces pasa los datos a la calculadora de tiempo de actividad para calcular las métricas de
tiempo de actividad para el servicio. Estos transformadores luego pasan los datos modificados al
consumidor de salida de base de datos , que luego persiste los datos en una MongoDB . base de datos.
Este ejemplo muestra las propiedades de extensibilidad de la arquitectura de la canalización. Por ejemplo, en la
Figura 112, se podría agregar fácilmente un nuevo filtro de prueba después del filtro de tiempo de actividad para
pasar los datos a otra métrica recién recopilada, como el tiempo de espera de la conexión a la base de datos.
El costo general y la simplicidad combinados con la modularidad son las principales fortalezas del estilo de
arquitectura de canalización. Al ser monolíticas por naturaleza, las arquitecturas de canalización no tienen las
complejidades asociadas con los estilos de arquitectura distribuida, son simples y fáciles de entender, y su
construcción y mantenimiento tienen un costo relativamente bajo. La modularidad arquitectónica se logra
mediante la separación de preocupaciones entre los diversos tipos de filtros y transformadores. Cualquiera de
estos filtros se puede modificar o reemplazar sin afectar a los otros filtros. Por ejemplo, en el ejemplo de Kafka
ilustrado en la Figura 112, la Calculadora de duración se puede modificar para cambiar el cálculo de la duración
sin afectar a ningún otro filtro.
La capacidad de implementación y de prueba, si bien se encuentran en un nivel promedio, tienen una calificación
ligeramente superior a la de la arquitectura en capas debido al nivel de modularidad que se logra a través de los
filtros. Dicho esto, este estilo de arquitectura sigue siendo un monolito y, como tal, la ceremonia, el riesgo, la
frecuencia de implementación y la finalización de las pruebas aún afectan la arquitectura del pipeline.
Al igual que la arquitectura en capas, la confiabilidad general se califica como media (tres estrellas)
en este estilo de arquitectura, principalmente debido a la falta de tráfico de red, ancho de banda y
latencia que se encuentran en la mayoría de las arquitecturas distribuidas. Solo le otorgamos tres
estrellas por confiabilidad debido a la naturaleza de la implementación monolítica de este estilo de
arquitectura junto con problemas de capacidad de prueba e implementación (como tener que probar
todo el monolito e implementarlo todo para cualquier cambio dado).
La arquitectura de pipeline tiene una tasa de elasticidad y escalabilidad muy baja (una estrella),
principalmente debido a las implementaciones monolíticas. Si bien es posible lograr que ciertas
funciones dentro de un monolito se escalen más que otras, este esfuerzo generalmente requiere
técnicas de diseño muy complejas, como subprocesamiento múltiple, mensajería interna y otras
prácticas de procesamiento paralelo, técnicas para las que esta arquitectura no es adecuada. Sin
embargo, debido a que la arquitectura de pipeline es siempre un quantum de sistema único debido
a la interfaz de usuario monolítica, el procesamiento de backend y la base de datos monolítica, las
aplicaciones solo pueden escalar hasta cierto punto en función del quantum de arquitectura única.
CAPÍTULO 12
Topología
El estilo de arquitectura de microkernel es una arquitectura monolítica relativamente simple que consta
de dos componentes de arquitectura: un sistema central y componentes complementarios.
La lógica de la aplicación se divide entre componentes independientes y el sistema básico central, lo
que proporciona extensibilidad, adaptabilidad y aislamiento de las características de la aplicación y
lógica de procesamiento personalizada. La Figura 121 ilustra la topología básica del estilo de
arquitectura de micronúcleo.
149
Machine Translated by Google
Sistema central
El sistema central se define formalmente como la funcionalidad mínima requerida para ejecutar el
sistema. El IDE de Eclipse es un buen ejemplo de esto. El sistema central de Eclipse es simplemente
un editor de texto básico: abre un archivo, cambia algo de texto y guarda el archivo. No es hasta que
agregas complementos que Eclipse comienza a convertirse en un producto utilizable. Sin embargo,
otra definición del sistema central es la ruta feliz (flujo de procesamiento general) a través de la
aplicación, con poco o ningún procesamiento personalizado. Eliminar la complejidad ciclomática del
sistema central y colocarla en componentes de complemento separados permite una mejor
extensibilidad y capacidad de mantenimiento, así como una mayor capacidad de prueba. Por ejemplo,
supongamos que una aplicación de reciclaje de dispositivos electrónicos debe realizar reglas de
evaluación personalizadas específicas para cada dispositivo electrónico recibido. El código Java para
este tipo de procesamiento podría verse así:
En lugar de colocar toda esta personalización específica del cliente en el sistema central con mucha
complejidad ciclomática, es mucho mejor crear un componente de complemento independiente para
cada dispositivo electrónico que se esté evaluando. Los componentes de complemento específicos del
cliente no solo aíslan la lógica independiente del dispositivo del resto del flujo de procesamiento, sino
que también permiten la capacidad de expansión. Agregar un nuevo dispositivo electrónico para evaluar
es simplemente una cuestión de agregar un nuevo componente de complemento y actualizar el registro.
Con el estilo de arquitectura de microkernel, evaluar un dispositivo electrónico solo requiere que el
sistema central ubique e invoque los complementos del dispositivo correspondientes, como se ilustra en
este código fuente revisado:
En este ejemplo, todas las reglas e instrucciones complejas para evaluar un dispositivo electrónico
particular están contenidas en un componente complementario independiente y autónomo que puede
ejecutarse de forma genérica desde el sistema central.
Según el tamaño y la complejidad, el sistema central se puede implementar como una arquitectura en
capas o como un monolito modular (como se ilustra en la Figura 122). En algunos casos, el sistema
central se puede dividir en servicios de dominio implementados por separado, y cada servicio de dominio
contiene componentes de complemento específicos para ese dominio. Por ejemplo, supongamos que el
procesamiento de pagos es el servicio de dominio que representa el sistema central. Cada método de
pago (tarjeta de crédito, PayPal, crédito de la tienda, tarjeta de regalo y orden de compra) serían
componentes de complemento separados específicos para el dominio de pago.
En todos estos casos, es típico que toda la aplicación monolítica comparta una única base de datos.
Topología | 151
Machine Translated by Google
La capa de presentación del sistema central puede estar integrada en el sistema central o implementarse
como una interfaz de usuario independiente, en la que el sistema central proporciona servicios de
backend. De hecho, también se puede implementar una interfaz de usuario independiente como un
estilo de arquitectura de microkernel. La Figura 123 ilustra estas variantes de la capa de presentación
en relación con el sistema central.
Componentes complementarios
Los componentes complementarios son componentes independientes y autónomos que contienen procesamiento
especializado, funciones adicionales y código personalizado destinado a mejorar o ampliar el sistema central.
Además, se pueden utilizar para aislar código altamente volátil, creando
Topología | 153
Machine Translated by Google
Mejor capacidad de mantenimiento y de prueba dentro de la aplicación. Lo ideal es que los componentes del complemento
sean independientes entre sí y no tengan dependencias entre ellos.
La comunicación entre los componentes del complemento y el sistema central es generalmente punto a punto, lo que
significa que la "tubería" que conecta el complemento con el sistema central suele ser una invocación de método o una
llamada de función a la clase de punto de entrada del componente del complemento. Además, el componente del
complemento puede estar basado en compilación o en tiempo de ejecución. Los componentes del complemento en tiempo
de ejecución se pueden agregar o eliminar en tiempo de ejecución sin tener que volver a implementar el sistema central u
otros complementos, y generalmente se administran a través de marcos como Open Service Gateway Initiative (OSGi) para
Java. Penrose (Java), Rompecabezas (Java), o Prisma (.NET). Los componentes de complemento basados en compilación
son mucho más simples de administrar, pero requieren que se vuelva a implementar toda la aplicación monolítica cuando
se modifica, agrega o elimina.
Los componentes de complemento punto a punto se pueden implementar como bibliotecas compartidas (como un JAR,
DLL o Gem), nombres de paquetes en Java o espacios de nombres en C#. Siguiendo con el ejemplo de aplicación de
evaluación de reciclaje de productos electrónicos, cada complemento de dispositivo electrónico se puede escribir e
implementar como un JAR, DLL o Ruby Gem (o cualquier otra biblioteca compartida), con el nombre del dispositivo
coincidiendo con el nombre de la biblioteca compartida independiente, como se ilustra en la Figura 124.
Como alternativa, un enfoque más sencillo que se muestra en la Figura 125 es implementar cada componente del
complemento como un espacio de nombres o nombre de paquete independiente dentro de la misma base de código o
proyecto IDE. Al crear el espacio de nombres, recomendamos la siguiente semántica: app.plugin.<dominio>.<contexto>.
Por ejemplo, considere el espacio de nombres app.plugin.assessment.iphone6s. El segundo nodo (complemento) deja en
claro que este componente es un complemento y, por lo tanto, debe cumplir estrictamente las reglas básicas con respecto
a los componentes del complemento (es decir, que son autónomos y separados).
El tercer nodo describe el dominio (en este caso, evaluación), lo que permite organizar y agrupar los componentes del
complemento según un propósito común. El cuarto nodo (iphone6s) describe el contexto específico del complemento,
lo que facilita la ubicación del complemento del dispositivo específico para su modificación o prueba.
Los componentes de complemento no siempre tienen que tener una comunicación punto a punto con el sistema
central. Existen otras alternativas, incluido el uso de REST o mensajería como un medio para invocar la
funcionalidad del complemento, donde cada complemento es un servicio independiente (o tal vez incluso un
microservicio implementado mediante un contenedor). Si bien esto puede parecer una buena manera de
aumentar la escalabilidad general, tenga en cuenta que esta topología (ilustrada en la Figura 126) sigue siendo
solo una arquitectura cuántica única debido al sistema central monolítico. Cada solicitud debe pasar primero por
el sistema central para llegar al servicio del complemento.
Los beneficios del enfoque de acceso remoto para acceder a los componentes complementarios implementados como
servicios individuales es que proporciona un mejor desacoplamiento general de los componentes,
Topología | 155
Machine Translated by Google
Permite una mejor escalabilidad y rendimiento, y permite cambios en el tiempo de ejecución sin marcos
especiales como OSGi, Jigsaw o Prism. También permite comunicaciones asincrónicas con complementos, lo
que, según el escenario, podría mejorar significativamente la capacidad de respuesta general del usuario.
Usando el ejemplo del reciclaje de productos electrónicos, en lugar de tener que esperar a que se ejecute la
evaluación del dispositivo electrónico, el sistema central podría realizar una solicitud asincrónica para iniciar una
evaluación para un dispositivo en particular. Cuando la evaluación se completa, el complemento puede notificar
al sistema central a través de otro canal de mensajería asincrónica, que a su vez notificaría al usuario que la
evaluación está completa.
Estos beneficios conllevan desventajas. El acceso remoto a complementos convierte la arquitectura del
microkernel en una arquitectura distribuida en lugar de una monolítica, lo que dificulta la implementación y el
despliegue de la mayoría de los productos locales de terceros. Además, genera más complejidad y costos
generales y complica la topología de implementación general. Si un complemento deja de responder o no se
ejecuta, en particular cuando se usa REST, la solicitud no se puede completar. Este no sería el caso con una
implementación monolítica. La elección de si hacer que la comunicación con los componentes del complemento
desde el sistema central sea punto a punto o remota debe basarse en requisitos específicos y, por lo tanto,
requiere un análisis cuidadoso de las ventajas y desventajas de dicho enfoque.
No es una práctica habitual que los componentes de complemento se conecten directamente a una base de
datos compartida de forma central. En cambio, el sistema central asume esta responsabilidad y pasa los datos
necesarios a cada complemento. La razón principal de esta práctica es el desacoplamiento.
La realización de un cambio en la base de datos solo debería afectar al sistema central, no a los componentes
del complemento. Dicho esto, los complementos pueden tener sus propios almacenes de datos independientes
a los que solo puede acceder ese complemento. Por ejemplo, cada complemento de evaluación de dispositivos
electrónicos en el ejemplo del sistema de reciclaje electrónico puede tener su propia base de datos simple o
motor de reglas que contenga todas las reglas de evaluación específicas para cada producto. El almacén de
datos propiedad del componente del complemento puede ser externo (como se muestra en la Figura 127) o
puede estar integrado como parte del componente del complemento o de una implementación monolítica (como
en el caso de una base de datos en memoria o integrada).
Figura 127. Los componentes del complemento pueden tener su propio almacén de datos
Registro
El sistema central necesita saber qué módulos de complemento están disponibles y cómo acceder a ellos. Una forma habitual
de implementar esto es mediante un registro de complementos.
Este registro contiene información sobre cada módulo de complemento, como su nombre, contrato de datos y detalles del
protocolo de acceso remoto (según cómo esté conectado el complemento al sistema central). Por ejemplo, un complemento
para software fiscal que señale elementos de auditoría fiscal de alto riesgo podría tener una entrada de registro que contenga el
nombre del servicio (AuditChecker), el contrato de datos (datos de entrada y datos de salida) y el formato del contrato (XML).
El registro puede ser tan simple como una estructura de mapa interna propiedad del sistema central que contiene una clave y la
referencia del componente del complemento, o puede ser tan complejo como un registro y una herramienta de descubrimiento
integrada en el sistema central o implementada externamente (como Apache ZooKeeper) . o Cónsul). Utilizando el ejemplo de
reciclaje de productos electrónicos, el siguiente código Java implementa un registro simple dentro del sistema central, mostrando
una entrada punto a punto, una entrada de mensajería y un ejemplo de entrada RESTful para evaluar un dispositivo iPhone 6S:
//ejemplo de mensajería
registration.put("iPhone6s", "iphone6s.queue");
//ejemplo restful
register.put("iPhone6s", "https://atlas:443/assess/iphone6s");
}
Registro | 157
Machine Translated by Google
Contratos
Los contratos entre los componentes del complemento y el sistema central suelen ser estándar en
un dominio de componentes del complemento e incluyen comportamiento, datos de entrada y datos
de salida devueltos por el componente del complemento. Los contratos personalizados suelen
encontrarse en situaciones en las que los componentes del complemento son desarrollados por un
tercero y usted no tiene control sobre el contrato utilizado por el complemento. En tales casos, es
habitual crear un adaptador entre el contrato del complemento y su contrato estándar para que el
sistema central no necesite código especializado para cada complemento.
En este ejemplo de contrato, se espera que el complemento de evaluación del dispositivo devuelva
el informe de evaluación como una cadena formateada; un indicador de reventa (verdadero o falso)
que indique si este dispositivo se puede revender en un mercado de terceros o desechar de forma
segura; y, finalmente, si se puede revender (otra forma de reciclaje), cuál es el valor calculado del
artículo y cuál debería ser el precio de reventa recomendado.
Otros complementos añaden capacidades adicionales que no se encuentran en el navegador básico que
representa el sistema central. Los ejemplos son infinitos para el software basado en productos, pero ¿qué
sucede con las grandes aplicaciones empresariales? La arquitectura de microkernel también se aplica a
estas situaciones. Para ilustrar este punto, considere el ejemplo de una compañía de seguros que involucra
el procesamiento de reclamos de seguros.
El procesamiento de reclamos es un proceso muy complicado. Cada jurisdicción tiene diferentes reglas y
regulaciones sobre lo que está permitido y lo que no en un reclamo de seguro. Por ejemplo, algunas
jurisdicciones (por ejemplo, los estados) permiten el reemplazo gratuito del parabrisas si el parabrisas se
daña con una piedra, mientras que otros estados no lo permiten. Esto crea un conjunto casi infinito de
condiciones para un proceso de reclamo estándar.
Las reglas de reclamaciones para cada jurisdicción se pueden incluir en componentes de complemento
independientes (implementados como código fuente o una instancia de motor de reglas específica a la que
accede el componente de complemento). De esta manera, se pueden agregar, eliminar o cambiar reglas
para una jurisdicción en particular sin afectar a ninguna otra parte del sistema. Además, se pueden agregar
y eliminar nuevas jurisdicciones sin afectar a otras partes del sistema. El sistema central en este ejemplo
sería el proceso estándar para presentar y procesar una reclamación, algo que no cambia con frecuencia.
Otro ejemplo de una aplicación empresarial grande y compleja que puede aprovechar la arquitectura de
microkernel es el software de preparación de impuestos. Por ejemplo, Estados Unidos tiene un formulario
fiscal básico de dos páginas llamado formulario 1040 que contiene un resumen de toda la información
necesaria para calcular la obligación tributaria de una persona. Cada línea del formulario fiscal 1040 tiene
un solo número que requiere muchos otros formularios y hojas de cálculo para llegar a ese único número
(como el ingreso bruto). Cada uno de estos formularios y hojas de cálculo adicionales se puede implementar
como un componente complementario, siendo el formulario fiscal resumido 1040 el sistema central (el
controlador). De esta manera, los cambios a la ley tributaria se pueden aislar en un componente
complementario independiente, lo que hace que los cambios sean más fáciles y menos riesgosos.
De manera similar al estilo de arquitectura en capas, la simplicidad y el costo general son las principales fortalezas del
estilo de arquitectura de microkernel, y la escalabilidad, la tolerancia a fallas y la extensibilidad son sus principales
debilidades. Estas debilidades se deben a las típicas implementaciones monolíticas que se encuentran con la
arquitectura de microkernel. Además, al igual que el estilo de arquitectura en capas, el número de cuantos es siempre
singular (uno) porque todas las solicitudes deben pasar por el sistema central para llegar a los componentes de
complemento independientes. Ahí es donde terminan las similitudes.
El estilo de arquitectura de microkernel es único en el sentido de que es el único estilo de arquitectura que puede ser
tanto particionada por dominio como técnicamente. Si bien la mayoría de las arquitecturas de microkernel están
particionadas técnicamente, el aspecto de partición de dominio se produce principalmente a través de un fuerte
isomorfismo de dominio a arquitectura. Por ejemplo, los problemas que requieren diferentes configuraciones para cada
ubicación o cliente se adaptan extremadamente bien a este estilo de arquitectura. Otro ejemplo es un producto o
aplicación que pone un fuerte énfasis en la personalización del usuario y la extensibilidad de funciones (como Jira o un
IDE como Eclipse).
La capacidad de prueba, la capacidad de implementación y la confiabilidad tienen una calificación ligeramente superior
a la media (tres estrellas), principalmente porque la funcionalidad se puede aislar en componentes de complemento
independientes. Si se hace correctamente, esto reduce el alcance general de las pruebas de los cambios y también
reduce el riesgo general de implementación, en particular si los componentes de complemento se implementan en
tiempo de ejecución.
La modularidad y la extensibilidad también están un poco por encima de la media (tres estrellas). Con el estilo de
arquitectura de microkernel, se pueden añadir, eliminar y cambiar funciones adicionales a través de componentes plug
in independientes y autónomos, lo que hace que sea relativamente fácil ampliar y mejorar las aplicaciones creadas con
este estilo de arquitectura y permite a los equipos responder a los cambios mucho más rápido. Considere el ejemplo
del software de preparación de impuestos de la sección anterior. Si la ley fiscal de EE. UU. cambia (lo que ocurre todo
el tiempo) y se requiere un nuevo formulario de impuestos, ese nuevo formulario de impuestos se puede crear como
un componente plugin y agregarlo a la aplicación sin mucho esfuerzo. De manera similar, si ya no se necesita un
formulario o una hoja de cálculo de impuestos, ese plugin se puede eliminar simplemente de la aplicación.
El rendimiento es siempre una característica interesante para evaluar con el estilo de arquitectura de microkernel. Le
otorgamos tres estrellas (un poco por encima del promedio) principalmente porque las aplicaciones de microkernel son
generalmente pequeñas y no crecen tanto como la mayoría de las arquitecturas en capas. Además, no sufren tanto por
el antipatrón de sumidero de arquitectura que se analizó en el Capítulo 10. Finalmente, las arquitecturas de microkernel
se pueden optimizar desconectando la funcionalidad innecesaria, lo que hace que la aplicación se ejecute más rápido.
Un buen ejemplo de esto es Wildfly. (anteriormente, JBoss Application Server). Al desconectar funciones innecesarias
como la agrupación en clústeres, el almacenamiento en caché y la mensajería, el servidor de aplicaciones funciona
mucho más rápido que con estas funciones instaladas.
CAPÍTULO 13
Topología
La topología básica de la arquitectura basada en servicios sigue una estructura distribuida en
capas macro que consta de una interfaz de usuario implementada por separado, servicios remotos
de grano grueso implementados por separado y una base de datos monolítica. Esta topología
básica se ilustra en la Figura 131.
Los servicios dentro de este estilo de arquitectura son típicamente “partes de una aplicación” de
grano grueso (usualmente llamados servicios de dominio) que son independientes y se implementan
por separado. Los servicios se implementan típicamente de la misma manera que cualquier
aplicación monolítica (como un archivo EAR, un archivo WAR o un ensamblaje) y, como tal, no
requieren contenedorización (aunque podría implementar un servicio de dominio en un contenedor
como Docker). Debido a que los servicios generalmente comparten una única base de datos
monolítica, la cantidad de servicios dentro de un contexto de aplicación generalmente varía entre
4 y 12 servicios, con un promedio de aproximadamente 7 servicios.
163
Machine Translated by Google
En la mayoría de los casos, solo hay una única instancia de cada servicio de dominio dentro de una
arquitectura basada en servicios. Sin embargo, en función de la escalabilidad, la tolerancia a fallas y las
necesidades de rendimiento, es posible que existan varias instancias de un servicio de dominio. Por lo
general, varias instancias de un servicio requieren algún tipo de capacidad de equilibrio de carga entre
la interfaz de usuario y el servicio de dominio para que la interfaz de usuario pueda dirigirse a una
instancia de servicio en buen estado y disponible.
Se accede a los servicios de forma remota desde una interfaz de usuario utilizando un protocolo de acceso remoto.
Si bien REST se utiliza normalmente para acceder a los servicios desde la interfaz de usuario, también se pueden
utilizar mensajes, llamadas a procedimientos remotos (RPC) o incluso SOAP. Si bien se puede utilizar una capa de
API que consta de un proxy o una puerta de enlace para acceder a los servicios desde la interfaz de usuario (u
otras solicitudes externas), en la mayoría de los casos la interfaz de usuario accede a los servicios directamente
mediante un patrón de localizador de servicios. incrustado dentro de la interfaz de usuario, puerta de enlace API o
proxy.
Un aspecto importante de la arquitectura basada en servicios es que normalmente utiliza una base de datos
compartida de forma centralizada. Esto permite que los servicios aprovechen las consultas SQL y las uniones de
la misma forma que lo haría una arquitectura monolítica en capas tradicional. Debido a la pequeña cantidad de
servicios (de 4 a 12), las conexiones de bases de datos no suelen ser un problema en la arquitectura basada en
servicios. Sin embargo, los cambios en las bases de datos pueden ser un problema. La sección “Particionamiento
de bases de datos” en la página 169 describe técnicas para abordar y administrar cambios en las bases de datos
dentro de una arquitectura basada en servicios.
Variantes de topología
Existen muchas variantes de topología dentro del estilo de arquitectura basado en servicios, lo que lo convierte
quizás en uno de los estilos de arquitectura más flexibles. Por ejemplo, la interfaz de usuario monolítica única, como
se ilustra en la Figura 131, se puede dividir en dominios de interfaz de usuario, incluso hasta un nivel que coincida
con cada servicio de dominio. Estas variantes de interfaz de usuario se ilustran en la Figura 132.
De manera similar, pueden existir oportunidades para dividir una única base de datos monolítica en bases de datos
independientes, llegando incluso a bases de datos con alcance de dominio que coincidan con cada servicio de dominio
(similar a los microservicios). En estos casos, es importante asegurarse de que los datos de cada base de datos
independiente no sean necesarios para otro servicio de dominio. Esto evita la comunicación entre servicios de dominio
(algo que definitivamente se debe evitar con la arquitectura basada en servicios) y también la duplicación de datos entre
bases de datos. Estas variantes de bases de datos se ilustran en la Figura 133.
Por último, también es posible agregar una capa de API que consiste en un proxy inverso o una puerta
de enlace entre la interfaz de usuario y los servicios, como se muestra en la Figura 134. Esta es una
buena práctica cuando se expone la funcionalidad del servicio de dominio a sistemas externos o
cuando se consolidan preocupaciones transversales compartidas y se las traslada fuera de la interfaz
de usuario (como métricas, seguridad, requisitos de auditoría y descubrimiento de servicios).
Figura 134. Adición de una capa de API entre la interfaz de usuario y los servicios de dominio
Independientemente del diseño del servicio, un servicio de dominio debe contener algún tipo de
fachada de acceso a API con la que la interfaz de usuario interactúe para ejecutar algún tipo de
funcionalidad comercial. La fachada de acceso a API generalmente asume la responsabilidad de
orquestar la solicitud comercial desde la interfaz de usuario. Por ejemplo, considere una solicitud
comercial desde la interfaz de usuario para realizar un pedido (también conocido como pago por catálogo).
Esta única solicitud, recibida por la fachada de acceso a la API dentro del servicio de dominio OrderService ,
organiza internamente la única solicitud comercial: realizar el pedido, generar un ID de pedido, aplicar el pago y
actualizar el inventario de productos para cada producto solicitado. En el estilo de arquitectura de microservicios,
esto probablemente implicaría la orquestación de muchos servicios remotos de un solo propósito implementados
por separado para completar la solicitud. Esta diferencia entre la orquestación interna a nivel de clase y la
orquestación de servicios externos apunta a una de las muchas diferencias significativas entre la arquitectura
basada en servicios y los microservicios en términos de granularidad.
Debido a que los servicios de dominio son de grano grueso, se utilizan transacciones de base de datos ACID
(atomicidad, consistencia, aislamiento, durabilidad) regulares que involucran confirmaciones y reversiones de
base de datos para garantizar la integridad de la base de datos dentro de un solo servicio de dominio.
Por otro lado, las arquitecturas distribuidas, como los microservicios, suelen tener servicios de grano fino y utilizan una
técnica de transacciones distribuidas conocida como transacciones BASE (disponibilidad básica, estado blando,
consistencia eventual) que dependen de la consistencia eventual y, por lo tanto, no admiten el mismo nivel de integridad
de la base de datos que las transacciones ACID en una arquitectura basada en servicios.
Para ilustrar este punto, considere el ejemplo de un proceso de pago por catálogo dentro de una arquitectura basada
en servicios. Supongamos que el cliente realiza un pedido y la tarjeta de crédito utilizada para el pago ha expirado.
Dado que se trata de una transacción atómica dentro del mismo servicio, todo lo agregado a la base de datos se puede
eliminar mediante una reversión y un aviso enviado al cliente indicando que el pago no se puede aplicar. Ahora
considere este mismo proceso en una arquitectura de microservicios con servicios de grano fino más pequeños.
Primero, el servicio OrderPlacement aceptaría la solicitud, crearía el pedido, generaría un ID de pedido e insertaría el
pedido en las tablas de pedidos. Una vez hecho esto, el servicio de pedidos realizaría una llamada remota al
PaymentService, que intentaría aplicar el pago. Si el pago no se puede aplicar debido a una tarjeta de crédito vencida,
entonces no se puede realizar el pedido y los datos están en un estado inconsistente (la información del pedido ya se
ha insertado pero no se ha aprobado). En este caso, ¿qué pasa con el inventario para ese pedido? ¿Debería marcarse
como ordenado y decrementarse? ¿Qué sucede si el inventario es bajo y otro cliente desea comprar el artículo? ¿Se
debe permitir que ese nuevo cliente lo compre o se debe reservar el inventario reservado para el cliente que intenta
realizar el pedido con una tarjeta de crédito vencida? Estas son solo algunas de las preguntas que se deben abordar al
organizar un proceso comercial con múltiples servicios de granularidad más detallada.
Los servicios de dominio, al ser de grano grueso, permiten una mejor integridad y consistencia de los datos, pero existe
una desventaja. Con una arquitectura basada en servicios, un cambio realizado en la funcionalidad de colocación de
pedidos en OrderService requeriría probar todo el servicio de grano grueso (incluido el procesamiento de pagos),
mientras que con los microservicios, el mismo cambio solo afectaría a un pequeño servicio de colocación de pedidos
(sin requerir ningún cambio en PaymentService). Además, debido a que se implementa más código, existe un mayor
riesgo con la arquitectura basada en servicios de que algo pueda fallar (incluido el procesamiento de pagos), mientras
que con los microservicios cada servicio tiene una única responsabilidad, por lo tanto, hay menos posibilidades de que
se rompa otra funcionalidad al realizar un cambio.
Aunque no es obligatorio, los servicios dentro de una arquitectura basada en servicios suelen compartir una única base
de datos monolítica debido a la pequeña cantidad de servicios (de 4 a 12) dentro de un contexto de aplicación
determinado. Este acoplamiento de bases de datos puede presentar un problema con respecto a los cambios en el
esquema de las tablas de la base de datos. Si no se realiza correctamente, un cambio en el esquema de las tablas
puede afectar potencialmente a todos los servicios, lo que hace que los cambios en la base de datos sean una tarea
muy costosa en términos de esfuerzo y coordinación.
En una arquitectura basada en servicios, los archivos de clase compartidos que representan los esquemas de las tablas de
la base de datos (normalmente denominados objetos de entidad) residen en una biblioteca compartida personalizada que
utilizan todos los servicios del dominio (como un archivo JAR o DLL). Las bibliotecas compartidas también pueden contener
código SQL. La práctica de crear una única biblioteca compartida de objetos de entidad es la forma menos eficaz de
implementar una arquitectura basada en servicios. Cualquier cambio en las estructuras de las tablas de la base de datos
también requeriría un cambio en la única biblioteca compartida que contiene todos los objetos de entidad correspondientes,
lo que requiere un cambio y una reimplementación en cada servicio, independientemente de si los servicios acceden o no
a la tabla modificada. El control de versiones de la biblioteca compartida puede ayudar a solucionar este problema, pero,
no obstante, con una única biblioteca compartida es difícil saber qué servicios se ven realmente afectados por el cambio
de tabla sin un análisis manual detallado. Este escenario de una única biblioteca compartida se ilustra en la Figura 136.
Figura 136. Uso de una única biblioteca compartida para objetos de entidad de base de datos
Una forma de mitigar el impacto y el riesgo de los cambios en la base de datos es particionar lógicamente la base de datos
y manifestar la partición lógica a través de bibliotecas compartidas federadas.
Observe en la Figura 137 que la base de datos está particionada lógicamente en cinco dominios separados (común,
cliente, facturación, pedido y seguimiento). Observe también que hay cinco bibliotecas compartidas correspondientes
utilizadas por los servicios de dominio que coinciden con las particiones lógicas en la base de datos. Con esta técnica, los
cambios en una tabla dentro de un dominio lógico particular (en este caso, facturación) coinciden con la biblioteca
compartida correspondiente que contiene los objetos de entidad (y posiblemente también SQL), lo que afecta solo a aquellos
Servicios que utilizan esa biblioteca compartida, que en este caso es el servicio de facturación. Este cambio no afecta a
ningún otro servicio.
Figura 137. Uso de múltiples bibliotecas compartidas para objetos de entidad de base de datos
Observe en la Figura 137 el uso del dominio común y la biblioteca compartida common_entities_lib correspondiente que
utilizan todos los servicios. Se trata de una situación relativamente común. Estas tablas son comunes a todos los
servicios y, como tales, los cambios en estas tablas requieren la coordinación de todos los servicios que acceden a la
base de datos compartida. Una forma de mitigar los cambios en estas tablas (y los objetos de entidad correspondientes)
es bloquear los objetos de entidad comunes en el sistema de control de versiones y restringir el acceso a los cambios
solo al equipo de la base de datos. Esto ayuda a controlar los cambios y enfatiza la importancia de los cambios en las
tablas comunes que utilizan todos los servicios.
Haga que la partición lógica en la base de datos sea lo más detallada posible y al
mismo tiempo mantenga dominios de datos bien definidos para controlar mejor los
cambios en la base de datos dentro de una arquitectura basada en servicios.
Ejemplo de arquitectura
Para ilustrar la flexibilidad y el poder del estilo de arquitectura basada en servicios, considere el
ejemplo del mundo real de un sistema de reciclaje electrónico utilizado para reciclar dispositivos
electrónicos viejos (como un iPhone o un teléfono celular Galaxy). El flujo de procesamiento del
reciclaje de dispositivos electrónicos viejos funciona de la siguiente manera: primero, el cliente
pregunta a la empresa (a través de un sitio web o quiosco) cuánto dinero puede obtener por el
dispositivo electrónico viejo (llamado cotización). Si está satisfecho, el cliente enviará el dispositivo
electrónico a la empresa de reciclaje, que a su vez recibirá el dispositivo físico (llamado recepción).
Una vez recibido, la empresa de reciclaje evaluará el dispositivo para determinar si el dispositivo está
en buenas condiciones de funcionamiento o no (llamado evaluación). Si el dispositivo está en buenas
condiciones de funcionamiento, la empresa enviará al cliente el dinero prometido por el dispositivo
(llamado contabilidad). A través de este proceso, el cliente puede ir al sitio web en cualquier momento
para verificar el estado del artículo (llamado estado del artículo). En función de la evaluación, el
dispositivo se recicla destruyéndolo de forma segura o vendiéndolo nuevamente (lo que se denomina
reciclaje). Por último, la empresa elabora periódicamente informes financieros y operativos ad hoc y
programados en función de la actividad de reciclaje (lo que se denomina informes).
La Figura 138 ilustra este sistema utilizando una arquitectura basada en servicios. Observe cómo
cada área de dominio identificada en la descripción anterior se implementa como un servicio de
dominio independiente implementado por separado. La escalabilidad se puede lograr escalando solo
aquellos servicios que necesitan un mayor rendimiento (en este caso, el servicio de cotización
orientado al cliente y el servicio ItemStatus ). Los demás servicios no necesitan escalar y, como tal,
solo requieren una única instancia de servicio.
Observe también cómo las aplicaciones de interfaz de usuario están federadas en sus respectivos
dominios: Atención al cliente, Recepción, Reciclaje y Contabilidad. Esta federación permite tolerancia
a fallos de la interfaz de usuario, escalabilidad y seguridad (los clientes externos no tienen una ruta
de red hacia la funcionalidad interna). Por último, observe en este ejemplo que hay dos bases de
datos físicas independientes: una para las operaciones externas de atención al cliente y otra para las
operaciones internas. Esto permite que los datos y las operaciones internas residan en una zona de
red separada de las operaciones externas (indicada por la línea vertical), lo que proporciona
restricciones de acceso de seguridad y protección de datos mucho mejores.
El acceso unidireccional a través del firewall permite que los servicios internos accedan y actualicen
la información que se muestra al cliente, pero no al revés. Alternativamente, según la base de datos
que se utilice, también se podría utilizar la duplicación y sincronización de tablas internas.
Figura 138. Ejemplo de reciclaje de productos electrónicos mediante una arquitectura basada en servicios
Este ejemplo ilustra muchos de los beneficios del enfoque de arquitectura basada en servicios: escalabilidad, tolerancia a fallas
y seguridad (protección y acceso a datos y funcionalidades), además de agilidad, capacidad de prueba e implementación. Por
ejemplo, el servicio de evaluación se modifica constantemente para agregar reglas de evaluación a medida que se reciben
nuevos productos. Este cambio frecuente se aísla en un solo servicio de dominio, lo que proporciona agilidad (la capacidad de
responder rápidamente al cambio), así como capacidad de prueba (la facilidad y la integridad de las pruebas) y capacidad de
implementación (la facilidad, la frecuencia y el riesgo de la implementación).
La arquitectura basada en servicios es una arquitectura particionada por dominio, lo que significa que la estructura está
impulsada por el dominio en lugar de una consideración técnica (como la lógica de presentación o la lógica de persistencia).
Considere el ejemplo anterior de la aplicación de reciclaje electrónico. Cada servicio, al ser una unidad de software
implementada por separado, tiene un alcance en un dominio específico (como la evaluación de artículos). Los cambios
realizados dentro de este dominio solo afectan al servicio específico, la interfaz de usuario correspondiente y la
base de datos correspondiente. No es necesario modificar nada más para respaldar un cambio de
evaluación específico.
Al ser una arquitectura distribuida, la cantidad de cuantos puede ser mayor o igual a uno. Aunque puede
haber entre 4 y 12 servicios implementados por separado, si todos esos servicios comparten la misma base
de datos o interfaz de usuario, todo el sistema sería un solo cuanto. Sin embargo, como se ilustra en
“Variantes de topología” en la página 165, tanto la interfaz de usuario como la base de datos pueden estar
federadas, lo que da como resultado múltiples cuantos dentro del sistema general. En el ejemplo de
reciclaje de productos electrónicos, el sistema contiene dos cuantos, como se ilustra en la Figura 1310:
uno para la parte de la aplicación orientada al cliente que contiene una interfaz de usuario de cliente, una
base de datos y un conjunto de servicios (cotización y estado del artículo) independientes; y uno para las
operaciones internas de recepción, evaluación y reciclaje del dispositivo electrónico. Observe que, aunque
el cuanto de operaciones internas contiene servicios implementados por separado y dos interfaces de
usuario independientes, todos comparten la misma base de datos, lo que hace que la parte de operaciones
internas de la aplicación sea un solo cuanto.
Aunque la arquitectura basada en servicios no contiene ninguna calificación de cinco estrellas, sin embargo
tiene una calificación alta (cuatro estrellas) en muchas áreas importantes y vitales. Dividir una aplicación en
servicios de dominio implementados por separado utilizando este estilo de arquitectura permite un cambio
más rápido (agilidad), una mejor cobertura de pruebas debido al alcance limitado del dominio (capacidad de
prueba) y la capacidad de implementaciones más frecuentes que conllevan menos riesgos que un gran
monolito (capacidad de implementación). Estas tres características conducen a un mejor tiempo de
comercialización, lo que permite a una organización ofrecer nuevas características y correcciones de errores
a un ritmo relativamente alto.
La tolerancia a fallos y la disponibilidad general de las aplicaciones también tienen una alta calificación en la
arquitectura basada en servicios. Aunque los servicios de dominio tienden a ser de grano grueso, la
calificación de cuatro estrellas se debe al hecho de que con este estilo de arquitectura, los servicios suelen
ser autónomos y no aprovechan la comunicación entre servicios debido al uso compartido de bases de datos
y de código. Como resultado, si un servicio de dominio deja de funcionar (por ejemplo, el servicio de
recepción en el ejemplo de la aplicación de reciclaje electrónico), no afecta a ninguno de los otros seis
servicios.
La escalabilidad solo tiene tres estrellas debido a la naturaleza de grano grueso de los servicios y, en
consecuencia, la elasticidad solo tiene dos estrellas. Aunque la escalabilidad y elasticidad programáticas son
ciertamente posibles con este estilo de arquitectura, se replica más funcionalidad que con servicios de grano
más fino (como microservicios) y, como tal, no es tan eficiente en términos de recursos de la máquina ni tan
rentable. Por lo general, solo hay instancias de servicio únicas con la arquitectura basada en servicios a
menos que haya una necesidad de mejor rendimiento o conmutación por error. Un buen ejemplo de esto es
el ejemplo de la aplicación de reciclaje de productos electrónicos: solo los servicios de cotización y estado
del artículo necesitan escalar para admitir grandes volúmenes de clientes, pero los otros servicios operativos
solo requieren instancias únicas, lo que hace que sea más fácil admitir cosas como el almacenamiento en
caché en memoria única y la agrupación de conexiones de base de datos.
La simplicidad y el costo total son otros dos factores que diferencian este estilo de arquitectura de otras
arquitecturas distribuidas más costosas y complejas, como los microservicios, la arquitectura basada en
eventos o incluso la arquitectura basada en el espacio. Esto hace que la arquitectura basada en servicios
sea una de las arquitecturas distribuidas más fáciles y rentables de implementar. Si bien se trata de una
propuesta atractiva, existe una contrapartida entre este ahorro de costos y la simplicidad en todas las
características que contienen calificaciones de cuatro estrellas. Cuanto mayor sea el costo y la complejidad,
mejores serán estas calificaciones.
Las arquitecturas basadas en servicios tienden a ser más confiables que otras arquitecturas distribuidas
debido a la naturaleza de grano grueso de los servicios de dominio. Los servicios más grandes implican
menos tráfico de red hacia y entre servicios, menos transacciones distribuidas y menos ancho de banda
utilizado, lo que aumenta la confiabilidad general con respecto a la red.
La arquitectura basada en servicios también es una opción natural cuando se realiza un diseño impulsado por el dominio.
Debido a que los servicios son de granularidad gruesa y tienen un alcance de dominio, cada dominio se adapta
perfectamente a un servicio de dominio implementado por separado. Cada servicio en la arquitectura basada en servicios
abarca un dominio particular (como el reciclaje en la aplicación de reciclaje electrónico), por lo que se compartimenta esa
funcionalidad en una sola unidad de software, lo que facilita la aplicación de cambios en ese dominio.
Mantener y coordinar las transacciones de bases de datos siempre es un problema con las arquitecturas distribuidas, ya
que generalmente dependen de la consistencia final en lugar de las transacciones ACID (atomicidad, consistencia,
aislamiento y durabilidad) tradicionales.
Sin embargo, la arquitectura basada en servicios preserva las transacciones ACID mejor que cualquier otra arquitectura
distribuida debido a la naturaleza de grano grueso de los servicios de dominio. Hay casos en los que la interfaz de usuario
o la puerta de enlace API pueden orquestar dos o más servicios de dominio y, en estos casos, la transacción necesitaría
depender de sagas y transacciones BASE. Sin embargo, en la mayoría de los casos, la transacción está limitada a un
servicio de dominio en particular, lo que permite la funcionalidad tradicional de transacción de confirmación y reversión
que se encuentra en la mayoría de las aplicaciones monolíticas.
Por último, la arquitectura basada en servicios es una buena opción para lograr un buen nivel de modularidad
arquitectónica sin tener que enredarse en las complejidades y los obstáculos de la granularidad. A medida que los
servicios se vuelven más granulares, comienzan a aparecer problemas relacionados con la orquestación y la coreografía.
Tanto la orquestación como la coreografía son necesarias cuando se deben coordinar varios servicios para completar
una determinada transacción comercial. La orquestación es la coordinación de varios servicios mediante el uso de un
servicio mediador independiente que controla y administra el flujo de trabajo de la transacción (como un director de
orquesta). La coreografía, por otro lado, es la coordinación de varios servicios mediante la cual cada servicio se comunica
con los demás sin el uso de un mediador central (como bailarines en una danza). A medida que los servicios se vuelven
más granulares, tanto la orquestación como la coreografía son necesarias para unir los servicios para completar la
transacción comercial. Sin embargo, debido a que los servicios dentro de una arquitectura basada en servicios tienden
a ser más granulares, no requieren tanta coordinación como otras arquitecturas distribuidas.
CAPÍTULO 14
El estilo de arquitectura basado en eventos es un estilo de arquitectura asíncrona distribuida popular que
se utiliza para producir aplicaciones altamente escalables y de alto rendimiento. También es muy
adaptable y se puede utilizar para aplicaciones pequeñas y también para aplicaciones grandes y
complejas. La arquitectura basada en eventos se compone de componentes de procesamiento de
eventos desacoplados que reciben y procesan eventos de forma asincrónica. Se puede utilizar como un
estilo de arquitectura independiente o integrado en otros estilos de arquitectura (como una arquitectura
de microservicios basada en eventos).
La mayoría de las aplicaciones siguen lo que se denomina un modelo basado en solicitudes (ilustrado en
la Figura 141). En este modelo, las solicitudes realizadas al sistema para realizar algún tipo de acción se
envían a un orquestador de solicitudes. El orquestador de solicitudes suele ser una interfaz de usuario,
pero también se puede implementar a través de una capa de API o un bus de servicios empresariales.
La función del orquestador de solicitudes es dirigir de forma determinista y sincrónica la solicitud a varios
procesadores de solicitudes. Los procesadores de solicitudes gestionan la solicitud, ya sea recuperando
o actualizando información en una base de datos.
Un buen ejemplo del modelo basado en solicitudes es la solicitud de un cliente para recuperar su historial
de pedidos de los últimos seis meses. La recuperación de información del historial de pedidos es una
solicitud determinista basada en datos que se realiza al sistema para obtener datos dentro de un contexto
específico, no un evento que sucede y al que el sistema debe reaccionar.
Por otro lado, un modelo basado en eventos reacciona a una situación particular y toma medidas en
función de ese evento. Un ejemplo de un modelo basado en eventos es la presentación de una oferta por
un artículo en particular dentro de una subasta en línea. La presentación de la oferta no es una solicitud
que se hace al sistema, sino un evento que sucede después de que se anuncia el precio de venta actual.
El sistema debe responder a este evento comparando la oferta con otras recibidas al mismo tiempo para
determinar quién es el postor más alto actual.
179
Machine Translated by Google
Topología
Existen dos topologías principales dentro de la arquitectura basada en eventos: la topología de mediador y la
topología de intermediario. La topología de mediador se utiliza comúnmente cuando se requiere control sobre
el flujo de trabajo de un proceso de eventos, mientras que la topología de intermediario se utiliza cuando se
requiere un alto grado de capacidad de respuesta y control dinámico sobre el procesamiento de un evento.
Debido a que las características de la arquitectura y las estrategias de implementación difieren entre estas
dos topologías, es importante comprender cada una para saber cuál es la más adecuada para una situación
particular.
Hay cuatro componentes arquitectónicos principales dentro de la topología del broker: un evento iniciador, el broker de
eventos, un procesador de eventos y un evento de procesamiento. El evento iniciador es el evento inicial que inicia todo el
flujo de eventos, ya sea un evento simple como hacer una oferta en una subasta en línea o eventos más complejos en un
sistema de beneficios de salud como cambiar de trabajo o casarse. El evento iniciador se envía a un canal de eventos en
el broker de eventos para su procesamiento. Dado que no hay un componente mediador en la topología del broker que
administre y controle el evento, un solo procesador de eventos acepta el evento iniciador del broker de eventos y comienza
el procesamiento de ese evento. El procesador de eventos que aceptó el evento iniciador realiza una tarea específica
asociada con el procesamiento de ese evento, luego anuncia asincrónicamente lo que hizo al resto del sistema creando lo
que se llama un evento de procesamiento. Este evento de procesamiento luego se envía asincrónicamente al broker de
eventos para su posterior procesamiento, si es necesario. Otros procesadores de eventos escuchan el evento de
procesamiento, reaccionan a ese evento haciendo algo y luego anuncian a través de un nuevo evento de procesamiento lo
que hicieron. Este proceso continúa hasta que nadie esté interesado en lo que hizo un procesador de eventos final.
El componente del agente de eventos suele estar federado (es decir, múltiples instancias agrupadas en clústeres basadas
en dominios), donde cada agente federado contiene todos los canales de eventos utilizados dentro del flujo de eventos
para ese dominio en particular. Debido a la naturaleza de transmisión asincrónica y desacoplada de tipo "activar y olvidar"
de la topología del agente, los temas (o intercambios de temas en el caso de AMQP) se utilizan generalmente en la
topología del agente mediante un modelo de mensajería de publicación y suscripción.
Siempre es una buena práctica dentro de la topología del intermediario que cada procesador de eventos
anuncie lo que hizo al resto del sistema, independientemente de si a algún otro procesador de eventos le
interesa o no esa acción. Esta práctica proporciona extensibilidad arquitectónica si se requiere funcionalidad
adicional para el procesamiento de ese evento.
Por ejemplo, supongamos que, como parte de un proceso de eventos complejo, como se ilustra en la Figura
143, se genera y envía un correo electrónico a un cliente para notificarle una acción particular realizada. El
procesador de eventos de notificación generaría y enviaría el correo electrónico y luego anunciaría esa acción
al resto del sistema a través de un nuevo evento de procesamiento enviado a un tema. Sin embargo, en este
caso, ningún otro procesador de eventos está escuchando eventos sobre ese tema y, como tal, el mensaje
simplemente desaparece.
Este es un buen ejemplo de extensibilidad arquitectónica. Si bien puede parecer un desperdicio de recursos
enviar mensajes que se ignoran, no lo es. Supongamos que surge un nuevo requisito para analizar los correos
electrónicos que se han enviado a los clientes. Este nuevo procesador de eventos se puede agregar al
sistema general con un mínimo esfuerzo porque la información del correo electrónico está disponible a través
del tema del correo electrónico para el nuevo analizador sin tener que agregar ninguna infraestructura adicional
ni aplicar ningún cambio a otros procesadores de eventos.
Para ilustrar cómo funciona la topología del intermediario, considere el flujo de procesamiento en un sistema
típico de ingreso de pedidos minoristas, como se ilustra en la Figura 144, donde se realiza un pedido de un
artículo (por ejemplo, un libro como este). En este ejemplo, el procesador de eventos OrderPlacement recibe
el evento de inicio (PlaceOrder), inserta el pedido en una tabla de base de datos y devuelve un ID de pedido
al cliente. Luego anuncia al resto del sistema que creó un pedido a través de un evento de procesamiento de
creación de pedidos . Observe que tres procesadores de eventos están interesados en ese evento: el
procesador de eventos Notification , el procesador de eventos Payment y el procesador de eventos Inventory .
Los tres procesadores de eventos realizan sus tareas en paralelo.
El procesador de eventos de notificación recibe el evento de procesamiento creado por el pedido y envía
un correo electrónico al cliente. Luego, genera otro evento de procesamiento (correo electrónico enviado).
Observe que ningún otro procesador de eventos está escuchando ese evento. Esto es normal e ilustra
el ejemplo anterior que describe la extensibilidad arquitectónica: un enlace en el lugar para que otros
procesadores de eventos puedan eventualmente acceder a esa fuente de eventos, si es necesario.
Al analizar el ejemplo anterior, observe que todos los procesadores de eventos están altamente
desacoplados y son independientes entre sí. La mejor manera de entender la topología de
intermediarios es pensar en ella como una carrera de relevos. En una carrera de relevos, los
corredores sostienen un testigo (un palo de madera) y corren una cierta distancia (por ejemplo, 1,5
kilómetros), luego pasan el testigo al siguiente corredor, y así sucesivamente hasta que el último
corredor cruza la línea de meta. En las carreras de relevos, una vez que un corredor entrega el
testigo, ese corredor termina la carrera y pasa a otras cosas. Esto también es cierto con la topología de intermediarios.
Una vez que un procesador de eventos entrega el evento, ya no participa en el procesamiento de ese
evento específico y está disponible para reaccionar ante otros eventos de inicio o procesamiento.
Además, cada procesador de eventos puede escalar de forma independiente de los demás para
manejar condiciones de carga variables o copias de seguridad en el procesamiento dentro de ese
evento. Los temas proporcionan el punto de contrapresión si un procesador de eventos deja de
funcionar o se ralentiza debido a algún problema del entorno.
Ventajas Desventajas
Al igual que en la topología de intermediario, el evento iniciador es el evento que inicia todo el proceso
de generación de eventos. A diferencia de la topología de intermediario, el evento iniciador se envía a
una cola de eventos iniciadores, que es aceptada por el mediador de eventos. El mediador de eventos
solo conoce los pasos involucrados en el procesamiento del evento y, por lo tanto, genera eventos de
procesamiento correspondientes que se envían a canales de eventos dedicados (generalmente colas)
en forma de mensajería punto a punto. Luego, los procesadores de eventos escuchan los canales de
eventos dedicados, procesan el evento y, por lo general, responden al mediador que han completado
su trabajo. A diferencia de la topología de intermediario, los procesadores de eventos dentro de la
topología de mediador no anuncian lo que hicieron al resto del sistema. La topología de mediador se
ilustra en la Figura 145.
Sin embargo, si el flujo de trabajo del evento requiere mucho procesamiento condicional y múltiples
rutas dinámicas con directivas de manejo de errores complejas, entonces un mediador como
ODE de Apache o el Administrador de procesos Oracle BPEL Sería una buena opción. Estos
mediadores se basan en el lenguaje de ejecución de procesos empresariales (BPEL), Una estructura
similar a XML que describe los pasos involucrados en el procesamiento de un evento. Los artefactos
BPEL también contienen elementos estructurados que se utilizan para el manejo de errores, redirección,
multidifusión, etc. BPEL es un lenguaje potente pero relativamente complejo de aprender y, como tal,
generalmente se crea utilizando herramientas de interfaz gráfica proporcionadas en el motor BPEL del producto.
suite.
BPEL es bueno para flujos de trabajo complejos y dinámicos, pero no funciona bien para aquellos
flujos de trabajo de eventos que requieren transacciones de larga duración que involucran la
intervención humana durante todo el proceso del evento. Por ejemplo, supongamos que se está
colocando una transacción a través de un evento de inicio de colocación de transacción . El mediador
del evento acepta este evento, pero durante el procesamiento descubre que se requiere una aprobación
manual porque la transacción supera una cierta cantidad de acciones. En este caso, el mediador del
evento tendría que detener el procesamiento del evento, enviar una notificación a un operador senior
para la aprobación manual y esperar a que se produzca dicha aprobación. En estos casos, un motor
de gestión de procesos empresariales (BPM) como jBPM sería necesario.
Es importante conocer los tipos de eventos que serán procesados a través del mediador para poder
hacer la elección correcta para la implementación del mediador de eventos.
Elegir Apache Camel para eventos complejos y de larga duración que involucran interacción humana
sería extremadamente difícil de escribir y mantener. Del mismo modo, usar un motor BPM para flujos
de eventos simples llevaría meses de esfuerzo desperdiciado cuando lo mismo podría lograrse en
Apache Camel en cuestión de días.
Dado que es poco frecuente que todos los eventos sean de una misma clase de complejidad,
recomendamos clasificar los eventos como simples, difíciles o complejos y que cada evento pase
siempre por un mediador simple (como Apache Camel o Mule). El mediador simple puede entonces
interrogar la clasificación del evento y, en función de esa clasificación, gestionar el evento en sí o
reenviarlo a otro mediador de eventos más complejo. De esta manera, todos los tipos de eventos
pueden ser procesados eficazmente por el tipo de mediador necesario para ese evento. Este modelo
de delegación de mediadores se ilustra en la Figura 146.
Observe en la Figura 146 que el Mediador de eventos simples genera y envía un evento de
procesamiento cuando el flujo de trabajo del evento es simple y puede ser manejado por el mediador
simple. Sin embargo, observe que cuando el evento iniciador que llega al Mediador de eventos
simples se clasifica como duro o complejo, reenvía el evento iniciador original a los mediadores
correspondientes (BPEL o BMP). El Mediador de eventos simples, después de haber interceptado
el evento original, puede seguir siendo responsable de saber cuándo se completa ese evento, o
simplemente delega todo el flujo de trabajo (incluida la notificación al cliente) a los otros mediadores.
Para ilustrar cómo funciona la topología del mediador, considere el mismo ejemplo del sistema de
ingreso de órdenes minoristas descrito en la sección anterior sobre la topología del corredor, pero
esta vez utilizando la topología del mediador. En este ejemplo, el mediador conoce los pasos
necesarios para procesar este evento en particular. Este flujo de eventos (interno al componente
del mediador) se ilustra en la Figura 147.
Siguiendo el ejemplo anterior, el mismo evento de inicio (PlaceOrder) se envía a la cola de eventos del
cliente para su procesamiento. El mediador del cliente toma este evento de inicio y comienza a generar
eventos de procesamiento según el flujo de la Figura 147. Observe que los múltiples eventos que se
muestran en los pasos 2, 3 y 4 se realizan de manera simultánea y en serie entre los pasos. En otras
palabras, el paso 3 (completar el pedido) debe completarse y confirmarse antes de que se pueda
notificar al cliente que el pedido está listo para ser enviado en el paso 4 (enviar el pedido).
Una vez recibido el evento de inicio, el mediador del Cliente genera un evento de procesamiento de
creación de pedido y envía este mensaje a la cola de colocación de pedidos (consulte la Figura 148).
El procesador de eventos de Colocación de pedidos acepta este evento y valida y crea el pedido,
devolviendo al mediador un acuse de recibo junto con el ID del pedido. En este punto, el mediador
podría enviar ese ID de pedido de vuelta al cliente, indicando que se realizó el pedido, o podría tener
que continuar hasta que se completen todos los pasos (esto se basaría en reglas comerciales específicas
sobre la colocación de pedidos).
Ahora que el paso 1 está completo, el mediador pasa al paso 2 (ver Figura 149) y genera
tres mensajes al mismo tiempo: emailcustomer, applypayment y adjustinventory. Estos
eventos de procesamiento se envían a sus respectivas colas. Los tres procesadores de
eventos reciben estos mensajes, realizan sus respectivas tareas y notifican al mediador que
el procesamiento se ha completado. Observe que el mediador debe esperar hasta recibir el
acuse de recibo de los tres procesos paralelos antes de pasar al paso 3. En este punto, si
ocurre un error en uno de los procesadores de eventos paralelos, el mediador puede tomar
medidas correctivas para solucionar el problema (esto se analiza más adelante en esta
sección con más detalle).
Una vez que el mediador obtiene un reconocimiento exitoso de todos los procesadores de
eventos en el paso 2, puede avanzar al paso 3 para completar el pedido (consulte la Figura
1410). Observe una vez más que ambos eventos (completar pedido y stock de pedido)
pueden ocurrir simultáneamente. Los procesadores de eventos OrderFulfillment y Warehouse
aceptan estos eventos, realizan su trabajo y devuelven un reconocimiento al mediador.
Una vez que se completan estos eventos, el mediador pasa al paso 4 (ver Figura 1411)
para enviar el pedido. Este paso genera otro evento de procesamiento de correo electrónico
al cliente con información específica sobre qué hacer (en este caso, notificar al cliente que
el pedido está listo para ser enviado), así como un evento de envío del pedido .
Finalmente, el mediador pasa al paso 5 (ver Figura 1412) y genera otro evento de correo
electrónico contextual del cliente para notificarle que el pedido ha sido enviado.
En este punto, el flujo de trabajo finaliza y el mediador marca el flujo del evento iniciador
como completo y elimina todo el estado asociado con el evento iniciador.
El componente mediador tiene conocimiento y control sobre el flujo de trabajo, algo que la
topología del intermediario no tiene. Debido a que el mediador controla el flujo de trabajo, puede
mantener el estado del evento y administrar el manejo de errores, la capacidad de recuperación
y las capacidades de reinicio. Por ejemplo, supongamos que en el ejemplo anterior el pago no se
aplicó debido a que la tarjeta de crédito estaba vencida. En este caso, el mediador recibe esta
condición de error y, al saber que el pedido no se puede completar (paso 3) hasta que se aplique
el pago, detiene el flujo de trabajo y registra el estado de la solicitud en su propio almacén de datos persistente.
Una vez que finalmente se aplica el pago, el flujo de trabajo se puede reiniciar desde donde se
dejó (en este caso, el comienzo del paso 3).
Otra diferencia inherente entre la topología de intermediario y la de mediador es cómo difieren los
eventos de procesamiento en términos de su significado y cómo se utilizan. En el ejemplo de
topología de intermediario de la sección anterior, los eventos de procesamiento se publicaron
como eventos que habían ocurrido en el sistema (como creación de pedido, aplicación de pago
y envío de correo electrónico). Los procesadores de eventos tomaron alguna acción y otros
procesadores de eventos reaccionaron a esa acción. Sin embargo, en la topología de mediador,
los eventos de procesamiento como realizar un pedido, enviar un correo electrónico y completar
un pedido son comandos (cosas que deben suceder) en lugar de eventos (cosas que ya
sucedieron). Además, en la topología de mediador, se debe procesar un comando, mientras que
se puede ignorar un evento en la topología de intermediario.
Si bien la topología del mediador aborda los problemas asociados con la topología del intermediario,
existen algunos aspectos negativos asociados con la topología del mediador. En primer lugar, es muy
difícil modelar de manera declarativa el procesamiento dinámico que ocurre dentro de un flujo de
eventos complejo. Como resultado, muchos flujos de trabajo dentro del mediador solo manejan el
procesamiento general, y se utiliza un modelo híbrido que combina las topologías del mediador y del
intermediario para abordar la naturaleza dinámica del procesamiento de eventos complejos (como
las condiciones de falta de existencias u otros errores atípicos). Además, aunque los procesadores
de eventos pueden escalar fácilmente de la misma manera que la topología del intermediario, el
mediador también debe escalar, algo que ocasionalmente produce un cuello de botella en el flujo de
procesamiento de eventos general. Finalmente, los procesadores de eventos no están tan
desacoplados en la topología del mediador como en la topología del intermediario, y el rendimiento
no es tan bueno debido a que el mediador controla el procesamiento del evento. Estas compensaciones
se resumen en la Tabla 142.
Ventajas Desventajas
Capacidades asincrónicas
El estilo de arquitectura basado en eventos ofrece una característica única con respecto a otros
estilos de arquitectura, ya que se basa únicamente en la comunicación asincrónica tanto para el
procesamiento de tipo "disparar y olvidar" (no se requiere respuesta) como para el procesamiento de
solicitud/respuesta (se requiere respuesta del consumidor del evento). La comunicación asincrónica
puede ser una técnica poderosa para aumentar la capacidad de respuesta general de un sistema.
Considere el ejemplo ilustrado en la Figura 1413 donde un usuario publica un comentario en un sitio
web para una revisión de un producto en particular. Suponga que el servicio de comentarios en este
ejemplo tarda 3000 milisegundos en publicar el comentario porque pasa por varios motores de
análisis: un verificador de malas palabras para verificar palabras inaceptables, un verificador
gramatical para asegurarse de que las estructuras de las oraciones no digan algo abusivo y,
finalmente, un verificador de contexto para asegurarse de que el comentario se refiere a un producto
en particular y no solo a una diatriba política. Observe en la Figura 1413 que la ruta superior utiliza
una llamada RESTful sincrónica para publicar el comentario: 50 milisegundos de latencia para que el
servicio reciba la publicación, 3000 milisegundos para publicar el comentario y 50 milisegundos de
latencia de red para responder al usuario que se publicó el comentario. Esto crea un tiempo de
respuesta para el usuario de 3100 milisegundos para publicar un comentario. Ahora observe la ruta
inferior y observe que con el uso de mensajería asincrónica, el tiempo de respuesta desde la
perspectiva del usuario final para publicar un comentario en el sitio web es de solo 25 milisegundos
(en comparación con 3100 milisegundos). Todavía se necesitan 3025 milisegundos para publicar el
comentario (25 milisegundos para recibir el mensaje y 3000 milisegundos para publicar el comentario),
pero desde la perspectiva del usuario final ya se ha hecho.
La diferencia en el tiempo de respuesta entre los dos ejemplos de la Figura 1413, de 3100
milisegundos a 25 milisegundos, es asombrosa. Hay una salvedad. En la ruta sincrónica que se
muestra en la parte superior del diagrama, se garantiza al usuario final que el comentario se ha
publicado. Sin embargo, en la ruta inferior solo hay un acuse de recibo de la publicación, con una
promesa futura de que eventualmente el comentario se publicará. Desde la perspectiva del usuario
final, el comentario se ha publicado. Pero ¿qué sucede si el usuario ha escrito una mala palabra en
el comentario? En este caso, el comentario sería rechazado, pero no hay forma de volver al usuario
final. ¿O sí? En este ejemplo, suponiendo que el usuario está registrado en el sitio web (que para
publicar un comentario tendría que estar), se podría enviar un mensaje al usuario indicando un
problema con el comentario y algunas sugerencias sobre cómo solucionarlo. Este es un ejemplo
simple.
¿Qué tal un ejemplo más complicado donde la compra de acciones se realiza de forma asincrónica (lo que
se denomina transacción de acciones) y no hay forma de comunicarse con el usuario?
Manejo de errores
El patrón de eventos de flujo de trabajo de la arquitectura reactiva es una forma de abordar los
problemas asociados con el manejo de errores en un flujo de trabajo asincrónico. Este patrón es un
patrón de arquitectura reactiva que aborda tanto la resiliencia como la capacidad de respuesta. En
otras palabras, el sistema puede ser resiliente en términos de manejo de errores sin que esto afecte
la capacidad de respuesta.
envía ese error al procesador de flujo de trabajo y pasa al siguiente mensaje en la cola de eventos. De esta
manera, la capacidad de respuesta general no se ve afectada porque el siguiente mensaje se procesa
inmediatamente. Si el consumidor de eventos tuviera que dedicar tiempo a intentar averiguar el error, no estaría
leyendo el siguiente mensaje en la cola, lo que afectaría la capacidad de respuesta no solo del siguiente
mensaje, sino de todos los demás mensajes que esperan en la cola para ser procesados.
Una vez que el procesador de flujo de trabajo recibe un error, intenta averiguar qué es lo que está mal en el
mensaje. Puede tratarse de un error estático y determinista, o puede aprovechar algunos algoritmos de
aprendizaje automático para analizar el mensaje y detectar alguna anomalía en los datos.
De cualquier manera, el procesador de flujo de trabajo realiza cambios en los datos originales de manera
programática (sin intervención humana) para intentar repararlos y luego los envía de vuelta a la cola de origen.
El consumidor de eventos ve este mensaje como uno nuevo e intenta procesarlo nuevamente, con suerte esta
vez con cierto éxito. Por supuesto, hay muchas ocasiones en las que el procesador de flujo de trabajo no puede
determinar qué es lo que está mal con el mensaje. En estos casos, el procesador de flujo de trabajo envía el
mensaje a otra cola, que luego se recibe en lo que generalmente se denomina un "panel de control", una
aplicación que se parece a Outlook de Microsoft o Mail de Apple. Este panel de control generalmente reside en
el escritorio de una persona importante, que luego mira el mensaje, le aplica correcciones manuales y luego lo
vuelve a enviar a la cola original (generalmente a través de una variable de encabezado de mensaje de
respuesta).
Para ilustrar el patrón de eventos del flujo de trabajo, supongamos que un asesor comercial en una parte del
país acepta órdenes comerciales (instrucciones sobre qué acciones comprar y por cuántas acciones) en nombre
de una gran empresa comercial en otra parte del país. El asesor agrupa las órdenes comerciales (lo que
generalmente se denomina una canasta) y las envía de manera asincrónica a la gran empresa comercial para
que las coloque en un corredor para que las acciones puedan ser compradas.
Comprado. Para simplificar el ejemplo, supongamos que el contrato de instrucciones comerciales debe
cumplir lo siguiente:
Supongamos que la gran empresa comercial recibe la siguiente canasta de órdenes comerciales de Apple
(AAPL) del asesor comercial:
12654A87FR4,COMPRAR,AAPL,1254
87R54E3068U,COMPRAR,AAPL,3122
6R4NB7609JJ,COMPRAR,AAPL,5433
2WE35HF6DHF,COMPRAR,AAPL,8756 ACCIONES
764980974R2,COMPRA,AAPL,1211
1533G658HD8,COMPRAR,AAPL,2654
Observe que la cuarta instrucción de transacción (2WE35HF6DHF, BUY, AAPL, 8756 SHARES) tiene la
palabra SHARES después del número de acciones para la transacción. Cuando estas órdenes de
transacción asincrónicas son procesadas por la gran empresa de transacciones sin ninguna capacidad de
manejo de errores, ocurre el siguiente error dentro del servicio de colocación de transacciones:
Cuando ocurre esta excepción, no hay nada que el servicio de colocación comercial pueda hacer, porque
se trata de una solicitud asincrónica, excepto posiblemente registrar la condición de error.
En otras palabras, no hay ningún usuario que responda sincrónicamente y solucione el error.
La aplicación del patrón de eventos de flujo de trabajo puede corregir este error de forma programática.
Debido a que la gran empresa comercial no tiene control sobre el asesor comercial y los datos de órdenes
comerciales correspondientes que envía, debe reaccionar para corregir el error por sí misma (como se
ilustra en la Figura 1415). Cuando se produce el mismo error (2WE35HF6DHF,BUY,AAPL,8756
SHARES), el servicio de colocación de operaciones delega inmediatamente el error mediante mensajes
asincrónicos al servicio de error de colocación de operaciones para su manejo, pasando junto con la
información del error sobre la excepción:
El servicio de error de colocación de operaciones (que actúa como delegado del flujo de trabajo) recibe el
error e inspecciona la excepción. Al ver que se trata de un problema con la palabra SHARES en el campo de
cantidad de acciones, el servicio de error de colocación de operaciones elimina la palabra SHARES y vuelve
a enviar la operación para su reprocesamiento:
...
operación realizada: 1533G658HD8,BUY,AAPL,2654
operación realizada: 2WE35HF6DHF,BUY,AAPL,8756 < esta fue la operación original por error
Una de las consecuencias del patrón de eventos de flujo de trabajo es que los mensajes con errores se
procesan fuera de secuencia cuando se vuelven a enviar. En nuestro ejemplo de operaciones, el orden de
los mensajes es importante, porque todas las operaciones dentro de una cuenta determinada deben
procesarse en orden (por ejemplo, una VENTA para IBM debe ocurrir antes de una COMPRA para AAPL
dentro de la misma cuenta de corretaje). Aunque no es imposible, es una tarea compleja mantener el orden
de los mensajes dentro de un contexto determinado (en este caso, el número de cuenta de corretaje). Una
forma de abordar esto es que el servicio de Colocación de operaciones ponga en cola y almacene el número
de cuenta de la operación con error. Cualquier operación con ese mismo número de cuenta se almacenaría
en una cola temporal para su posterior procesamiento (en orden FIFO). Una vez que se corrige y procesa la
operación que originalmente tenía un error, el servicio de Colocación de operaciones quita de la cola las
operaciones restantes para esa misma cuenta y las procesa en orden.
La pérdida de datos es siempre una preocupación principal cuando se trabaja con comunicaciones asincrónicas.
Lamentablemente, existen muchos lugares donde se pueden producir pérdidas de datos dentro de una arquitectura
basada en eventos. Por pérdida de datos nos referimos a un mensaje que se pierde o que nunca llega a su destino final.
Afortunadamente, existen técnicas básicas listas para usar que se pueden aprovechar para evitar la pérdida de datos
cuando se utilizan mensajes asincrónicos.
Para ilustrar los problemas asociados con la pérdida de datos dentro de una arquitectura basada en
eventos, supongamos que el procesador de eventos A envía de forma asincrónica un mensaje a una
cola. El procesador de eventos B acepta el mensaje e inserta los datos dentro del mensaje en una base
de datos. Como se ilustra en la Figura 1416, pueden ocurrir tres áreas de pérdida de datos dentro de
este escenario típico:
1. El mensaje nunca llega a la cola desde el procesador de eventos A; o incluso si lo hace, el intermediario se cae antes
de que el siguiente procesador de eventos pueda recuperar el mensaje.
mensaje.
2. El procesador de eventos B saca de la cola el siguiente mensaje disponible y se bloquea antes de que se complete.
Puede procesar el evento.
3. El procesador de eventos B no puede conservar el mensaje en la base de datos debido a algún problema.
Error de datos.
Figura 1416. Dónde puede ocurrir la pérdida de datos dentro de una arquitectura basada en eventos
Cada una de estas áreas de pérdida de datos se puede mitigar mediante técnicas básicas de mensajería.
El problema 1 (el mensaje nunca llega a la cola) se resuelve fácilmente aprovechando las colas de mensajes persistentes,
junto con algo llamado envío sincrónico. Las colas de mensajes persistentes admiten lo que se conoce como entrega
garantizada. Cuando el agente de mensajes recibe el mensaje, no solo lo almacena en la memoria para una recuperación
rápida, sino que también persiste el mensaje en algún tipo de almacenamiento de datos físico (como un sistema de archivos
o una base de datos). Si el agente de mensajes deja de funcionar, el mensaje se almacena físicamente en el disco para
que cuando vuelva a funcionar, el mensaje esté disponible para su procesamiento. El envío sincrónico realiza una espera
de bloqueo en el productor de mensajes hasta que el agente haya reconocido que el mensaje se ha persistido. Con estas
dos técnicas básicas
No hay forma de perder un mensaje entre el productor del evento y la cola porque el mensaje todavía está con
el productor del mensaje o persiste dentro de la cola.
El problema 2 (el procesador de eventos B saca de la cola el siguiente mensaje disponible y se bloquea antes
de poder procesar el evento) también se puede resolver utilizando una técnica básica de mensajería llamada
modo de reconocimiento del cliente. De manera predeterminada, cuando se saca de la cola un mensaje, se lo
elimina inmediatamente de la cola (algo llamado modo de reconocimiento automático). El modo de
reconocimiento del cliente mantiene el mensaje en la cola y adjunta el ID del cliente al mensaje para que
ningún otro consumidor pueda leerlo. Con este modo, si el procesador de eventos B se bloquea, el mensaje
aún se conserva en la cola, lo que evita la pérdida de mensajes en esta parte del flujo de mensajes.
El problema 3 (el procesador de eventos B no puede conservar el mensaje en la base de datos debido a algún
error en los datos) se soluciona aprovechando las transacciones ACID (atomicidad, consistencia, aislamiento,
durabilidad) a través de una confirmación de la base de datos. Una vez que se realiza la confirmación de la
base de datos, se garantiza que los datos se conservarán en la base de datos. Al aprovechar algo llamado
soporte del último participante (LPS), se elimina el mensaje de la cola de conservación al reconocer que se ha
completado el procesamiento y que el mensaje se ha conservado. Esto garantiza que el mensaje no se pierda
durante el tránsito desde el procesador de eventos A hasta la base de datos. Estas técnicas se ilustran en la
Figura 1417.
Capacidades de transmisión
Otra de las características exclusivas de la arquitectura basada en eventos es la capacidad de
transmitir eventos sin saber quién (si es que alguien) recibe el mensaje y qué hace con él. Esta
técnica, que se ilustra en la Figura 1418, muestra que cuando un productor publica un mensaje, ese
mismo mensaje es recibido por varios suscriptores.
La difusión es quizás el nivel más alto de desacoplamiento entre procesadores de eventos porque el
productor del mensaje de difusión generalmente no sabe qué procesadores de eventos recibirán el mensaje
de difusión y, lo que es más importante, qué harán con el mensaje. Las capacidades de difusión son una
parte esencial de los patrones para la coherencia final, el procesamiento de eventos complejos (CEP) y
una serie de otras situaciones.
Considere los cambios frecuentes en los precios de las acciones de los instrumentos que se negocian en
el mercado de valores. Cada ticker (el precio actual de una acción en particular) puede influir en una serie
de cosas. Sin embargo, el servicio que publica el último precio simplemente lo transmite sin saber cómo se
utilizará esa información.
SolicitudRespuesta
Hasta ahora, en este capítulo hemos tratado solicitudes asincrónicas que no necesitan una respuesta
inmediata del consumidor de eventos. Pero, ¿qué sucede si se necesita un ID de pedido al solicitar
un libro? ¿Qué sucede si se necesita un número de confirmación al reservar un vuelo? Estos son
ejemplos de comunicación entre servicios o procesadores de eventos que requieren algún tipo de
comunicación sincrónica.
1. El productor de eventos envía un mensaje a la cola de solicitudes y registra el ID de mensaje único (en
este caso, el ID 124). Observe que el ID de correlación (CID) en este caso es nulo.
2. El productor de eventos ahora realiza una espera de bloqueo en la cola de respuestas con un filtro
de mensajes (también llamado selector de mensajes), donde el ID de correlación en el encabezado
del mensaje es igual al ID del mensaje original (en este caso 124). Observe que hay dos mensajes
en la cola de respuestas: el ID de mensaje 855 con el ID de correlación 120 y el ID de mensaje 856
con el ID de correlación 122. Ninguno de estos mensajes será detectado porque el ID de correlación
no coincide con lo que busca el consumidor de eventos (CID 124).
La otra técnica utilizada para implementar la mensajería de solicitudrespuesta es utilizar una cola
temporal para la cola de respuesta. Una cola temporal está dedicada a la solicitud específica, se crea
cuando se realiza la solicitud y se elimina cuando la solicitud finaliza. Esta técnica, como se ilustra en la
Figura 1421, no requiere un ID de correlación porque la cola temporal es una cola dedicada que solo
conoce el productor del evento para la solicitud específica.
La técnica de cola temporal funciona de la siguiente manera:
1. El productor de eventos crea una cola temporal (o se crea una automáticamente, dependiendo del
agente de mensajes) y envía un mensaje a la cola de solicitudes,
SolicitudRespuesta | 205
Machine Translated by Google
pasando el nombre de la cola temporal en el encabezado de respuesta (o algún otro atributo personalizado
acordado en el encabezado del mensaje).
2. El productor de eventos realiza una espera de bloqueo en la cola de respuestas temporal. No se necesita
ningún selector de mensajes porque cualquier mensaje enviado a esta cola pertenece únicamente al
productor de eventos que originalmente envió el mensaje.
3. El consumidor de eventos recibe el mensaje, procesa la solicitud y envía un mensaje de respuesta a la cola
de respuestas indicada en el encabezado de respuesta.
Si bien la técnica de cola temporal es mucho más sencilla, el agente de mensajes debe crear una cola temporal
para cada solicitud realizada y luego eliminarla inmediatamente después. Los grandes volúmenes de mensajes
pueden ralentizar significativamente el agente de mensajes y afectar el rendimiento general y la capacidad de
respuesta. Por este motivo, generalmente recomendamos utilizar la técnica de identificación de correlación.
Tanto el modelo basado en solicitudes como el modelo basado en eventos son enfoques viables para diseñar
sistemas de software. Sin embargo, la elección del modelo adecuado es esencial para el éxito general del sistema.
Recomendamos elegir el modelo basado en solicitudes para solicitudes bien estructuradas y basadas en datos
(como la recuperación de datos de perfiles de clientes) cuando se necesita certeza y control sobre el flujo de
trabajo. Recomendamos elegir el modelo basado en eventos para eventos flexibles y basados en acciones que
requieren altos niveles de capacidad de respuesta y escala, con un procesamiento de usuarios complejo y
dinámico.
Comprender las ventajas y desventajas del modelo basado en eventos también ayuda a decidir cuál
es el más adecuado. La Tabla 143 enumera las ventajas y desventajas del modelo basado en
eventos de la arquitectura impulsada por eventos.
Mejor respuesta al contenido dinámico del usuario Solo admite consistencia eventual
Mejor agilidad y gestión del cambio Menos certeza sobre el resultado del flujo de eventos
Agregar una arquitectura basada en eventos a cualquier estilo de arquitectura ayuda a eliminar cuellos de botella,
proporciona un punto de contrapresión en caso de que se realicen copias de seguridad de las solicitudes y
proporciona un nivel de capacidad de respuesta del usuario que no se encuentra en otros estilos de arquitectura.
Tanto los microservicios como la arquitectura basada en el espacio aprovechan la mensajería para el bombeo de
datos, enviando datos de forma asincrónica a otro procesador que, a su vez, actualiza los datos en una base de
datos. Ambos también aprovechan la arquitectura basada en eventos para proporcionar un nivel de escalabilidad
programática a los servicios en una arquitectura de microservicios y a las unidades de procesamiento en una
arquitectura basada en el espacio cuando se utiliza la mensajería para la comunicación entre servicios.
La arquitectura basada en eventos es principalmente una arquitectura particionada técnicamente, ya que cualquier dominio
en particular se distribuye entre varios procesadores de eventos y se vincula entre sí a través de mediadores, colas y
temas. Los cambios en un dominio en particular suelen afectar a muchos procesadores de eventos, mediadores y otros
artefactos de mensajería, por lo que la arquitectura basada en eventos no está particionada en el dominio.
La cantidad de cuantos dentro de una arquitectura basada en eventos puede variar de uno a muchos cuantos, lo que
generalmente se basa en las interacciones de la base de datos dentro de cada procesador de eventos y el procesamiento
de solicitudrespuesta. Aunque toda la comunicación en una arquitectura basada en eventos es asincrónica, si varios
procesadores de eventos comparten una única instancia de base de datos, todos estarían contenidos dentro del mismo
cuanto arquitectónico.
Lo mismo ocurre con el procesamiento de solicitudrespuesta: aunque la comunicación sigue siendo asincrónica entre los
procesadores de eventos, si se necesita una solicitud de inmediato del consumidor de eventos, vincula esos procesadores
de eventos de forma sincrónica; por lo tanto, pertenecen al mismo quantum.
Para ilustrar este punto, considere el ejemplo en el que un procesador de eventos envía una solicitud a otro
procesador de eventos para realizar un pedido. El primer procesador de eventos debe esperar un ID de pedido del
otro procesador de eventos para continuar. Si el segundo procesador de eventos que realiza el pedido y genera un
ID de pedido está inactivo, el primer procesador de eventos no puede continuar. Por lo tanto, son parte de la misma
arquitectura cuántica y comparten las mismas características arquitectónicas, aunque ambos envíen y reciban
mensajes asincrónicos.
La arquitectura basada en eventos obtiene cinco estrellas por rendimiento, escalabilidad y tolerancia a fallas, las
principales fortalezas de este estilo de arquitectura. El alto rendimiento se logra mediante comunicaciones
asincrónicas combinadas con un procesamiento altamente paralelo.
Se logra una alta escalabilidad mediante el equilibrio de carga programático de los procesadores de eventos
(también llamados consumidores en competencia). A medida que aumenta la carga de solicitudes, se pueden
agregar procesadores de eventos adicionales mediante programación para manejar las solicitudes adicionales.
La tolerancia a fallas se logra a través de procesadores de eventos altamente desacoplados y asincrónicos que
brindan consistencia eventual y procesamiento eventual de flujos de trabajo de eventos.
Siempre que la interfaz de usuario o un procesador de eventos que realiza una solicitud no necesite una respuesta
inmediata, se pueden aprovechar las promesas y los futuros para procesar el evento en un momento posterior si
otros procesadores posteriores no están disponibles.
La simplicidad general y la tasa de capacidad de prueba son relativamente bajas con la arquitectura basada en
eventos, principalmente debido a los flujos de eventos dinámicos y no deterministas que se encuentran típicamente
dentro de este estilo de arquitectura. Si bien los flujos deterministas dentro del modelo basado en solicitudes son
relativamente fáciles de probar porque las rutas y los resultados generalmente se conocen, ese no es el caso con
el modelo basado en eventos. A veces no se sabe cómo reaccionarán los procesadores de eventos a los eventos
dinámicos y qué mensajes podrían producir. Estos "diagramas de árbol de eventos" pueden ser extremadamente
complejos y generar cientos o incluso miles de escenarios, lo que hace que sea muy difícil gobernarlos y probarlos.
Finalmente, las arquitecturas basadas en eventos son altamente evolutivas, de ahí la calificación de cinco estrellas.
Agregar nuevas funciones a través de procesadores de eventos existentes o nuevos es relativamente sencillo, en
particular en la topología del intermediario. Al proporcionar enlaces a través de mensajes publicados en la topología
del intermediario, los datos ya están disponibles, por lo que no se requieren cambios en la infraestructura o en los
procesadores de eventos existentes para agregar esa nueva funcionalidad.
CAPÍTULO 15
La mayoría de las aplicaciones empresariales basadas en la Web siguen el mismo flujo de solicitud general: una
solicitud de un navegador llega al servidor Web, luego a un servidor de aplicaciones y, finalmente, al servidor de
base de datos. Si bien este patrón funciona muy bien para un pequeño grupo de usuarios, comienzan a aparecer
cuellos de botella a medida que aumenta la carga de usuarios, primero en la capa del servidor Web, luego en la
capa del servidor de aplicaciones y, finalmente, en la capa del servidor de base de datos. La respuesta habitual a
los cuellos de botella basados en un aumento en la carga de usuarios es escalar horizontalmente los servidores Web. Esto es
Relativamente fácil y económico, y a veces funciona para resolver los problemas de cuello de botella. Sin embargo,
en la mayoría de los casos de alta carga de usuarios, escalar horizontalmente la capa del servidor web simplemente
mueve el cuello de botella hacia abajo, al servidor de aplicaciones. Escalar servidores de aplicaciones puede ser
más complejo y costoso que los servidores web y, por lo general, solo mueve el cuello de botella hacia abajo, al
servidor de base de datos, que es aún más difícil y costoso de escalar.
Incluso si puede escalar la base de datos, lo que obtendrá finalmente será una topología en forma de triángulo,
donde la parte más ancha del triángulo son los servidores web (los más fáciles de escalar) y la parte más pequeña
es la base de datos (los más difíciles de escalar), como se ilustra en la Figura 151.
En cualquier aplicación de gran volumen con una gran carga de usuarios simultáneos, la base de datos suele ser
el factor limitante final en la cantidad de transacciones que se pueden procesar simultáneamente. Si bien varias
tecnologías de almacenamiento en caché y productos de escalado de bases de datos ayudan a abordar estos
problemas, el hecho es que escalar una aplicación normal para cargas extremas es una propuesta muy difícil.
211
Machine Translated by Google
Figura 151. Límites de escalabilidad dentro de una topología tradicional basada en la web
El estilo de arquitectura basado en el espacio está diseñado específicamente para abordar problemas que
involucran alta escalabilidad, elasticidad y alta concurrencia. También es un estilo de arquitectura útil para
aplicaciones que tienen volúmenes de usuarios concurrentes variables e impredecibles. Resolver el problema de
escalabilidad extrema y variable desde el punto de vista arquitectónico suele ser un mejor enfoque que intentar
escalar una base de datos o adaptar tecnologías de almacenamiento en caché a una arquitectura no escalable.
Topología general
La arquitectura basada en el espacio recibe su nombre del concepto de espacio de tuplas, la técnica de utilizar
múltiples procesadores paralelos que se comunican a través de una memoria compartida. Se logra una alta
escalabilidad, alta elasticidad y alto rendimiento eliminando la base de datos central como una restricción
sincrónica en el sistema y, en su lugar, aprovechando las cuadrículas de datos replicados en memoria. Los datos
de la aplicación se mantienen en la memoria y se replican entre todas las unidades de procesamiento activas.
Cuando una unidad de procesamiento actualiza los datos, los envía de forma asincrónica a la base de datos,
generalmente a través de mensajes con colas persistentes. Las unidades de procesamiento se inician y se apagan
dinámicamente a medida que aumenta y disminuye la carga de usuarios, abordando así la escalabilidad variable.
Debido a que no hay una base de datos central involucrada en el procesamiento transaccional estándar de la
aplicación, se elimina el cuello de botella de la base de datos, lo que proporciona una escalabilidad casi infinita
dentro de la aplicación.
Hay varios componentes de arquitectura que forman una arquitectura basada en el espacio: una unidad de
procesamiento que contiene el código de la aplicación, middleware virtualizado utilizado para administrar y coordinar
las unidades de procesamiento, bombas de datos para enviar de forma asincrónica datos actualizados a la base de
datos, escritores de datos que realizan las actualizaciones de las bombas de datos y lectores de datos que leen los
datos de la base de datos y los envían a las unidades de procesamiento al iniciarse.
La figura 152 ilustra estos componentes de arquitectura principales.
Unidad de procesamiento
La unidad de procesamiento (ilustrada en la Figura 153) contiene la lógica de la aplicación (o partes de la lógica de
la aplicación). Esto generalmente incluye componentes basados en la web, así como la lógica empresarial del
backend. El contenido de la unidad de procesamiento varía según el tipo de aplicación. Las aplicaciones basadas en
la web más pequeñas probablemente se implementarían en una sola unidad de procesamiento, mientras que las
aplicaciones más grandes pueden dividir la funcionalidad de la aplicación en múltiples unidades de procesamiento
según las áreas funcionales de la aplicación. La unidad de procesamiento también puede contener servicios pequeños
de un solo propósito (como con los microservicios). Además de la lógica de la aplicación, la unidad de procesamiento
también contiene una cuadrícula de datos en memoria y un motor de replicación generalmente implementados a
través de productos como Hazelcast, Encender Apache, y Oracle Coherence.
Middleware virtualizado
El middleware virtualizado se encarga de las cuestiones de infraestructura dentro de la arquitectura que controlan varios aspectos
de la sincronización de datos y el manejo de solicitudes. Los componentes que conforman el middleware virtualizado incluyen
una cuadrícula de mensajería, una cuadrícula de datos, una cuadrícula de procesamiento y un administrador de implementación.
Estos componentes, que se describen en detalle en las siguientes secciones, pueden ser personalizados o adquiridos como
productos de terceros.
Cuadrícula de
mensajería La cuadrícula de mensajería, que se muestra en la Figura 154, administra la solicitud de entrada y el estado de la sesión.
Cuando una solicitud llega al middleware virtualizado, el componente de la red de mensajería determina qué componentes de
procesamiento activos están disponibles para recibir la solicitud y la reenvía a una de esas unidades de procesamiento. La
complejidad de la red de mensajería puede variar desde un algoritmo simple de turno rotatorio hasta un algoritmo más complejo
de siguiente disponibilidad que realiza un seguimiento de qué solicitud está siendo procesada por qué unidad de procesamiento.
Este componente generalmente se implementa utilizando un servidor web típico con capacidades de equilibrio de carga (como
HA Proxy y Nginx).
Cuadrícula
de datos El componente de cuadrícula de datos es quizás el componente más importante y crucial en este estilo de
arquitectura. En la mayoría de las implementaciones modernas, la cuadrícula de datos se implementa únicamente
dentro de las unidades de procesamiento como una caché replicada. Sin embargo, para aquellas implementaciones
de almacenamiento en caché replicado que requieren un controlador externo, o cuando se utiliza una caché
distribuida, esta funcionalidad residiría tanto en las unidades de procesamiento como en el componente de cuadrícula
de datos dentro del middleware virtualizado. Dado que la cuadrícula de mensajería puede reenviar una solicitud a
cualquiera de las unidades de procesamiento disponibles, es esencial que cada unidad de procesamiento contenga
exactamente los mismos datos en su cuadrícula de datos en memoria.
Aunque la Figura 155 muestra una replicación de datos sincrónica entre unidades de procesamiento, en realidad
esto se realiza de forma asincrónica y muy rápida, normalmente completándose la sincronización de datos en menos
de 100 milisegundos.
Los datos se sincronizan entre unidades de procesamiento que contienen la misma cuadrícula de datos con nombre. Para
ilustrar este punto, considere el siguiente código en Java que utiliza Hazelcast y que crea una cuadrícula de datos replicada
interna para unidades de procesamiento que contienen información del perfil del cliente:
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
Mapa<Cadena, PerfilDeCliente> perfilCache =
hz.getReplicatedMap("Perfil del Cliente");
Todas las unidades de procesamiento que necesiten acceder a la información del perfil del cliente contendrán este código. Los
cambios realizados en la caché con nombre CustomerProfile desde cualquiera de las unidades de procesamiento se replicarán
en todas las demás unidades de procesamiento que contengan esa misma caché con nombre. Una unidad de procesamiento
puede contener tantas cachés replicadas como sean necesarias para completar su trabajo. Alternativamente, una unidad de
procesamiento puede realizar una llamada remota a otra unidad de procesamiento para solicitar datos (coreografía) o aprovechar
la red de procesamiento (descrita en la siguiente sección) para orquestar la solicitud.
La replicación de datos dentro de las unidades de procesamiento también permite que las instancias de
servicio se activen y desactiven sin tener que leer datos de la base de datos, siempre que haya al menos
una instancia que contenga la caché replicada con nombre. Cuando se activa una instancia de la unidad
de procesamiento, se conecta al proveedor de caché (como Hazelcast) y realiza una solicitud para
obtener la caché con nombre. Una vez que se realiza la conexión con las otras unidades de
procesamiento, la caché se cargará desde una de las otras instancias.
Cada unidad de procesamiento conoce todas las demás instancias de unidades de procesamiento
mediante el uso de una lista de miembros. La lista de miembros contiene la dirección IP y los puertos de
todas las demás unidades de procesamiento que utilizan esa misma caché con nombre. Por ejemplo,
supongamos que hay una única instancia de procesamiento que contiene código y datos replicados en
caché para el perfil del cliente. En este caso, solo hay una instancia, por lo que la lista de miembros para
esa instancia solo se contiene a sí misma, como se ilustra en las siguientes declaraciones de registro
generadas con Hazelcast:
Instancia 1:
Cuando otra unidad de procesamiento se inicia con el mismo caché con nombre, la lista de miembros de
ambos servicios se actualiza para reflejar la dirección IP y el puerto de cada unidad de procesamiento:
Instancia 1:
Instancia 2:
Instancia 1:
Instancia 2:
Instancia 3:
Miembros {size:3, ver:3}
[ Miembro [172.19.248.89]:5701 04a6f863dfce41e59d519f4e356ef268 Miembro
[172.19.248.90]:5702 ea9e4dd55cb34b278fe8db5cc62c7316 Miembro
[172.19.248.91]:5703 1623eadf9cfb4b839983d80520cef753 este
]
Tenga en cuenta que las tres instancias se conocen entre sí (incluso a sí mismas). Supongamos que la instancia 1 recibe
una solicitud para actualizar la información del perfil del cliente. Cuando la instancia 1 actualiza la memoria caché con un
método de actualización de caché cache.put() o similar, la cuadrícula de datos (como Hazelcast) actualizará de forma
asincrónica las otras memorias caché replicadas con la misma actualización, lo que garantiza que las tres memorias caché
del perfil del cliente siempre permanezcan sincronizadas entre sí.
Cuando las instancias de la unidad de procesamiento dejan de funcionar, todas las demás unidades de procesamiento se
actualizan automáticamente para reflejar el miembro perdido. Por ejemplo, si la instancia 2 deja de funcionar, las listas de
miembros de las instancias 1 y 3 se actualizan de la siguiente manera:
Instancia 1:
Miembros {size:2, ver:4}
[ Miembro [172.19.248.89]:5701 04a6f863dfce41e59d519f4e356ef268 este Miembro
[172.19.248.91]:5703 1623eadf9cfb4b839983d80520cef753
]
Instancia 3:
Miembros {size:2, ver:4} [ Miembro
[172.19.248.89]:5701 04a6f863dfce41e59d519f4e356ef268 Miembro [172.19.248.91]:5703
1623eadf9cfb4b839983d80520cef753 este
]
Cuadrícula de
procesamiento La cuadrícula de procesamiento, ilustrada en la Figura 156, es un componente opcional dentro del
middleware virtualizado que administra el procesamiento orquestado de solicitudes cuando hay múltiples unidades de
procesamiento involucradas en una sola solicitud comercial. Si llega una solicitud que requiere coordinación entre tipos de
unidades de procesamiento (por ejemplo, una unidad de procesamiento de pedidos y una unidad de procesamiento de
pagos), es la cuadrícula de procesamiento la que media y orquesta la solicitud entre esas dos unidades de procesamiento.
Administrador de
implementación El componente Administrador de implementación administra el inicio y el apagado dinámicos de las instancias de la
unidad de procesamiento en función de las condiciones de carga. Este componente monitorea continuamente los tiempos de respuesta
y las cargas de usuarios, inicia nuevas unidades de procesamiento cuando la carga aumenta y apaga las unidades de procesamiento
cuando la carga disminuye. Es un componente fundamental para lograr las necesidades de escalabilidad variable (elasticidad) dentro
de una aplicación.
bomba de datos es una forma de enviar datos a otro procesador que luego actualiza los datos en una base de datos. Las bombas de
datos son un componente necesario dentro de la arquitectura basada en el espacio, ya que las unidades de procesamiento no leen ni
escriben directamente en una base de datos. Las bombas de datos dentro de una arquitectura basada en el espacio siempre son
asincrónicas, lo que proporciona una consistencia eventual con la memoria caché en memoria y la base de datos. Cuando una
instancia de unidad de procesamiento recibe una solicitud y actualiza su caché, esa unidad de procesamiento se convierte en el
propietario de la actualización y, por lo tanto, es responsable de enviar esa actualización a través de la bomba de datos para que la
Los bombeos de datos se implementan generalmente mediante mensajería, como se muestra en la Figura 157. La
mensajería es una buena opción para los bombeos de datos cuando se utiliza una arquitectura basada en el espacio. La
mensajería no solo admite la comunicación asincrónica, sino que también admite la entrega garantizada y la preservación
del orden de los mensajes mediante colas FIFO (primero en entrar, primero en salir). Además, la mensajería proporciona
un desacoplamiento entre la unidad de procesamiento y el escritor de datos, de modo que si el escritor de datos no está
disponible, el procesamiento ininterrumpido aún puede tener lugar dentro de las unidades de procesamiento.
Figura 157. Bomba de datos utilizada para enviar datos a una base de datos
En la mayoría de los casos, existen múltiples bombas de datos, cada una de ellas dedicada a un dominio o subdominio
en particular (como cliente o inventario). Las bombas de datos pueden estar dedicadas a cada tipo de caché (como
CustomerProfile, CustomerWishlist, etc.) o pueden estar dedicadas a un dominio de unidad de procesamiento (como
Customer) que contenga una caché mucho más grande y general.
Las bombas de datos suelen tener contratos asociados, incluida una acción asociada con los datos del contrato (agregar,
eliminar o actualizar). El contrato puede ser un esquema JSON, un esquema XML, un objeto o incluso un mensaje
basado en valores (mensaje de mapa que contiene pares nombrevalor). En el caso de las actualizaciones, los datos
incluidos en el mensaje de la bomba de datos normalmente solo contienen los nuevos valores de datos. Por ejemplo, si
un cliente cambia un número de teléfono en su perfil, solo se enviará el nuevo número de teléfono, junto con el ID del
cliente y una acción para actualizar los datos.
Escritores de datos
El componente de escritura de datos acepta mensajes de una bomba de datos y actualiza la base de datos con
la información contenida en el mensaje de la bomba de datos (consulte la Figura 157). Los escritores de datos
se pueden implementar como servicios, aplicaciones o centros de datos (como Ab Initio). La granularidad de los
escritores de datos puede variar según el alcance de las bombas de datos y las unidades de procesamiento.
Un escritor de datos basado en dominio contiene toda la lógica de base de datos necesaria para manejar todas
las actualizaciones dentro de un dominio particular (como cliente), independientemente de la cantidad de bombas
de datos que acepte. Observe en la Figura 158 que hay cuatro unidades de procesamiento diferentes y cuatro
bombas de datos diferentes que representan el dominio del cliente (Perfil, Lista de deseos, Monedero y
Preferencias), pero solo un escritor de datos. El escritor de datos de cliente único escucha las cuatro bombas
de datos y contiene la lógica de base de datos necesaria (como SQL) para actualizar los datos relacionados con
el cliente en la base de datos.
Como alternativa, cada clase de unidad de procesamiento puede tener su propio componente de escritura de
datos dedicado, como se ilustra en la Figura 159. En este modelo, el escritor de datos está dedicado a cada
bomba de datos correspondiente y contiene solo la lógica de procesamiento de la base de datos para esa
unidad de procesamiento en particular (como Wallet). Si bien este modelo tiende a producir demasiados
componentes de escritura de datos, proporciona una mejor escalabilidad y agilidad debido a la alineación de la
unidad de procesamiento, la bomba de datos y el escritor de datos.
Lectores de datos
Mientras que los escritores de datos asumen la responsabilidad de actualizar la base de datos, los lectores de
datos asumen la responsabilidad de leer los datos de la base de datos y enviarlos a las unidades de
procesamiento a través de un bombeo de datos inverso. En la arquitectura basada en el espacio, los lectores
de datos solo se invocan en una de tres situaciones: una falla de todas las instancias de la unidad de
procesamiento de la misma caché con nombre, una redistribución de todas las unidades de procesamiento
dentro de la misma caché con nombre o la recuperación de datos de archivo que no están contenidos en la caché replicada.
En el caso de que todas las instancias se caigan (debido a un bloqueo de todo el sistema o una redistribución
de todas las instancias), los datos deben leerse de la base de datos (algo que generalmente se evita en la
arquitectura basada en el espacio). Cuando las instancias de una clase de unidad de procesamiento comienzan
a aparecer, cada una intenta obtener un bloqueo en la memoria caché. La primera en obtener el bloqueo se
convierte en el propietario temporal de la memoria caché; las demás entran en un estado de espera hasta que
se libera el bloqueo (esto puede variar según el tipo de implementación de memoria caché que se utilice, pero
independientemente de ello, hay un propietario principal de la memoria caché en este escenario). Para cargar la
memoria caché, la instancia que obtuvo el estado de propietario temporal de la memoria caché envía un mensaje
a una cola solicitando datos. El componente lector de datos acepta la solicitud de lectura y luego realiza la lógica
de consulta de base de datos necesaria para recuperar los datos que necesita la unidad de procesamiento. A
medida que el lector de datos consulta los datos de la base de datos, envía esos datos a una cola diferente
(llamada bomba de datos inversa). La unidad de procesamiento del propietario de la caché temporal recibe los
datos de la bomba de datos inversa y carga la caché. Una vez que se han cargado todos los datos, el propietario
temporal libera el bloqueo de la caché, se sincronizan todas las demás instancias y puede comenzar el
procesamiento. Este flujo de procesamiento se ilustra en la Figura 1510.
Al igual que los escritores de datos, los lectores de datos también pueden estar basados en dominios o dedicados
a una clase específica de unidad de procesamiento (que es lo que suele suceder). La implementación también
es la misma que la de los escritores de datos: servicio, aplicación o centro de datos.
Los escritores y lectores de datos forman esencialmente lo que se conoce habitualmente como una capa de
abstracción de datos (o capa de acceso a datos en algunos casos). La diferencia entre las dos está en la
cantidad de conocimiento detallado que tienen las unidades de procesamiento con respecto a la estructura de
las tablas (o esquema) en la base de datos. Una capa de acceso a datos significa que las unidades de
procesamiento están acopladas a las estructuras de datos subyacentes en la base de datos y
Solo se utilizan los lectores y escritores de datos para acceder indirectamente a la base de datos. Por otro lado, una capa
de abstracción de datos significa que la unidad de procesamiento está desacoplada de las estructuras de tabla de la base
de datos subyacente a través de contratos separados. La arquitectura basada en el espacio generalmente se basa en un
modelo de capa de abstracción de datos para que el esquema de caché replicado en cada unidad de procesamiento pueda
ser diferente de las estructuras de tabla de la base de datos subyacente. Esto permite cambios incrementales en la base
de datos sin afectar necesariamente a las unidades de procesamiento. Para facilitar este cambio incremental, los escritores
de datos y los lectores de datos contienen una lógica de transformación para que, si cambia un tipo de columna o se
elimina una columna o tabla, los lectores de datos y los escritores de datos puedan almacenar en búfer el cambio de la
base de datos hasta que se puedan realizar los cambios necesarios en las cachés de la unidad de procesamiento.
Colisiones de datos
Para ilustrar este problema, supongamos que hay dos instancias de servicio (Servicio A y Servicio B) que contienen una
caché replicada del inventario de productos. El siguiente flujo demuestra el problema de colisión de datos:
A actualiza el caché de inventario de widgets azules a 490 unidades (10 vendidas) • Durante la replicación, el
• La caché del Servicio B se actualiza a 490 unidades debido a la replicación del Servicio A
actualizar
• La caché del Servicio A recibe actualizaciones a 495 unidades debido a la replicación del Servicio B
actualizar
• Ambos cachés en el Servicio A y B son incorrectos y no están sincronizados (el inventario debería
ser 485 unidades)
Existen varios factores que influyen en la cantidad de colisiones de datos que pueden ocurrir: la cantidad de
instancias de la unidad de procesamiento que contienen la misma caché, la tasa de actualización de la
caché, el tamaño de la caché y, por último, la latencia de replicación del producto de almacenamiento en
caché. La fórmula utilizada para determinar de manera probabilística cuántas colisiones de datos potenciales
pueden ocurrir en función de estos factores es la siguiente:
UR2 *
Tasa de colisión = N * En realidad
donde N representa el número de instancias de servicio que utilizan el mismo caché con nombre, UR
representa la tasa de actualización en milisegundos (al cuadrado), S el tamaño de caché (en términos de
número de filas) y RL la latencia de replicación del producto de almacenamiento en caché.
Esta fórmula es útil para determinar el porcentaje de colisiones de datos que probablemente ocurrirán
se produzcan y, por lo tanto, la viabilidad del uso del almacenamiento en caché replicado. Por ejemplo, considere
los siguientes valores para los factores que intervienen en este cálculo:
Porcentaje: 0,02%
Aplicando estos factores a la fórmula se obtienen 72.000 actualizaciones por hora, con un valor alto
probabilidad de que 14 actualizaciones de los mismos datos puedan colisionar. Dado el bajo porcentaje
(0,02%), la replicación sería una opción viable.
Porcentaje: 0,0002%
El número de unidades de procesamiento que contienen la misma caché nombrada (como se representa
a través del factor número de instancias) también tiene una relación directamente proporcional a
el número de posibles colisiones de datos. Por ejemplo, reducir el número de procesos.
Al convertir unidades de 5 instancias en 2 instancias se obtiene una tasa de colisión de datos de solo 6 por hora.
de 72.000 actualizaciones por hora:
Porcentaje: 0,008%
Porcentaje: 0,1%
En circunstancias normales, la mayoría de los sistemas no tienen tasas de actualización consistentes a lo largo del tiempo.
un período de tiempo tan largo. Por lo tanto, al utilizar este cálculo es útil comprender
mantener la tasa de actualización máxima durante el uso pico y calcular el mínimo, normal,
y tasas máximas de colisión.
La arquitectura basada en el espacio ofrece algunas opciones únicas en lo que respecta al medio ambiente.
en los que se implementa. La topología completa, incluidas las unidades de procesamiento,
middleware virtualizado, bombas de datos, lectores y escritores de datos y la base de datos pueden
implementarse en entornos basados en la nube en las instalaciones (“onprem”). Sin embargo,
Este estilo de arquitectura también se puede implementar entre estos entornos, ofreciendo una
Característica única que no se encuentra en otros estilos de arquitectura.
Una característica poderosa de este estilo de arquitectura (como se ilustra en la Figura 1511) es la implementación de
aplicaciones a través de unidades de procesamiento y middleware virtualizado en entornos administrados basados en la
nube, mientras se mantienen las bases de datos físicas y los datos correspondientes en las instalaciones. Esta topología
admite una sincronización de datos basada en la nube muy efectiva debido a las bombas de datos asincrónicas y al modelo
de consistencia final de este estilo de arquitectura. El procesamiento transaccional puede ocurrir en entornos dinámicos y
elásticos basados en la nube, mientras se preserva la administración de datos físicos, los informes y el análisis de datos
dentro de entornos locales seguros y locales.
Con el almacenamiento en caché replicado, como se ilustra en la Figura 1512, cada unidad de procesamiento contiene su
propia cuadrícula de datos en memoria que se sincroniza entre todas las unidades de procesamiento que utilizan esa misma
caché con nombre. Cuando se produce una actualización en una caché dentro de cualquiera de los procesos,
Al procesar unidades, las demás unidades de procesamiento se actualizan automáticamente con la nueva información.
El almacenamiento en caché replicado no solo es extremadamente rápido, sino que también admite altos niveles de tolerancia a
fallas. Dado que no hay un servidor central que contenga el caché, el almacenamiento en caché replicado no tiene un único punto
de falla. Sin embargo, puede haber excepciones a esta regla, según la implementación del producto de almacenamiento en caché
utilizado. Algunos productos de almacenamiento en caché requieren la presencia de un controlador externo para supervisar y
controlar la replicación de datos entre unidades de procesamiento, pero la mayoría de las empresas de productos se están
Si bien el almacenamiento en caché replicado es el modelo de almacenamiento en caché estándar para la arquitectura basada
en el espacio, existen algunos casos en los que no es posible utilizar el almacenamiento en caché replicado. Estas situaciones
incluyen grandes volúmenes de datos (tamaño de la memoria caché) y altas tasas de actualización de los datos de la memoria
caché. Las memorias caché internas de más de 100 MB pueden comenzar a causar problemas con respecto a la elasticidad y la
alta escalabilidad debido a la cantidad de memoria utilizada por cada unidad de procesamiento. Las unidades de procesamiento
generalmente se implementan dentro de una máquina virtual (o en algunos casos representan la máquina virtual). Cada máquina
virtual solo tiene una cierta cantidad de memoria disponible para el uso de la memoria caché interna, lo que limita la cantidad de
instancias de la unidad de procesamiento que se pueden iniciar para procesar situaciones de alto rendimiento. Además, como se
muestra en “Colisiones de datos” en la página 224, si la tasa de actualización de los datos de la memoria caché es demasiado
alta, la cuadrícula de datos podría no poder mantener esa alta tasa de actualización para garantizar la coherencia de los datos en
todas las instancias de la unidad de procesamiento. Cuando ocurren estas situaciones, se puede utilizar el almacenamiento en
caché distribuido.
El almacenamiento en caché distribuido, como se ilustra en la Figura 1513, requiere un servidor externo o un servicio dedicado
a almacenar un caché centralizado. En este modelo, las unidades de procesamiento no almacenan datos en la memoria interna,
sino que utilizan un protocolo propietario para acceder a los datos desde el servidor de caché central. El almacenamiento en
consistencia porque los datos están todos en un solo lugar y no es necesario replicarlos.
Sin embargo, este modelo tiene un rendimiento menor que el almacenamiento en caché replicado porque se debe acceder a los
datos de la caché de forma remota, lo que aumenta la latencia general del sistema. La tolerancia a fallos también es un problema
con el almacenamiento en caché distribuido. Si el servidor de caché que contiene los datos deja de funcionar, no se puede
acceder a los datos ni actualizarlos desde ninguna de las unidades de procesamiento, lo que las deja fuera de servicio. La
tolerancia a fallos se puede mitigar duplicando la caché distribuida, pero esto podría presentar problemas de coherencia si el
servidor de caché principal deja de funcionar inesperadamente y los datos no llegan a la caché duplicada.
servidor.
Cuando el tamaño de la memoria caché es relativamente pequeño (menos de 100 MB) y la tasa de actualización de la memoria
caché es lo suficientemente baja como para que el motor de replicación del producto de almacenamiento en caché pueda seguir
el ritmo de las actualizaciones de la memoria caché, la decisión entre usar una memoria caché replicada y una distribuida se
convierte en una de consistencia de datos versus rendimiento y tolerancia a fallas. Una memoria caché distribuida siempre
ofrecerá una mejor consistencia de datos que una memoria caché replicada porque la memoria caché de datos está en un solo
lugar (en lugar de estar distribuida en múltiples unidades de procesamiento). Sin embargo, el rendimiento y la tolerancia a fallas
siempre serán mejores cuando se usa una memoria caché replicada. Muchas veces, esta decisión se reduce al tipo de datos
que se almacenan en caché en las unidades de procesamiento. La necesidad de datos altamente consistentes (como recuentos
de inventario de los productos disponibles) generalmente justifica una memoria caché distribuida, mientras que los datos que no
cambian a menudo (como datos de referencia como pares de nombre/valor, códigos de producto y descripciones de producto)
generalmente justifican una memoria caché replicada para una búsqueda rápida. Algunos de los criterios de selección que
pueden utilizarse como guía para elegir cuándo utilizar un caché distribuido frente a un caché replicado se enumeran en la Tabla
151.
Al elegir el tipo de modelo de almacenamiento en caché que se utilizará con la arquitectura basada en el espacio,
Recuerde que en la mayoría de los casos ambos modelos serán aplicables dentro de cualquier aplicación determinada.
contexto de la tarea. En otras palabras, ni el almacenamiento en caché replicado ni el almacenamiento en caché distribuido resuelven el problema.
cada problema. En lugar de intentar buscar compromisos a través de una única solución coherente
modelo de almacenamiento en caché en toda la aplicación, aproveche cada uno por sus puntos fuertes. Por ejemplo, para
una unidad de procesamiento que mantiene el inventario actual, elija un almacenamiento en caché distribuido
modelo de consistencia de datos; para una unidad de procesamiento que mantiene el perfil del cliente,
Elija un caché replicado para mejorar el rendimiento y la tolerancia a fallas.
Un caché cercano es un tipo de modelo híbrido de almacenamiento en caché que conecta las cuadrículas de datos en memoria con una
un caché usado más recientemente (MRU) que contiene los elementos usados más recientemente o un caché usado más recientemente (MRU)
caché de uso frecuente (MFU) que contiene los elementos utilizados con más frecuencia. Alterna
Alternativamente, se puede utilizar una política de desalojo de reemplazo aleatorio en el caché frontal para que
Los elementos se eliminan de forma aleatoria cuando se necesita espacio para agregar un nuevo elemento.
El reemplazo aleatorio (RR) es una buena política de desalojo cuando no hay un análisis claro de
los datos con respecto a mantener lo último usado versus lo usado con más frecuencia.
Si bien las cachés frontales siempre se mantienen sincronizadas con la caché de respaldo completa, las
cachés frontales contenidas dentro de cada unidad de procesamiento no están sincronizadas entre otras
unidades de procesamiento que comparten los mismos datos. Esto significa que es probable que varias
unidades de procesamiento que comparten el mismo contexto de datos (como un perfil de cliente) tengan
datos diferentes en su caché frontal. Esto crea inconsistencias en el rendimiento y la capacidad de respuesta
entre las unidades de procesamiento porque cada unidad de procesamiento contiene datos diferentes en la
caché frontal. Por este motivo, no recomendamos utilizar un modelo de caché cercana para la arquitectura
basada en el espacio.
Ejemplos de implementación
La arquitectura basada en el espacio es ideal para aplicaciones que experimentan picos altos en el volumen
de usuarios o solicitudes y aplicaciones que tienen un rendimiento superior a 10 000 usuarios simultáneos.
Algunos ejemplos de arquitectura basada en el espacio incluyen aplicaciones como sistemas de venta de
entradas para conciertos en línea y sistemas de subastas en línea. Ambos ejemplos requieren un alto
rendimiento, una alta escalabilidad y altos niveles de elasticidad.
conciertos Los sistemas de venta de entradas para conciertos tienen un problema único en el sentido de que
el volumen de usuarios simultáneos es relativamente bajo hasta que se anuncia un concierto popular. Una
vez que las entradas para el concierto salen a la venta, el volumen de usuarios suele aumentar de varios
cientos de usuarios simultáneos a varios miles (posiblemente decenas de miles, según el concierto), todos
intentando adquirir una entrada para el concierto (¡con suerte, buenos asientos!). Las entradas suelen
agotarse en cuestión de minutos, lo que requiere el tipo de características arquitectónicas que admite la
arquitectura basada en el espacio.
Este tipo de sistema presenta muchos desafíos. En primer lugar, solo hay una cierta cantidad de boletos
disponibles, independientemente de las preferencias de asientos. La disponibilidad de asientos debe
actualizarse continuamente y ponerse a disposición lo más rápido posible dada la gran cantidad de
solicitudes simultáneas. Además, suponiendo que los asientos asignados sean una opción, la
disponibilidad de asientos también debe actualizarse lo más rápido posible. El acceso continuo a una
base de datos central de forma sincrónica para este tipo de sistema probablemente no funcione; sería
muy difícil para una base de datos típica manejar decenas de miles de solicitudes simultáneas a través
de transacciones de base de datos estándar a este nivel de escala y frecuencia de actualización.
La arquitectura basada en el espacio sería una buena opción para un sistema de venta de entradas
para conciertos debido a los altos requisitos de elasticidad que requiere este tipo de aplicación. Un
aumento instantáneo en la cantidad de usuarios simultáneos que desean comprar entradas para
conciertos sería reconocido inmediatamente por el administrador de implementación, que a su vez
pondría en marcha una gran cantidad de unidades de procesamiento para manejar el gran volumen de solicitudes.
Lo óptimo sería configurar el administrador de implementación para iniciar la cantidad necesaria de
unidades de procesamiento poco antes de que salgan a la venta los tickets, y así tener esas instancias
en espera justo antes del aumento significativo en la carga de usuarios.
Los sistemas de subastas en línea (pujas por artículos dentro de una subasta) comparten el mismo tipo
de características que los sistemas de venta de entradas para conciertos en línea descritos
anteriormente: ambos requieren altos niveles de rendimiento y elasticidad, y ambos tienen picos
impredecibles en la carga de usuarios y solicitudes. Cuando comienza una subasta, no hay forma de
determinar cuántas personas se unirán a la subasta y, de esas personas, cuántas ofertas simultáneas
se producirán por cada precio solicitado.
La arquitectura basada en el espacio es adecuada para este tipo de dominio de problemas, ya que se
pueden iniciar múltiples unidades de procesamiento a medida que aumenta la carga; y a medida que la
subasta finaliza, las unidades de procesamiento no utilizadas podrían destruirse. Se pueden dedicar
unidades de procesamiento individuales a cada subasta, lo que garantiza la coherencia con los datos
de licitación. Además, debido a la naturaleza asincrónica de los envíos de datos, los datos de licitación
se pueden enviar a otro procesamiento (como historial de ofertas, análisis de ofertas y auditoría) sin
mucha latencia, lo que aumenta el rendimiento general del proceso de licitación.
la característica de arquitectura es una de las características más sólidas del estilo de arquitectura. La definición de cada
característica identificada en el cuadro de mando se puede encontrar en el Capítulo 4.
Tenga en cuenta que la arquitectura basada en el espacio maximiza la elasticidad, la escalabilidad y el rendimiento (todas las
calificaciones de cinco estrellas). Estos son los atributos impulsores y las principales ventajas de este estilo de arquitectura. Se
logran altos niveles de estas tres características de arquitectura aprovechando el almacenamiento en caché de datos en
memoria y eliminando la base de datos como restricción. Como resultado, es posible procesar millones de usuarios simultáneos
utilizando este estilo de arquitectura.
Si bien los altos niveles de elasticidad, escalabilidad y rendimiento son ventajas en este estilo de arquitectura,
existe una contrapartida para esta ventaja, específicamente con respecto a la simplicidad general y la capacidad
de prueba. La arquitectura basada en el espacio es un estilo de arquitectura muy complicado debido al uso de
almacenamiento en caché y la consistencia final del almacén de datos primario, que es el sistema de registro
definitivo. Se debe tener cuidado para garantizar que no se pierdan datos en caso de una falla en cualquiera de
las numerosas partes móviles de este estilo de arquitectura (consulte “Prevención de pérdida de datos” en la
página 201 en el Capítulo 14).
Las pruebas obtienen una calificación de una estrella debido a la complejidad que implica simular los altos niveles
de escalabilidad y elasticidad que admite este estilo de arquitectura. Probar cientos de miles de usuarios
simultáneos en condiciones de carga máxima es una tarea muy complicada y costosa y, como resultado, la
mayoría de las pruebas de gran volumen se realizan en entornos de producción con una carga extrema real.
Esto produce un riesgo significativo para las operaciones normales dentro de un entorno de producción.
El costo es otro factor a tener en cuenta a la hora de elegir este estilo de arquitectura. La arquitectura basada en
el espacio es relativamente cara, principalmente debido a las tarifas de licencias para productos de
almacenamiento en caché y al alto uso de recursos dentro de los sistemas locales y en la nube debido a la alta
escalabilidad y elasticidad.
Es difícil identificar el tipo de particionamiento de la arquitectura basada en el espacio, y como resultado la hemos
identificado como particionada tanto por dominio como técnicamente. La arquitectura basada en el espacio está
particionada por dominio no solo porque se alinea con un tipo específico de dominio (sistemas altamente elásticos
y escalables), sino también por la flexibilidad de las unidades de procesamiento. Las unidades de procesamiento
pueden actuar como servicios de dominio de la misma manera que los servicios se definen en una arquitectura
basada en servicios o una arquitectura de microservicios. Al mismo tiempo, la arquitectura basada en el espacio
está particionada técnicamente en la forma en que separa las preocupaciones sobre el procesamiento
transaccional mediante almacenamiento en caché del almacenamiento real de los datos en la base de datos a
través de bombas de datos. Las unidades de procesamiento, las bombas de datos, los lectores y escritores de
datos y la base de datos forman una estratificación técnica en términos de cómo se procesan las solicitudes,
muy similar con respecto a cómo se estructura una arquitectura monolítica en capas de n niveles.
La cantidad de cuantos dentro de una arquitectura basada en el espacio puede variar según cómo esté diseñada
la interfaz de usuario y cómo se produce la comunicación entre las unidades de procesamiento. Debido a que las
unidades de procesamiento no se comunican sincrónicamente con la base de datos, la base de datos en sí no
forma parte de la ecuación cuántica. Como resultado, los cuantos dentro de una arquitectura basada en el
espacio se delinean típicamente a través de la asociación entre las diversas interfaces de usuario y las unidades
de procesamiento. Las unidades de procesamiento que se comunican sincrónicamente entre sí (o sincrónicamente
a través de la red de procesamiento para la orquestación) serían todas parte del mismo cuanto arquitectónico.
CAPÍTULO 16
Los estilos arquitectónicos, al igual que los movimientos artísticos, deben entenderse en el contexto de la
época en la que evolucionaron, y esta arquitectura ejemplifica esta regla más que ninguna otra. La combinación
de fuerzas externas que a menudo influyen en las decisiones arquitectónicas, combinadas con una filosofía
organizacional lógica pero en última instancia desastrosa, condenaron a esta arquitectura a la irrelevancia. Sin
embargo, proporciona un gran ejemplo de cómo una idea organizacional particular puede tener sentido lógico
pero obstaculizar las partes más importantes del proceso de desarrollo.
Historia y Filosofía
Este estilo de arquitectura orientada a servicios apareció justo cuando las empresas se estaban convirtiendo
en grandes empresas a finales de los años 1990: se fusionaban con empresas más pequeñas, crecían a un
ritmo vertiginoso y requerían TI más sofisticadas para adaptarse a este crecimiento. Sin embargo, los recursos
informáticos eran escasos, valiosos y comerciales. La informática distribuida acababa de volverse posible y
necesaria, y muchas empresas necesitaban la escalabilidad variable y otras características beneficiosas.
Muchos factores externos obligaron a los arquitectos de esta era a adoptar arquitecturas distribuidas con
importantes limitaciones. Antes de que se pensara que los sistemas operativos de código abierto eran lo
suficientemente fiables para realizar trabajos serios, los sistemas operativos eran caros y se licenciaban por
máquina. De manera similar, los servidores de bases de datos comerciales venían con esquemas de licencias
bizantinos, lo que hizo que los proveedores de servidores de aplicaciones (que ofrecían agrupación de
conexiones de bases de datos) compitieran con los proveedores de bases de datos. Por lo tanto, se esperaba
que los arquitectos reutilizaran tanto como fuera posible. De hecho, la reutilización en todas sus formas se
convirtió en la filosofía dominante en esta arquitectura, cuyos efectos secundarios cubrimos en “Reutilización…
y acoplamiento” en la página 239.
235
Machine Translated by Google
Este estilo de arquitectura también ejemplifica hasta qué punto los arquitectos pueden llevar la idea de
la división técnica, que tuvo buenas motivaciones pero malas consecuencias.
Topología
La topología de este tipo de arquitectura orientada a servicios se muestra en la Figura 161.
No todos los ejemplos de este estilo de arquitectura tenían las capas exactas ilustradas en la Figura
161, pero todos seguían la misma idea de establecer una taxonomía de servicios dentro de la
arquitectura, cada capa con una responsabilidad específica.
Taxonomía
La filosofía que guiaba al arquitecto en esta arquitectura se centraba en la reutilización a nivel
empresarial. Muchas grandes empresas estaban molestas por la cantidad de veces que tenían que
reescribir el software y se les ocurrió una estrategia para resolver ese problema gradualmente.
Cada capa de la taxonomía apoyó este objetivo.
Servicios empresariales
Los servicios empresariales se encuentran en la parte superior de esta arquitectura y proporcionan el punto de
entrada. Por ejemplo, servicios como ExecuteTrade o PlaceOrder representan el comportamiento del dominio.
Una prueba de fuego común en ese momento era si un arquitecto podía responder afirmativamente a la
pregunta "¿Estamos en el negocio de…?" para cada uno de estos servicios.
Estas definiciones de servicio no contenían código, solo información de entrada, salida y, a veces, de esquema.
Por lo general, las definían los usuarios empresariales, de ahí el nombre de servicios empresariales.
Esta separación de responsabilidades surge del objetivo de reutilización de esta arquitectura. Si los
desarrolladores pueden crear servicios empresariales detallados con el nivel de granularidad adecuado, la
empresa no tendrá que volver a escribir esa parte del flujo de trabajo empresarial.
Poco a poco, la empresa creará una colección de activos reutilizables en forma de servicios empresariales
reutilizables.
Lamentablemente, la naturaleza dinámica de la realidad desafía estos intentos. Los componentes empresariales
no son como los materiales de construcción, cuyas soluciones duran décadas. Los mercados, los cambios
tecnológicos, las prácticas de ingeniería y una serie de otros factores frustran los intentos de imponer estabilidad
en el mundo del software.
Servicios de aplicación No
todos los servicios de la arquitectura requieren el mismo nivel de granularidad o reutilización que
los servicios empresariales. Los servicios de aplicación son servicios únicos y de implementación única.
Por ejemplo, tal vez una aplicación necesite geolocalización, pero la organización no quiere dedicar tiempo ni
esfuerzo a convertir ese servicio en algo reutilizable. Un servicio de aplicaciones, normalmente propiedad de
un solo equipo de aplicaciones, resuelve estos problemas.
Servicios de Infraestructura
Los servicios de infraestructura se encargan de las cuestiones operativas, como la supervisión, el registro, la
autenticación y la autorización. Estos servicios suelen ser implementaciones concretas, propiedad de un equipo
de infraestructura compartida que trabaja en estrecha colaboración con el departamento de operaciones.
Taxonomía | 237
Machine Translated by Google
Motor de orquestación El
El motor de orquestación define la relación entre los servicios empresariales y comerciales, cómo se
relacionan entre sí y dónde se encuentran los límites de las transacciones. También actúa como un
centro de integración, lo que permite a los arquitectos integrar código personalizado con sistemas de
software heredados y en paquetes.
Debido a que este mecanismo forma el corazón de la arquitectura, la ley de Conway (ver “Ley de
Conway” en la página 103) predice correctamente que el equipo de arquitectos de integración
responsables de este motor se convierte en una fuerza política dentro de una organización y,
eventualmente, en un cuello de botella burocrático.
Si bien este enfoque puede parecer atractivo, en la práctica resultó ser un desastre. Transferir el
comportamiento de las transacciones a una herramienta de orquestación parecía una buena idea,
pero encontrar el nivel correcto de granularidad de las transacciones se volvió cada vez más difícil.
Si bien es posible crear algunos servicios envueltos en una transacción distribuida, la arquitectura se
vuelve cada vez más compleja a medida que los desarrolladores deben determinar dónde se
encuentran los límites de transacción adecuados entre los servicios.
Flujo de mensajes
Todas las solicitudes pasan por el motor de orquestación, que es el lugar dentro de esta arquitectura
donde reside la lógica. Por lo tanto, el flujo de mensajes pasa por el motor incluso para las llamadas
internas, como se muestra en la Figura 162.
En la Figura 162, el servicio de nivel empresarial CreateQuote llama al bus de servicio, que define el flujo de
trabajo que consta de llamadas a CreateCustomer y CalculateQuote, cada una de las cuales también tiene
llamadas a servicios de aplicación. El bus de servicio actúa como intermediario para todas las llamadas dentro de
esta arquitectura, sirviendo como centro de integración y motor de orquestación.
Reutilización…y acoplamiento
Un objetivo principal de esta arquitectura es la reutilización a nivel de servicio: la capacidad de crear gradualmente
un comportamiento empresarial que pueda reutilizarse de forma incremental con el tiempo. Los arquitectos de
esta arquitectura recibieron instrucciones de buscar oportunidades de reutilización de la forma más agresiva posible.
Por ejemplo, consideremos la situación ilustrada en la Figura 163.
En la Figura 163, un arquitecto se da cuenta de que cada una de estas divisiones dentro de una compañía de seguros
contiene una noción de Cliente. Por lo tanto, la estrategia adecuada para la arquitectura orientada a servicios implica
extraer las partes del cliente en un servicio reutilizable y permitir que los servicios originales hagan referencia al
servicio al Cliente canónico , que se muestra en la Figura 164.
En la Figura 164, el arquitecto ha aislado todo el comportamiento del cliente en un único servicio al cliente ,
logrando objetivos de reutilización obvios.
Sin embargo, los arquitectos sólo se dieron cuenta lentamente de las desventajas de este diseño. En primer
lugar, cuando un equipo construye un sistema principalmente en torno a la reutilización, también incurre en
una gran cantidad de acoplamiento entre componentes. Por ejemplo, en la Figura 164, un cambio en el
servicio de atención al cliente se propaga a todos los demás servicios, lo que hace que el cambio sea
riesgoso. Por lo tanto, en la arquitectura orientada a servicios, los arquitectos lucharon para hacer cambios
incrementales: cada cambio tenía un potencial efecto dominó enorme. Eso, a su vez, condujo a la necesidad
de implementaciones coordinadas, pruebas holísticas y otros obstáculos para la eficiencia de la ingeniería.
Otro efecto secundario negativo de la consolidación de la conducta en un único lugar: considere el caso del
seguro de automóvil y de discapacidad en la Figura 164. Para respaldar un servicio de atención al cliente
único , debe incluir todos los detalles que la organización conoce sobre los clientes. El seguro de automóvil
requiere una licencia de conducir, que es propiedad de la persona, no del vehículo. Por lo tanto, el servicio
de atención al cliente tendrá que incluir detalles sobre las licencias de conducir que no le interesan a la
división de seguros de discapacidad. Sin embargo, el equipo que se ocupa de la discapacidad debe lidiar
con la complejidad adicional de una única definición de cliente.
Tal vez la revelación más perjudicial de esta arquitectura llegó con la comprensión de lo poco práctico que
era construir una arquitectura tan centrada en la partición técnica. Si bien tiene sentido desde el punto de
vista de la filosofía de separación y reutilización, era una pesadilla práctica. Los conceptos de dominio como
CatalogCheckout estaban tan dispersos en esta arquitectura que prácticamente se habían reducido a polvo.
Los desarrolladores suelen trabajar en tareas como "agregar una nueva línea de dirección a
CatalogCheckout". En una arquitectura orientada a servicios, eso podría implicar docenas de servicios en
varios niveles diferentes, además de cambios en un único esquema de base de datos. Y, si los servicios
empresariales actuales no están definidos con la granularidad transaccional correcta, los desarrolladores
tendrán que cambiar su diseño o construir un nuevo servicio casi idéntico para cambiar el comportamiento
transaccional. Hasta ahí llegó la reutilización.
Una calificación de una estrella en la tabla de calificación de características de la Figura 165 significa que
la característica de arquitectura específica no está bien respaldada en la arquitectura, mientras que una
calificación de cinco estrellas significa que la característica de arquitectura es una de las características más
sólidas del estilo de arquitectura. La definición de cada característica identificada en el cuadro de puntuación
se puede encontrar en el Capítulo 4.
La arquitectura orientada a servicios es quizás la arquitectura de propósito general más particionada técnicamente
que se haya intentado jamás. De hecho, la reacción contra las desventajas de esta estructura condujo a
arquitecturas más modernas como los microservicios. Tiene un único quantum a pesar de ser una arquitectura
distribuida por dos razones. En primer lugar, generalmente utiliza una única base de datos o solo unas pocas
bases de datos, lo que crea puntos de acoplamiento dentro de la arquitectura en muchas preocupaciones
diferentes. En segundo lugar, y más importante, el motor de orquestación actúa como un punto de acoplamiento
gigante: ninguna parte de la arquitectura puede tener características de arquitectura diferentes a las del mediador
que orquesta todo el comportamiento. Por lo tanto, esta arquitectura logra encontrar las desventajas tanto de las
Los objetivos de ingeniería modernos, como la capacidad de implementación y la capacidad de prueba, obtienen
resultados desastrosos en esta arquitectura, tanto porque recibieron poco apoyo como porque no eran objetivos
importantes (o incluso aspiracionales) durante esa época.
Esta arquitectura sí admitía algunos objetivos, como elasticidad y escalabilidad, a pesar de las
dificultades para implementar esos comportamientos, porque los proveedores de herramientas
dedicaron un enorme esfuerzo a hacer que estos sistemas fueran escalables mediante la creación de
replicación de sesiones en servidores de aplicaciones y otras técnicas. Sin embargo, al ser una
arquitectura distribuida, el rendimiento nunca fue un punto destacado de este estilo de arquitectura y
era extremadamente deficiente porque cada solicitud empresarial se dividía en gran parte de la arquitectura.
Debido a todos estos factores, la simplicidad y el costo tienen la relación inversa que la mayoría de
los arquitectos preferirían. Esta arquitectura fue un hito importante porque enseñó a los arquitectos lo
difíciles que pueden ser las transacciones distribuidas en el mundo real y los límites prácticos de la
partición técnica.
CAPÍTULO 17
Arquitectura de microservicios
Los microservicios son un estilo arquitectónico muy popular que ha ganado un impulso
significativo en los últimos años. En este capítulo, ofrecemos una descripción general de las
características importantes que distinguen a esta arquitectura, tanto topológica como filosóficamente.
Historia
La mayoría de los estilos arquitectónicos reciben su nombre de arquitectos que se dan cuenta
de que un patrón particular reaparece una y otra vez; no existe un grupo secreto de arquitectos
que decida cuál será el próximo gran movimiento. Más bien, resulta que muchos arquitectos
terminan tomando decisiones comunes a medida que el ecosistema de desarrollo de software
cambia y se transforma. Las mejores formas comunes de abordar y aprovechar esos cambios
se convierten en estilos arquitectónicos que otros emulan.
Los microservicios difieren en este sentido: su nombre se le dio bastante temprano en su uso y
se popularizó gracias a una famosa entrada de blog de Martin Fowler y James Lewis titulada
“Microservicios ”. Publicado en marzo de 2014. Reconocieron muchas características comunes
en este estilo arquitectónico relativamente nuevo y las describieron. Su publicación en el blog
ayudó a definir la arquitectura para los arquitectos curiosos y los ayudó a comprender la filosofía
subyacente.
Los microservicios están fuertemente inspirados en las ideas del diseño impulsado por el
dominio (DDD), un proceso de diseño lógico para proyectos de software. Un concepto en
particular del DDD, el contexto delimitado, inspiró decididamente los microservicios. El concepto
de contexto delimitado representa un estilo de desacoplamiento. Cuando un desarrollador define
un dominio, ese dominio incluye muchas entidades y comportamientos, identificados en
artefactos como código y esquemas de base de datos. Por ejemplo, una aplicación podría tener
un dominio llamado CatalogCheckout, que incluye nociones como elementos del catálogo,
clientes y pago. En una arquitectura monolítica tradicional, los desarrolladores compartirían muchos de estos conce
245
Machine Translated by Google
Creación de clases reutilizables y bases de datos vinculadas. Dentro de un contexto delimitado, las
partes internas, como el código y los esquemas de datos, se acoplan entre sí para producir trabajo;
pero nunca se acoplan a nada que esté fuera del contexto delimitado, como una base de datos o una
definición de clase de otro contexto delimitado. Esto permite que cada contexto defina solo lo que
necesita en lugar de acomodar otros componentes.
Si bien la reutilización es beneficiosa, recuerde la Primera Ley de la Arquitectura de Software en relación con
las compensaciones. La desventaja de la reutilización es el acoplamiento. Cuando un arquitecto diseña un
sistema que favorece la reutilización, también favorece el acoplamiento para lograr esa reutilización, ya sea
por herencia o por composición.
Sin embargo, si el objetivo del arquitecto requiere un alto grado de desacoplamiento, entonces favorece la
duplicación en lugar de la reutilización. El objetivo principal de los microservicios es un alto grado de
desacoplamiento, modelando físicamente la noción lógica de contexto delimitado.
Topología
La topología de los microservicios se muestra en la Figura 171.
Como se ilustra en la Figura 171, debido a su naturaleza de propósito único, el tamaño del servicio en
microservicios es mucho más pequeño que otras arquitecturas distribuidas, como
Arquitectura orientada a servicios basada en orquestación. Los arquitectos esperan que cada servicio
incluya todas las partes necesarias para funcionar de forma independiente, incluidas las bases de datos
y otros componentes dependientes. Las diferentes características aparecen en las siguientes secciones.
Repartido
Los microservicios forman una arquitectura distribuida: cada servicio se ejecuta en su propio proceso,
lo que originalmente implicaba una computadora física, pero evolucionó rápidamente a máquinas
virtuales y contenedores. Desacoplar los servicios hasta este punto permite una solución simple a un
problema común en arquitecturas que cuentan con una infraestructura multiusuario para alojar
aplicaciones. Por ejemplo, cuando se utiliza un servidor de aplicaciones para administrar múltiples
aplicaciones en ejecución, permite la reutilización operativa del ancho de banda de red, la memoria, el
espacio en disco y una serie de otros beneficios. Sin embargo, si todas las aplicaciones admitidas
continúan creciendo, eventualmente algunos recursos se vuelven limitados en la infraestructura
compartida. Otro problema se relaciona con el aislamiento inadecuado entre aplicaciones compartidas.
Separar cada servicio en su propio proceso resuelve todos los problemas que genera el uso compartido.
Antes del desarrollo evolutivo de los sistemas operativos de código abierto de libre acceso, combinados
con el aprovisionamiento automático de máquinas, no era práctico que cada dominio tuviera su propia
infraestructura. Sin embargo, ahora, con los recursos en la nube y la tecnología de contenedores, los
equipos pueden aprovechar los beneficios de una disociación extrema, tanto a nivel de dominio como
operativo.
Debido a que los microservicios son una arquitectura distribuida, los arquitectos experimentados
desaconsejan el uso de transacciones a través de los límites de los servicios, lo que hace que determinar
la granularidad de los servicios sea la clave del éxito en esta arquitectura.
Contexto delimitado
La filosofía que guía a los microservicios es la noción de contexto limitado: cada servicio modela un
dominio o flujo de trabajo. Por lo tanto, cada servicio incluye todo lo necesario para operar dentro de la
aplicación, incluidas las clases, otros subcomponentes y los esquemas de bases de datos. Esta filosofía
impulsa muchas de las decisiones que toman los arquitectos dentro de esta arquitectura. Por ejemplo,
en un monolito, es común que los desarrolladores compartan clases comunes, como Address, entre
partes dispares de la aplicación. Sin embargo, los microservicios intentan evitar el acoplamiento y, por
lo tanto, un arquitecto que crea este estilo de arquitectura prefiere la duplicación al acoplamiento.
Distribuido | 247
Machine Translated by Google
Los microservicios llevan el concepto de una arquitectura particionada por dominio al extremo.
Cada servicio está destinado a representar un dominio o subdominio; en muchos sentidos, los microservicios
son la encarnación física de los conceptos lógicos en el diseño impulsado por el dominio.
Los arquitectos
de granularidad luchan por encontrar la granularidad correcta para los servicios en microservicios y, a
menudo, cometen el error de hacer que sus servicios sean demasiado pequeños, lo que requiere que creen
vínculos de comunicación entre los servicios para realizar un trabajo útil.
En otras palabras, los creadores del término necesitaban llamar de alguna manera a este nuevo estilo y
eligieron “microservicios” para contrastarlo con el estilo arquitectónico dominante en ese momento, la
arquitectura orientada a servicios, que podría haberse llamado “servicios gigantescos”. Sin embargo,
muchos desarrolladores toman el término “microservicios” como un mandamiento, no como una descripción,
y crean servicios que son demasiado detallados.
El objetivo de los límites de servicio en los microservicios es capturar un dominio o flujo de trabajo. En
algunas aplicaciones, esos límites naturales pueden ser grandes para algunas partes del sistema (algunos
procesos de negocio están más acoplados que otros). A continuación, se presentan algunas pautas que
los arquitectos pueden utilizar para ayudar a encontrar los límites adecuados:
Propósito
El límite más obvio se basa en la inspiración para el estilo de arquitectura, un dominio. Idealmente,
cada microservicio debería ser extremadamente cohesivo funcionalmente y contribuir con un
comportamiento significativo en nombre de la aplicación general.
Actas
Los contextos delimitados son flujos de trabajo empresariales y, a menudo, las entidades que
necesitan cooperar en una transacción muestran a los arquitectos un buen límite de servicio. Debido
a que las transacciones causan problemas en las arquitecturas distribuidas, si los arquitectos pueden
diseñar su sistema para evitarlos, generan mejores diseños.
Coreografía Si
un arquitecto crea un conjunto de servicios que ofrecen un excelente aislamiento de dominio pero
requieren una comunicación extensa para funcionar, el arquitecto puede considerar agrupar estos
servicios en un servicio más grande para evitar la sobrecarga de comunicación.
La iteración es la única forma de garantizar un buen diseño de servicios. Los arquitectos rara vez descubren
la granularidad, las dependencias de datos y los estilos de comunicación perfectos en su primera pasada.
Sin embargo, después de iterar sobre las opciones, un arquitecto tiene una buena posibilidad de refinar su
diseño.
Aislamiento de datos
Otro requisito de los microservicios, impulsado por el concepto de contexto limitado, es el aislamiento de los
datos. Muchos otros estilos de arquitectura utilizan una única base de datos para la persistencia.
Sin embargo, los microservicios intentan evitar todo tipo de acoplamiento, incluidos esquemas compartidos y
bases de datos utilizadas como puntos de integración.
El aislamiento de datos es otro factor que un arquitecto debe tener en cuenta al analizar la granularidad de los
servicios. Los arquitectos deben tener cuidado con la trampa de entidades (que se analiza en “Trampa de
entidades” en la página 110) y no modelar simplemente sus servicios para que se asemejen a entidades individuales
en una base de datos.
Los arquitectos están acostumbrados a utilizar bases de datos relacionales para unificar valores dentro
de un sistema, creando una única fuente de información, lo que ya no es una opción cuando se distribuyen
datos en toda la arquitectura. Por lo tanto, los arquitectos deben decidir cómo quieren manejar este
problema: ya sea identificando un dominio como la fuente de información para algún hecho y
coordinándose con él para recuperar valores o utilizando la replicación de bases de datos o el
almacenamiento en caché para distribuir información.
Si bien este nivel de aislamiento de datos genera dolores de cabeza, también brinda oportunidades.
Ahora que los equipos no están obligados a unificarse en torno a una única base de datos, cada servicio puede
elegir la herramienta más adecuada en función del precio, el tipo de almacenamiento o una serie de otros
factores. En un sistema altamente desacoplado, los equipos tienen la ventaja de cambiar de opinión y elegir
una base de datos más adecuada (u otra dependencia) sin afectar a otros equipos, a los que no se les permite
acoplarse a los detalles de implementación.
Capa API
La mayoría de las imágenes de microservicios incluyen una capa de API ubicada entre los consumidores del
sistema (ya sean interfaces de usuario o llamadas de otros sistemas), pero es opcional. Es común porque
ofrece una buena ubicación dentro de la arquitectura para realizar tareas útiles, ya sea a través de la indirección
como proxy o un vínculo con instalaciones operativas, como un servicio de nombres (que se trata en
“Reutilización operativa” en la página 250).
Si bien una capa de API puede utilizarse para diversas cosas, no debería utilizarse como mediador o
herramienta de orquestación si el arquitecto quiere mantenerse fiel a la filosofía subyacente de esta arquitectura:
toda la lógica interesante en esta arquitectura debería ocurrir dentro de un contexto delimitado, y poner la
orquestación u otra lógica en un mediador viola esa regla. Esto también ilustra la diferencia entre la partición
técnica y de dominio en la arquitectura: los arquitectos suelen utilizar mediadores en arquitecturas particionadas
técnicamente, mientras que los microservicios están firmemente particionados en el dominio.
Reutilización operativa
Dado que los microservicios prefieren la duplicación al acoplamiento, ¿cómo manejan los arquitectos
las partes de la arquitectura que realmente se benefician del acoplamiento, como las preocupaciones
operativas como la monitorización, el registro y los disyuntores? Una de las filosofías de la
arquitectura orientada a servicios tradicional era reutilizar la mayor cantidad posible de funcionalidad,
tanto de dominio como operativa. En los microservicios, los arquitectos intentan dividir estas dos
preocupaciones.
Una vez que un equipo ha creado varios microservicios, se da cuenta de que cada uno tiene
elementos comunes que se benefician de la similitud. Por ejemplo, si una organización permite que
cada equipo de servicio implemente la monitorización por sí mismo, ¿cómo puede garantizar que
cada equipo lo haga? ¿Y cómo manejan cuestiones como las actualizaciones? ¿Es responsabilidad
de cada equipo manejar la actualización a la nueva versión de la herramienta de monitorización?
¿Cuánto tiempo llevará eso?
El patrón sidecar ofrece una solución a este problema, ilustrada en la Figura 172.
En la Figura 172, las preocupaciones operativas comunes aparecen dentro de cada servicio como
un componente separado, que puede ser propiedad de equipos individuales o de un equipo de
infraestructura compartida. El componente sidecar maneja todas las preocupaciones operativas que
los equipos se benefician al acoplar. Por lo tanto, cuando llega el momento de actualizar la
herramienta de monitoreo, el equipo de infraestructura compartida puede actualizar el sidecar y
cada microservicio recibe esa nueva funcionalidad.
Una vez que los equipos saben que cada servicio incluye un componente secundario común, pueden
crear una malla de servicios, lo que permite un control unificado en toda la arquitectura para cuestiones
como el registro y la supervisión. Los componentes secundarios comunes se conectan para formar una
interfaz operativa consistente en todos los microservicios, como se muestra en la Figura 173.
Figura 173. El plano de servicio conecta los sidecars en una malla de servicio
En la Figura 173, cada sidecar se conecta al plano de servicio, que forma la interfaz consistente para
cada servicio.
La malla de servicios en sí forma una consola que permite a los desarrolladores un acceso integral a los
servicios, lo que se muestra en la Figura 174.
Figura 174. La malla de servicios forma una vista holística del aspecto operativo de los microservicios.
vicios
Cada servicio forma un nodo en la malla general, como se muestra en la Figura 174. La malla de servicios
forma una consola que permite a los equipos controlar globalmente el acoplamiento operativo, como los
niveles de monitoreo, el registro y otras cuestiones operativas transversales.
Los arquitectos utilizan el descubrimiento de servicios como una forma de incorporar elasticidad a las
arquitecturas de microservicios. En lugar de invocar un solo servicio, una solicitud pasa por una herramienta
de descubrimiento de servicios, que puede monitorear la cantidad y la frecuencia de las solicitudes, así como
generar nuevas instancias de servicios para manejar problemas de escala o elasticidad. Los arquitectos a
menudo incluyen el descubrimiento de servicios en la malla de servicios, lo que lo convierte en parte de cada microservicio.
La capa API se utiliza a menudo para alojar el descubrimiento de servicios, lo que permite un único lugar para
que las interfaces de usuario u otros sistemas de llamada encuentren y creen servicios de forma elástica y
consistente.
Interfaces
Los microservicios favorecen el desacoplamiento, que idealmente abarcaría las interfaces de usuario,
así como las cuestiones del backend. De hecho, la visión original de los microservicios incluía la interfaz
de usuario como parte del contexto delimitado, fiel al principio de DDD. Sin embargo, los aspectos
prácticos de la partición requerida por las aplicaciones web y otras restricciones externas dificultan ese
objetivo. Por lo tanto, suelen aparecer dos estilos de interfaces de usuario para las arquitecturas de
microservicios; el primero aparece en la Figura 175.
En la Figura 175, el frontend monolítico presenta una única interfaz de usuario que realiza llamadas a
través de la capa API para satisfacer las solicitudes de los usuarios. El frontend podría ser una
aplicación web, móvil o de escritorio enriquecida. Por ejemplo, muchas aplicaciones web ahora utilizan
un marco web JavaScript para crear una única interfaz de usuario.
La segunda opción para interfaces de usuario utiliza microfrontends, que se muestran en la Figura 176.
En la Figura 176, este enfoque utiliza componentes en el nivel de la interfaz de usuario para crear un nivel
sincrónico de granularidad y aislamiento en la interfaz de usuario como servicios de backend. Cada servicio
emite la interfaz de usuario para ese servicio, que el frontend coordina con los demás componentes de la
interfaz de usuario emitidos. Con este patrón, los equipos pueden aislar los límites de los servicios desde la
interfaz de usuario hasta los servicios de backend, unificando todo el dominio dentro de un solo equipo.
Los desarrolladores pueden implementar el patrón microfrontend de diversas maneras, ya sea utilizando un
marco web basado en componentes como React o utilizando uno de varios marcos de código abierto que
admiten este patrón.
Comunicación
En los microservicios, los arquitectos y desarrolladores tienen dificultades para encontrar la granularidad
adecuada, lo que afecta tanto al aislamiento de los datos como a la comunicación. Encontrar el estilo de
comunicación correcto ayuda a los equipos a mantener los servicios desacoplados pero coordinados de maneras útiles.
Básicamente, los arquitectos deben decidir entre comunicación sincrónica o asincrónica. La comunicación
sincrónica requiere que el emisor de la llamada espere una respuesta del receptor de la llamada. Las
arquitecturas de microservicios suelen utilizar interoperabilidad heterogénea que reconoce protocolos. Vamos
a explicar ese término:
Consciente de
protocolos Dado que los microservicios generalmente no incluyen un centro de integración
centralizado para evitar el acoplamiento operativo, cada servicio debe saber cómo llamar a otros servicios.
Por lo tanto, los arquitectos suelen estandarizar la forma en que determinados servicios se llaman
entre sí: un determinado nivel de REST, colas de mensajes, etc. Esto significa que los servicios
deben saber (o descubrir) qué protocolo utilizar para llamar a otros servicios.
Heterogéneo
Debido a que los microservicios son una arquitectura distribuida, cada servicio puede estar escrito
en una pila de tecnología diferente. Heterogéneo sugiere que los microservicios son totalmente
compatibles con entornos políglotas, donde los diferentes servicios utilizan diferentes plataformas.
Interoperabilidad
Describe los servicios que se llaman entre sí. Si bien los arquitectos de microservicios intentan
desalentar las llamadas a métodos transaccionales, los servicios suelen llamar a otros servicios
a través de la red para colaborar y enviar/recibir información.
Heterogeneidad forzada Un
conocido arquitecto que fue pionero en el estilo de microservicios fue el arquitecto jefe de una
startup de administración de información personal para dispositivos móviles. Debido a que
tenían un dominio de problemas de rápida evolución, el arquitecto quería asegurarse de que
ninguno de los equipos de desarrollo creara accidentalmente puntos de acoplamiento entre sí,
lo que obstaculizara la capacidad de los equipos de moverse de forma independiente. Resultó
que este arquitecto tenía una amplia mezcla de habilidades técnicas en los equipos, por lo que
exigía que cada equipo de desarrollo utilizara una pila de tecnología diferente. Si un equipo
usaba Java y el otro .NET, ¡era imposible compartir clases accidentalmente!
Para la comunicación asincrónica, los arquitectos a menudo utilizan eventos y mensajes, utilizando así
internamente una arquitectura basada en eventos, que se trata en el Capítulo 14; los patrones de
intermediario y mediador se manifiestan en los microservicios como coreografía y orquestación.
Comunicación | 255
Machine Translated by Google
El isomorfismo dominio/arquitectura es una característica clave que los arquitectos deben buscar al evaluar
qué tan apropiado es un estilo arquitectónico para un problema particular.
Este término describe cómo la forma de una arquitectura se corresponde con un estilo arquitectónico particular.
Por ejemplo, en la Figura 87, la arquitectura técnicamente particionada de los sándwiches de silicio admite
estructuralmente la personalización, y el estilo de arquitectura del microkernel ofrece la misma estructura
general. Por lo tanto, los problemas que requieren un alto grado de personalización se vuelven más fáciles de
implementar en un microkernel.
De manera similar, debido a que el objetivo del arquitecto en una arquitectura de microservicios favorece el
desacoplamiento, la forma de los microservicios se asemeja al EDA del broker, lo que hace que estos dos
patrones sean simbióticos.
En la coreografía, cada servicio llama a otros servicios según sea necesario, sin un mediador central. Por
ejemplo, considere el escenario que se muestra en la Figura 177.
En la Figura 177, el usuario solicita detalles sobre su lista de deseos. Como el servicio Customer
WishList no contiene toda la información necesaria, realiza una llamada a CustomerDemographics
para recuperar la información faltante y devuelve el resultado al usuario.
Debido a que las arquitecturas de microservicios no incluyen un mediador global como otras
arquitecturas orientadas a servicios, si un arquitecto necesita coordinar varios servicios, puede crear
su propio mediador localizado, como se muestra en la Figura 178.
En la Figura 178, los desarrolladores crean un servicio cuya única responsabilidad es coordinar la
llamada para obtener toda la información de un cliente en particular. El usuario llama al mediador
Report CustomerInformation , que llama a los demás servicios necesarios.
Comunicación | 257
Machine Translated by Google
La primera ley de la arquitectura de software sugiere que ninguna de estas soluciones es perfecta, ya que
cada una tiene sus pros y sus contras. En la coreografía, el arquitecto conserva la filosofía altamente
disociada del estilo arquitectónico, con lo que obtiene los máximos beneficios que promueve el estilo. Sin
embargo, los problemas comunes, como el manejo de errores y la coordinación, se vuelven más complejos
en los entornos coreografiados.
Considere un ejemplo con un flujo de trabajo más complejo, que se muestra en la Figura 179.
En la Figura 179, el primer servicio llamado debe coordinarse con una amplia variedad de otros servicios,
actuando básicamente como mediador además de sus otras responsabilidades de dominio. Este patrón
se denomina patrón de controlador frontal, donde un servicio coreografiado nominalmente se convierte en
un mediador más complejo para algún problema. La desventaja de este patrón es que agrega complejidad
al servicio.
Como alternativa, un arquitecto puede optar por utilizar la orquestación para procesos de negocio
complejos, como se ilustra en la Figura 1710.
Comunicación | 259
Machine Translated by Google
Siempre existen excepciones. Por ejemplo, puede surgir una situación en la que dos servicios
diferentes necesiten características arquitectónicas muy diferentes, lo que requiere límites de servicio
distintos, pero aun así necesitan coordinación transaccional. En esas situaciones, existen patrones
para gestionar la orquestación de transacciones, con serias desventajas.
Comunicación | 261
Machine Translated by Google
En una condición de error, el mediador debe garantizar que ninguna parte de la transacción tenga éxito si una
parte falla. Considere la situación que se muestra en la Figura 1712.
Figura 1712. Patrón Saga que compensa las transacciones en caso de condiciones de error
En la Figura 1712, si la primera parte de la transacción tiene éxito, pero la segunda parte falla, el mediador
debe enviar una solicitud a todas las partes de la transacción que tuvieron éxito y decirles que deshagan la
solicitud anterior. Este estilo de coordinación transaccional se denomina marco de transacción compensatoria.
Los desarrolladores implementan este patrón haciendo que cada solicitud del mediador ingrese en un estado
pendiente hasta que el mediador indique un éxito general. Sin embargo, este diseño se vuelve complejo si se
deben hacer malabarismos con solicitudes asincrónicas, especialmente si aparecen nuevas solicitudes que
dependen del estado transaccional pendiente. Esto también crea mucho tráfico de coordinación a nivel de red.
Otra implementación de un marco de transacciones compensatorias consiste en que los desarrolladores creen
operaciones de hacer y deshacer para cada operación potencialmente transaccional. Esto permite una menor
coordinación durante las transacciones, pero las operaciones de deshacer tienden a ser significativamente más
complejas que las operaciones de hacer, lo que duplica el trabajo de diseño, implementación y depuración.
Si bien es posible que los arquitectos creen un comportamiento transaccional entre servicios, esto va en contra
del motivo por el que se eligió el patrón de microservicios. Siempre existen excepciones, por lo que el mejor
consejo para los arquitectos es utilizar el patrón saga con moderación.
Cabe destacar el alto nivel de apoyo a las prácticas de ingeniería modernas, como la implementación
automatizada, la capacidad de prueba y otras que no se mencionan. Los microservicios no podrían existir sin la
revolución de DevOps y la marcha incesante hacia la automatización de los controles operativos.
preocupaciones.
Como los microservicios son una arquitectura distribuida, sufren muchas de las deficiencias inherentes a las
arquitecturas hechas de piezas conectadas entre sí en tiempo de ejecución. Por lo tanto, la tolerancia a fallas y
la confiabilidad se ven afectadas cuando se utiliza demasiada comunicación entre servicios. Sin embargo, estas
calificaciones solo indican tendencias en la arquitectura; los desarrolladores solucionan muchos de estos
problemas mediante redundancia y escalado a través del descubrimiento de servicios. Sin embargo, en
circunstancias normales, los servicios independientes de un solo propósito generalmente conducen a una alta
tolerancia a fallas, de ahí la alta calificación para esta característica dentro de una arquitectura de microservicios.
Los puntos fuertes de esta arquitectura son la escalabilidad, la elasticidad y la capacidad evolutiva. Algunos de
los sistemas más escalables que se han escrito hasta ahora han utilizado este estilo con gran éxito. De manera
similar, debido a que la arquitectura se basa en gran medida en la automatización y la integración inteligente
con las operaciones, los desarrolladores también pueden incorporar soporte de elasticidad en la arquitectura.
Debido a que la arquitectura favorece un alto desacoplamiento a un nivel incremental, respalda la práctica
comercial moderna de cambio evolutivo, incluso a nivel de arquitectura.
Los negocios modernos se mueven rápidamente y el desarrollo de software ha luchado por mantener el ritmo.
Al construir una arquitectura que tiene unidades de implementación extremadamente pequeñas y altamente
disociadas, los arquitectos tienen una estructura que puede soportar un ritmo de cambio más rápido.
El rendimiento suele ser un problema en los microservicios: las arquitecturas distribuidas deben
realizar muchas llamadas de red para completar el trabajo, lo que implica una gran sobrecarga de
rendimiento, y deben invocar controles de seguridad para verificar la identidad y el acceso a cada punto final.
Existen muchos patrones en el mundo de los microservicios para aumentar el rendimiento, incluido el
almacenamiento en caché y la replicación de datos inteligentes para evitar un exceso de llamadas de red.
El rendimiento es otra razón por la que los microservicios a menudo utilizan coreografía en lugar de
orquestación, ya que un menor acoplamiento permite una comunicación más rápida y menos cuellos
de botella.
Los microservicios son una arquitectura claramente centrada en el dominio, donde cada límite de
servicio debe corresponder a los dominios. También tiene los cuantos más distintivos de cualquier
arquitectura moderna; en muchos sentidos, ejemplifica lo que evalúa la medida cuántica. La
filosofía impulsora del desacoplamiento extremo crea muchos dolores de cabeza en esta
arquitectura, pero produce enormes beneficios cuando se hace bien. Como en cualquier
arquitectura, los arquitectos deben comprender las reglas para romperlas de manera inteligente.
Referencias adicionales
Si bien nuestro objetivo en este capítulo fue abordar algunos de los aspectos más importantes de
este estilo arquitectónico, existen muchos recursos excelentes para obtener más información
sobre este estilo arquitectónico. Puede encontrar información adicional y más detallada sobre los
microservicios en las siguientes referencias:
CAPÍTULO 18
Elegir lo apropiado
Estilo arquitectónico
¡Depende! Con todas las opciones disponibles (y nuevas opciones que aparecen casi a diario), nos gustaría
decirle cuál usar, pero no podemos. Nada es más contextual que una serie de factores dentro de una organización
y el software que crea. La elección de un estilo de arquitectura representa la culminación del análisis y la reflexión
sobre las compensaciones entre las características de la arquitectura, las consideraciones de dominio, los
objetivos estratégicos y una serie de otras cosas.
Independientemente del contexto de la decisión, existen algunos consejos generales sobre cómo elegir un estilo
arquitectónico apropiado.
Cambios en el ecosistema El
cambio constante es una característica confiable del ecosistema de desarrollo de software: todo cambia
todo el tiempo. El cambio en nuestro ecosistema es particularmente
267
Machine Translated by Google
caótico, lo que hace que incluso el tipo de cambio sea imposible de predecir. Por ejemplo, hace unos años,
nadie sabía qué era Kubernetes, y ahora hay múltiples conferencias en todo el mundo con miles de
desarrolladores. En unos años más, Kubernetes puede ser reemplazado por alguna otra herramienta que aún
no se haya escrito.
Nuevas capacidades
Cuando surgen nuevas capacidades, la arquitectura no solo puede reemplazar una herramienta por otra, sino
que puede cambiar a un paradigma completamente nuevo. Por ejemplo, pocos arquitectos o desarrolladores
anticiparon el cambio tectónico que causó en el mundo del desarrollo de software la llegada de contenedores
como Docker. Si bien fue un paso evolutivo, el impacto que tuvo en los arquitectos, las herramientas, las
prácticas de ingeniería y una serie de otros factores asombró a la mayoría de la industria. El cambio constante
en el ecosistema también ofrece una nueva colección de herramientas y capacidades de forma regular.
Los arquitectos deben estar atentos no sólo a las nuevas herramientas sino también a los nuevos paradigmas.
Es posible que algo parezca una novedad de algo que ya tenemos, pero puede incluir matices u otros cambios
que lo conviertan en un elemento innovador. Las nuevas capacidades ni siquiera tienen por qué revolucionar
todo el mundo del desarrollo: las nuevas características pueden ser un cambio menor que se alinee
exactamente con los objetivos de un arquitecto.
Aceleración
No solo el ecosistema cambia constantemente, sino que la tasa de cambio también sigue aumentando. Las
nuevas herramientas crean nuevas prácticas de ingeniería, que conducen a nuevos diseños y capacidades.
Los arquitectos viven en un estado de cambio constante porque el cambio es generalizado y constante.
Cambios de dominio
El dominio para el cual los desarrolladores escriben software cambia constantemente, ya sea porque el
negocio continúa evolucionando o por factores como fusiones con otras empresas.
La tecnología cambia A
medida que la tecnología continúa evolucionando, las organizaciones intentan mantenerse al día con al menos
algunos de estos cambios, especialmente aquellos con obvios beneficios finales.
Factores externos
Muchos factores externos que solo se asocian de manera periférica con el desarrollo de software pueden
impulsar cambios dentro de una organización. Por ejemplo, los arquitectos y desarrolladores pueden estar
perfectamente satisfechos con una herramienta en particular, pero el costo de la licencia se ha vuelto
prohibitivo, lo que obliga a migrar a otra opción.
Criterios de decisión
Al elegir un estilo arquitectónico, un arquitecto debe tener en cuenta todos los diversos factores que
contribuyen a la estructura del diseño del dominio. Básicamente, un arquitecto diseña dos cosas: el dominio
que se ha especificado y todos los demás elementos estructurales necesarios para que el sistema sea un
éxito.
Los arquitectos deben tomar decisiones de diseño sintiéndose cómodos con los siguientes aspectos:
El dominio
Los arquitectos deben comprender muchos aspectos importantes del dominio, especialmente aquellos
que afectan las características de la arquitectura operativa. Los arquitectos no tienen que ser expertos
en la materia, pero deben tener al menos un buen conocimiento general de los aspectos principales
del dominio en diseño.
Arquitectura de datos
Los arquitectos y los administradores de bases de datos deben colaborar en cuestiones relacionadas
con bases de datos, esquemas y otros datos. En este libro no abordamos demasiado la arquitectura
de datos, ya que es una especialidad en sí misma. Sin embargo, los arquitectos deben comprender el
impacto que el diseño de datos puede tener en su diseño, en particular si el nuevo sistema debe
interactuar con una arquitectura de datos más antigua o en uso.
Factores organizativos
Muchos factores externos pueden influir en el diseño. Por ejemplo, el costo de un proveedor de
servicios en la nube en particular puede impedir que se logre el diseño ideal. O tal vez la empresa
planee participar en fusiones y adquisiciones, lo que alienta a un arquitecto a gravitar hacia soluciones
abiertas y arquitecturas de integración.
operaciones y arquitectura basada en el espacio, que ofrece una gran cantidad de procesadores
discretos.
De manera similar, algunos dominios problemáticos pueden ser particularmente inadecuados para
algunos estilos de arquitectura. Por ejemplo, los sistemas altamente escalables tienen dificultades
con diseños monolíticos grandes porque a los arquitectos les resulta difícil admitir una gran cantidad
de usuarios simultáneos en una base de código altamente acoplada. Un dominio problemático que
incluye una gran cantidad de acoplamiento semántico coincide mal con una arquitectura distribuida
y altamente desacoplada. Por ejemplo, una aplicación de una compañía de seguros que consta de
formularios de varias páginas, cada uno de los cuales se basa en el contexto de páginas anteriores,
sería difícil de modelar en microservicios. Este es un problema altamente acoplado que presentará
a los arquitectos desafíos de diseño en una arquitectura desacoplada; una arquitectura menos
acoplada como la arquitectura basada en servicios se adaptaría mejor a este problema.
Si la arquitectura es monolítica, los arquitectos suelen suponer que hay una única base de datos
relacional o varias. En una arquitectura distribuida, el arquitecto debe decidir qué servicios deben
conservar los datos, lo que también implica pensar en cómo deben fluir los datos a lo largo de la
arquitectura para crear flujos de trabajo. Los arquitectos deben tener en cuenta tanto la estructura
como el comportamiento al diseñar la arquitectura y no tener miedo de iterar sobre el diseño para
encontrar mejores combinaciones.
El resultado de este proceso de diseño es la topología de la arquitectura, que tiene en cuenta el estilo
de arquitectura (y las hibridaciones) que eligió el arquitecto, los registros de decisiones de arquitectura
sobre las partes del diseño que requirieron el mayor esfuerzo por parte del arquitecto y las funciones
de aptitud de la arquitectura para proteger los principios importantes y las características operativas
de la arquitectura.
Sin embargo, creamos dos diseños de componentes diferentes para los sándwiches de silicio: uno con
particiones de dominio y otro con particiones técnicas. Dada la simplicidad de la solución, crearemos
diseños para cada uno y abordaremos las ventajas y desventajas.
Monolito modular
Un monolito modular construye componentes centrados en el dominio con una única base de datos,
implementada como un único quantum; el diseño del monolito modular para Silicon Sandwiches aparece
en la Figura 181.
Se trata de un monolito con una única base de datos relacional, implementado con una única interfaz
de usuario basada en la web (con cuidadosas consideraciones de diseño para dispositivos móviles) para
mantener bajos los costos generales. Cada uno de los dominios que el arquitecto identificó anteriormente
aparecen como componentes. Si el tiempo y los recursos son suficientes, el arquitecto debería considerar
la posibilidad de crear la misma separación de tablas y otros activos de base de datos que los
componentes del dominio, lo que permitiría que esta arquitectura migre a una arquitectura distribuida
más fácilmente si los requisitos futuros lo justifican.
micronúcleo
Una de las características de la arquitectura que el arquitecto identificó en Silicon Sandwiches fue la
capacidad de personalización. Si se considera el isomorfismo entre dominio y arquitectura, un arquitecto
puede optar por implementarlo utilizando un microkernel, como se ilustra en la Figura 182.
En la Figura 182, el sistema central consta de los componentes del dominio y una única base de datos
relacional. Al igual que en el diseño anterior, la sincronización cuidadosa entre los dominios y el diseño
de los datos permitirá la migración futura del núcleo a una arquitectura distribuida.
Cada personalización aparece en un complemento, las comunes en un único conjunto de complementos
(con una base de datos correspondiente) y una serie de locales, cada uno con sus propios datos.
Como ninguno de los complementos necesita estar acoplado a los otros complementos, cada uno puede
mantener sus datos, dejando los complementos desacoplados.
El otro elemento de diseño único aquí utiliza Backends para Frontends (BFF) patrón, lo que convierte a
la capa API en un adaptador de microkernel delgado. Proporciona información general desde el backend
y los adaptadores BFF traducen la información genérica al formato adecuado para el dispositivo frontend.
Por ejemplo, BFF para iOS tomará la salida genérica del backend y la personalizará para lo que espera
la aplicación nativa de iOS: el formato de datos, la paginación, la latencia y otros factores. Construir cada
BFF
El adaptador permite las interfaces de usuario más completas y la capacidad de expandirse para
soportar otros dispositivos en el futuro, uno de los beneficios del estilo microkernel.
La comunicación dentro de cualquier arquitectura Silicon Sandwich puede ser sincrónica (la
arquitectura no requiere requisitos extremos de rendimiento o elasticidad) y ninguna de las
operaciones será larga.
Los requisitos para GGG también establecen explícitamente ciertos niveles ambiciosos de escala,
elasticidad, rendimiento y una serie de otras características complicadas de la arquitectura operativa.
El arquitecto debe elegir un patrón que permita un alto grado de personalización a un nivel de grano
fino dentro de la arquitectura. De las arquitecturas distribuidas candidatas, tanto las impulsadas por
eventos de bajo nivel como los microservicios coinciden con la mayoría de las características de la
arquitectura. De los dos, los microservicios admiten mejor las diferentes características de la
arquitectura operativa: las arquitecturas puramente impulsadas por eventos normalmente no
separan las piezas debido a estas características de la arquitectura operativa, sino que se basan
en el estilo de comunicación, orquestado en lugar de coreografiado.
Alcanzar el rendimiento indicado será un desafío en el caso de los microservicios, pero los
arquitectos a menudo pueden abordar cualquier punto débil de una arquitectura diseñando para
adaptarse a él. Por ejemplo, si bien los microservicios ofrecen naturalmente un alto grado de
escalabilidad, los arquitectos comúnmente tienen que abordar problemas de rendimiento específicos
causados por demasiada orquestación, separación de datos demasiado agresiva, etc.
Postor
Los numerosos postores de la subasta en línea.
Subastador
Uno por subasta.
Servicio de
transmisión en directo responsable de transmitir el vídeo y la oferta a los postores. Tenga en cuenta que se trata de una
transmisión de solo lectura, lo que permite realizar optimizaciones que no están disponibles si fuera necesario realizar
actualizaciones.
Captura de ofertas
Captura las entradas de los postores en línea y las envía de forma asincrónica a Bid Tracker.
Este servicio no necesita persistencia porque actúa como un conducto para las ofertas en línea.
Oferta Streamer
Transmite las ofertas a los participantes en línea en un formato de solo lectura y alto rendimiento.
arroyo.
rastreador de ofertas
Realiza un seguimiento de las ofertas tanto de Auctioneer Capture como de Bid Capture. Este es
el componente que unifica los dos flujos de información diferentes, ordenando las ofertas lo más
cerca posible del tiempo real. Tenga en cuenta que ambas conexiones entrantes a este servicio
son asincrónicas, lo que permite a los desarrolladores utilizar colas de mensajes como búferes para
gestionar velocidades de flujo de mensajes muy diferentes.
Sesión de subasta
Pago
Proveedor de pagos de terceros que maneja la información de pago después de que la sesión de
subasta haya completado la subasta.
Captura de video
Captura la transmisión de video de la subasta en vivo.
Video Streamer
Transmite el video de la subasta a los postores en línea.
En el análisis final, este diseño se resolvió en cinco cuantos, identificados en la Figura 184.
En la Figura 184, el diseño incluye los cuantos para Pago, Subastador, Postor, Flujos de Postores y
Rastreador de Ofertas, que corresponden aproximadamente a los servicios. Las instancias múltiples
se indican mediante pilas de contenedores en el diagrama. El uso del análisis cuántico en la etapa
de diseño de componentes permitió al arquitecto identificar más fácilmente los límites de servicio,
datos y comunicación.
Tenga en cuenta que este no es el diseño “correcto” para GGG, y ciertamente no es el único.
Ni siquiera sugerimos que sea el mejor diseño posible, pero parece ser el que tiene el menor
conjunto de desventajas. Elegir microservicios y luego usar de manera inteligente eventos y
mensajes permite que la arquitectura aproveche al máximo un patrón de arquitectura genérico y,
al mismo tiempo, construya una base para el desarrollo y la expansión futuros.
PARTE III
CAPÍTULO 19
Decisiones de arquitectura
281
Machine Translated by Google
Hay dos maneras de superar este antipatrón. La primera es esperar hasta el último momento
responsable para tomar una decisión arquitectónica importante. El último momento responsable
significa esperar hasta tener suficiente información para justificar y validar su decisión, pero no
esperar tanto que retrase a los equipos de desarrollo o caiga en el antipatrón de la parálisis por
análisis. La segunda manera de evitar este antipatrón es colaborar continuamente con los equipos
de desarrollo para garantizar que la decisión que tomó se pueda implementar como se esperaba.
Esto es de vital importancia porque no es factible que un arquitecto conozca todos los detalles sobre
una tecnología en particular y todos los problemas asociados. Al colaborar estrechamente con los
equipos de desarrollo, el arquitecto puede responder rápidamente a un cambio en la decisión
arquitectónica si surgen problemas.
Para ilustrar este punto, supongamos que un arquitecto toma la decisión de que todos los datos de
referencia relacionados con el producto (descripción del producto, peso y dimensiones) se almacenen
en caché en todas las instancias de servicio que necesitan esa información mediante un caché
replicado de solo lectura, con la réplica principal propiedad del servicio de catálogo. Un caché
replicado significa que si hay algún cambio en la información del producto (o se agrega un nuevo
producto), el servicio de catálogo actualizaría su caché, que luego se replicaría a todos los demás
servicios que requieren esos datos a través de un producto de caché replicado (en memoria). Una
buena justificación para esta decisión es reducir el acoplamiento entre los servicios y compartir datos
de manera efectiva sin tener que hacer una llamada entre servicios. Sin embargo, los equipos de
desarrollo que implementan esta decisión de arquitectura descubren que debido a ciertos requisitos
de escalabilidad de algunos de los servicios, esta decisión requeriría más memoria en proceso de la
que está disponible. Al colaborar estrechamente con los equipos de desarrollo, el arquitecto puede
darse cuenta rápidamente del problema y ajustar la decisión de arquitectura para adaptarse a estas
situaciones.
El antipatrón del Día de la Marmota se produce porque una vez que un arquitecto toma una decisión
arquitectónica, no proporciona una justificación para la decisión (o una justificación completa). Al
justificar las decisiones arquitectónicas, es importante proporcionar justificaciones tanto técnicas
como comerciales para su decisión. Por ejemplo, un arquitecto puede
tomar la decisión de dividir una aplicación monolítica en servicios separados para desacoplar los
aspectos funcionales de la aplicación de modo que cada parte de la aplicación utilice menos recursos
de máquina virtual y pueda mantenerse e implementarse por separado.
Si bien este es un buen ejemplo de justificación técnica, lo que falta es la justificación comercial; en
otras palabras, ¿por qué la empresa debería pagar por esta refactorización arquitectónica? Una buena
justificación comercial para esta decisión podría ser la de entregar nuevas funciones comerciales más
rápido, mejorando así el tiempo de comercialización. Otra podría ser la de reducir los costos asociados
con el desarrollo y el lanzamiento de nuevas funciones.
Proporcionar el valor comercial al justificar las decisiones es de vital importancia para cualquier decisión
de arquitectura. También es una buena prueba de fuego para determinar si la decisión de arquitectura
debe tomarse en primer lugar. Si una decisión de arquitectura en particular no proporciona ningún valor
comercial, entonces tal vez no sea una buena decisión y deba reconsiderarse.
Cuatro de las justificaciones comerciales más comunes son el costo, el tiempo de comercialización, la
satisfacción del usuario y el posicionamiento estratégico. Al centrarse en estas justificaciones comerciales
comunes, es importante tener en cuenta lo que es importante para las partes interesadas de la empresa.
Justificar una decisión particular basándose únicamente en el ahorro de costos puede no ser la decisión
correcta si las partes interesadas de la empresa están menos preocupadas por el costo y más
preocupadas por el tiempo de comercialización.
Una vez que un arquitecto toma decisiones y las justifica plenamente, surge un tercer antipatrón
arquitectónico: la arquitectura basada en el correo electrónico. El antipatrón de la arquitectura basada
en el correo electrónico es aquel en el que las personas pierden, olvidan o ni siquiera saben que se ha
tomado una decisión arquitectónica y, por lo tanto, no pueden implementarla.
Este antipatrón tiene como objetivo comunicar de manera efectiva sus decisiones arquitectónicas.
El correo electrónico es una gran herramienta de comunicación, pero constituye un sistema deficiente de almacenamiento de
documentos.
La segunda regla para comunicar eficazmente las decisiones de arquitectura es notificar únicamente
a aquellas personas a las que realmente les importa la decisión de arquitectura. Una técnica eficaz es
escribir el cuerpo del correo electrónico de la
siguiente manera: “Hola Sandra, he tomado una decisión importante con respecto a la comunicación
entre servicios que te afecta directamente. Consulta la decisión mediante el siguiente enlace…”
Arquitectónicamente significativo
Muchos arquitectos creen que si la decisión arquitectónica involucra una tecnología específica,
entonces no es una decisión arquitectónica, sino más bien una decisión técnica. Esto no siempre es
cierto. Si un arquitecto toma la decisión de utilizar una tecnología particular porque apoya directamente
una característica arquitectónica particular (como el rendimiento o la escalabilidad), entonces es una
decisión arquitectónica.
Michael Nygård, Michael, un conocido arquitecto de software y autor de Release It! (Pragmatic
Bookshelf), abordó el problema de qué decisiones debe tomar un arquitecto (y, por lo tanto, qué es
una decisión de arquitectura) acuñando el término “arquitectónicamente significativa”. Según Michael,
las decisiones arquitectónicamente significativas son aquellas que afectan la estructura, las
características no funcionales, las dependencias, las interfaces o las técnicas de construcción.
La estructura se refiere a decisiones que afectan los patrones o estilos de arquitectura que se utilizan.
Un ejemplo de esto es la decisión de compartir datos entre un conjunto de microservicios. Esta
decisión afecta el contexto delimitado del microservicio y, como tal, afecta la estructura de la aplicación.
Las características no funcionales son las características de la arquitectura (“ilidades”) que son
importantes para la aplicación o el sistema que se está desarrollando o manteniendo. Si una elección
de tecnología afecta el rendimiento, y el rendimiento es un aspecto importante de la aplicación,
entonces se convierte en una decisión de arquitectura.
Las dependencias se refieren a puntos de acoplamiento entre componentes y/o servicios dentro del
sistema, que a su vez impactan la escalabilidad general, la modularidad, la agilidad, la capacidad de
prueba, la confiabilidad, etc.
Las interfaces hacen referencia a cómo se accede a los servicios y componentes y cómo se organizan,
generalmente a través de una puerta de enlace, un centro de integración, un bus de servicio o un proxy API. Las
interfaces suelen implicar la definición de contratos, incluida la estrategia de control de versiones y desuso de
esos contratos. Las interfaces afectan a otros usuarios del sistema y, por lo tanto, son arquitectónicamente
significativas.
Finalmente, las técnicas de construcción se refieren a decisiones sobre plataformas, marcos, herramientas e
incluso procesos que, aunque sean de naturaleza técnica, podrían afectar algún aspecto de la arquitectura.
Una de las formas más efectivas de documentar decisiones de arquitectura es a través de los Registros de
Decisiones de Arquitectura (ADR). Los ADR fueron evangelizados por primera vez por Michael Nygard en una
publicación de blog y posteriormente marcado como “adoptar” en el ThoughtWorks Technology Radar. Un ADR
consiste en un archivo de texto breve (normalmente de una o dos páginas) que describe una decisión de
arquitectura específica. Si bien los ADR se pueden escribir en texto sin formato, normalmente se escriben en
algún tipo de formato de documento de texto, como AsciiDoc. o Markdown.
Alternativamente, también se puede escribir un ADR utilizando una plantilla de página wiki.
También hay herramientas disponibles para gestionar los ADR. Nat Pryce, coautor de Growing ObjectOriented
Software Guided by Tests (AddisonWesley), ha escrito una herramienta de código abierto para los ADR
denominada ADRtools. ADRtools proporciona una interfaz de línea de comandos para administrar los ADR,
incluidos los esquemas de numeración, las ubicaciones y la lógica reemplazada. Micha Kops, un ingeniero de
software de Alemania, ha escrito una publicación en el blog sobre el uso de herramientas ADR que brindan
algunos excelentes ejemplos sobre cómo se pueden utilizar para administrar registros de decisiones de
arquitectura.
Estructura básica
La estructura básica de un ADR consta de cinco secciones principales: Título, Estado, Contexto, Decisión y
Consecuencias. Normalmente, añadimos dos secciones adicionales como parte de la estructura básica:
Cumplimiento y Notas. Esta estructura básica (como se ilustra en la Figura 191) se puede ampliar para incluir
cualquier otra sección que se considere necesaria, siempre que la plantilla se mantenga coherente y concisa. Un
buen ejemplo de esto podría ser añadir una sección de Alternativas si es necesario para proporcionar un análisis
de todas las demás posibles soluciones alternativas.
Título
El título de un ADR suele estar numerado secuencialmente y contiene una frase breve que describe las
decisiones de arquitectura. Por ejemplo, la decisión de utilizar mensajería asincrónica entre el Servicio
de pedidos y el Servicio de pagos podría decir: “42. Uso de mensajería asincrónica entre los Servicios
de pedidos y de pagos”. El título debe ser lo suficientemente descriptivo como para eliminar cualquier
ambigüedad sobre la naturaleza y el contexto de la decisión, pero al mismo tiempo debe ser breve y
conciso.
Estado
El estado de una ADR puede marcarse como Propuesta, Aceptada o Reemplazada. El estado Propuesta
significa que la decisión debe ser aprobada por un responsable de toma de decisiones de nivel superior
o algún tipo de organismo de gobernanza arquitectónica (como una junta de revisión de arquitectura).
El estado de Aceptado significa que la decisión ha sido aprobada y está lista para su implementación.
El estado de Reemplazado significa que la decisión ha sido modificada y reemplazada por otra ADR. El
estado de Reemplazado siempre supone que el estado de ADR anterior fue aceptado; en otras palabras,
una ADR propuesta nunca sería reemplazada por otra ADR, sino que continuaría modificándose hasta
que fuera aceptada.
El estado Reemplazado es una forma eficaz de mantener un registro histórico de las decisiones que
se tomaron, por qué se tomaron en ese momento y cuál es la nueva decisión y por qué se modificó.
Por lo general, cuando se reemplaza un ADR, se marca con la decisión que lo reemplazó. De manera
similar, la decisión que reemplaza a otro ADR se marca con el ADR que reemplazó. Por ejemplo,
supongamos que el ADR 42 (“Uso de mensajería asincrónica entre los servicios de pedidos y pagos”)
se aprobó anteriormente, pero debido a cambios posteriores en la implementación y la ubicación del
servicio de pagos, ahora se debe utilizar REST entre los dos servicios (ADR 68). El estado se vería
de la siguiente manera:
El vínculo y el rastro histórico entre los ADR 42 y 68 evitan la inevitable pregunta “¿qué pasa con el
uso de mensajería?” con respecto al ADR 68.
ESTADO
Otro aspecto importante de la sección Estado de un ADR es que obliga al arquitecto a tener las
conversaciones necesarias con su jefe o arquitecto principal sobre los criterios con los que puede
aprobar una decisión de arquitectura por su cuenta, o si debe ser aprobada a través de un arquitecto
de nivel superior, una junta de revisión de arquitectura o algún otro organismo rector de la arquitectura.
Tres criterios que constituyen un buen punto de partida para estas conversaciones son el costo, el
impacto entre equipos y la seguridad. El costo puede incluir la compra de software o tarifas de licencia,
costos de hardware adicionales, así como el nivel general de esfuerzo para implementar la arquitectura.
Una vez que se hayan establecido y acordado los criterios y los límites correspondientes (por ejemplo,
“los costes superiores a 5.000 € deben ser aprobados por el consejo de revisión de arquitectura”),
estos criterios deben estar bien documentados para que todos los arquitectos que creen ADR sepan
cuándo pueden y cuándo no pueden aprobar sus propias decisiones de arquitectura.
Contexto
La sección de contexto de un ADR especifica las fuerzas en juego. En otras palabras, “¿qué situación
me obliga a tomar esta decisión?” Esta sección del ADR permite al arquitecto describir la situación o
el problema específico y explicar de manera concisa las posibles alternativas. Si se requiere que un
arquitecto documente el análisis de cada alternativa en detalle, se puede agregar una sección de
Alternativas adicional al ADR en lugar de agregar ese análisis a la sección de Contexto.
Decisión
La sección de Decisión del ADR contiene la decisión de arquitectura, junto con una justificación
completa de la decisión. Michael Nygard introdujo una excelente manera de expresar una decisión de
arquitectura utilizando un tono de voz muy afirmativo y autoritario en lugar de uno pasivo. Por ejemplo,
la decisión de utilizar mensajería asincrónica entre servicios se leería “utilizaremos mensajería
asincrónica entre servicios”. Esta es una forma mucho mejor de expresar una decisión en comparación
con “Creo que la mensajería asincrónica entre servicios sería la mejor opción”. Observe que aquí no
está claro cuál es la decisión.
No importa si se ha tomado una decisión o no, sólo se expresa la opinión del arquitecto.
Tal vez uno de los aspectos más poderosos de la sección de Decisiones de los ADR es que
permite al arquitecto poner más énfasis en el por qué que en el cómo. Entender por qué se tomó
una decisión es mucho más importante que entender cómo funciona algo. La mayoría de los
arquitectos y desarrolladores pueden identificar cómo funcionan las cosas al observar los
diagramas de contexto, pero no por qué se tomó una decisión. Saber por qué se tomó una
decisión y la justificación correspondiente para la decisión ayuda a las personas a comprender
mejor el contexto del problema y evita posibles errores al refactorizar hacia otra solución que
podría generar problemas.
Para ilustrar este punto, considere una decisión de arquitectura original tomada hace varios años
para utilizar la Llamada a procedimiento remoto (gRPC) de Google. como un medio para
comunicarse entre dos servicios. Sin entender por qué se tomó esa decisión, otro arquitecto
varios años después decide anularla y usar la mensajería en su lugar para desacoplar mejor los
servicios. Sin embargo, la implementación de esta refactorización provoca de repente un
aumento significativo en la latencia, lo que a su vez, en última instancia, provoca que se
produzcan tiempos de espera en los sistemas ascendentes. Entender que el uso original de
gRPC era reducir significativamente la latencia (a costa de servicios estrechamente acoplados)
habría evitado que se produjera la refactorización en primer lugar.
Consecuencias
La sección Consecuencias de un ADR es otra sección muy importante. Esta sección documenta
el impacto general de una decisión de arquitectura. Cada decisión de arquitectura que toma un
arquitecto tiene algún tipo de impacto, tanto bueno como malo. Tener que especificar el impacto
de una decisión de arquitectura obliga al arquitecto a pensar si esos impactos superan los
beneficios de la decisión.
Otro buen uso de esta sección es documentar el análisis de las compensaciones asociadas con
la decisión de arquitectura. Estas compensaciones pueden estar basadas en costos o en
compensaciones contra otras características de la arquitectura (“ilidades”). Por ejemplo,
considere la decisión de usar mensajes asincrónicos (disparar y olvidar) para publicar una
reseña en un sitio web. La justificación de esta decisión es aumentar significativamente la
capacidad de respuesta de la solicitud de publicación de la reseña de 3100 milisegundos a 25
milisegundos porque los usuarios no tendrían que esperar a que se publique la reseña real (solo
a que se envíe el mensaje a una cola). Si bien esta es una buena justificación, alguien más
podría argumentar que es una mala idea debido a la complejidad del manejo de errores asociado
con una solicitud asincrónica (“¿qué sucede si alguien publica una reseña con algunas malas
palabras?”). Sin que la persona que impugnó esta decisión lo supiera, esa cuestión ya se había
discutido con las partes interesadas de la empresa y otros arquitectos, y se decidió desde una
perspectiva de compensación que era más importante aumentar la capacidad de respuesta y
lidiar con el manejo complejo de errores en lugar de tener que esperar para proporcionar de
manera sincrónica la retroalimentación al usuario de que la revisión se publicó correctamente.
Al aprovechar los ADR, ese análisis de compensación se puede incluir en la sección Consecuencias, lo que proporc
imagen del contexto (y las compensaciones) de la decisión de arquitectura y así evitar estas
situaciones.
Cumplimiento
Por ejemplo, considere la siguiente decisión de arquitectura dentro de una arquitectura tradicional
de n niveles, como se ilustra en la Figura 192. Todos los objetos compartidos que utilizan los
objetos comerciales en la capa comercial residirán en la capa de servicios compartidos para aislar
y contener la funcionalidad compartida.
@Test
public void los servicios compartidos deben residir en la capa de servicios () { clases ().
que (). están anotadas con (SharedService.class)
.should().resideInAPackage("..services..") .because("Todas
las clases de servicios compartidos utilizadas por la empresa" +
" +
"los objetos en la capa empresarial deben residir en la capa de servicios para aislar
y contener la lógica compartida") .check(myClasses);
}
Tenga en cuenta que esta función de aptitud automatizada requeriría que se escribieran nuevas
historias para crear una nueva anotación de Java (@SharedService) y luego agregar esta anotación
a todas las clases compartidas. Esta sección también especifica qué es la prueba, dónde se puede
encontrar la prueba y cómo se ejecutará la prueba y cuándo.
Notas
Otra sección que no forma parte de un ADR estándar pero que recomendamos encarecidamente agregar es la sección Notas.
Esta sección incluye varios metadatos sobre el ADR, como los siguientes:
aprobación • Aprobado
por • Fecha
reemplazada
• Modificado por •
Última modificación
Incluso cuando se almacenan ADR en un sistema de control de versiones (como Git), es útil contar con metainformación
adicional más allá de lo que el repositorio puede admitir, por lo que recomendamos agregar esta sección independientemente
de cómo y dónde se almacenen los ADR.
Almacenamiento de
ADR Una vez que un arquitecto crea un ADR, debe almacenarlo en algún lugar. Independientemente de dónde se almacenen
los ADR, cada decisión de arquitectura debe tener su propio archivo o página wiki.
A algunos arquitectos les gusta mantener los ADR en el repositorio Git junto con el código fuente. Mantener los ADR en un
repositorio Git permite controlar las versiones y realizar un seguimiento de los mismos.
Sin embargo, para las organizaciones más grandes desaconsejamos esta práctica por varias razones.
En primer lugar, es posible que no todos los que necesiten ver la decisión de arquitectura tengan acceso al repositorio Git. En
segundo lugar, este no es un buen lugar para almacenar ADR que tienen un contexto fuera del repositorio Git de la aplicación
(como decisiones de arquitectura de integración, decisiones de arquitectura empresarial o decisiones comunes a todas las
aplicaciones).
Por estos motivos, recomendamos almacenar los ADR en un wiki (utilizando una plantilla wiki) o en un
directorio compartido en un servidor de archivos compartido al que se pueda acceder fácilmente mediante
un wiki u otro software de representación de documentos. La Figura 193 muestra un ejemplo de cómo
podría verse esta estructura de directorio (o estructura de navegación de páginas wiki).
El directorio de la aplicación contiene las decisiones de arquitectura que son específicas de algún tipo de
contexto de aplicación. Este directorio se subdivide en otros directorios.
El subdirectorio común es para las decisiones de arquitectura que se aplican a todas las aplicaciones,
como “Todas las clases relacionadas con el marco contendrán una anotación (@Framework en Java) o
un atributo ([Framework] en C#) que identifique la clase como perteneciente al código del marco
subyacente”. Los subdirectorios bajo el directorio de la aplicación corresponden al contexto específico de
la aplicación o sistema y contienen las decisiones de arquitectura específicas de esa aplicación o sistema
(en este ejemplo, las aplicaciones ATP y PSTD). El directorio de integración contiene aquellas ADR que
involucran la comunicación entre aplicaciones, sistemas o servicios. Las ADR de arquitectura empresarial
están contenidas dentro del directorio empresarial, lo que indica que estas son decisiones de arquitectura
globales que impactan todos los sistemas y aplicaciones. Un ejemplo de una ADR de arquitectura
empresarial sería “Todo acceso a una base de datos del sistema será solo desde el sistema propietario”,
lo que evita el uso compartido de bases de datos entre múltiples sistemas.
Al almacenar ADR en una wiki (nuestra recomendación), se aplica la misma estructura descrita
anteriormente, donde cada estructura de directorio representa una página de inicio de navegación. Cada
ADR se representaría como una sola página wiki dentro de cada página de inicio de navegación
(Aplicación, Integración o Empresa).
Los nombres de directorios o páginas de destino que se indican en esta sección son solo una recomendación.
Cada empresa puede elegir los nombres que mejor se adapten a su situación, siempre que sean coherentes
entre los equipos.
Documentar la arquitectura del software siempre ha sido un tema difícil. Si bien están surgiendo algunos
estándares para la diagramación de la arquitectura (como el modelo C4 del arquitecto de software Simon Brown
o El Grupo Abierto ArchiMate No existe ningún estándar para documentar la arquitectura del software. Ahí es
donde entran en juego los ADR.
Los registros de decisiones de arquitectura pueden utilizarse como un medio eficaz para documentar una
arquitectura de software. La sección Contexto de un ADR proporciona una excelente oportunidad para describir
el área específica del sistema que requiere que se tome una decisión de arquitectura. Esta sección también
proporciona una oportunidad para describir las alternativas. Quizás lo más importante es que la sección Decisión
describe las razones por las que se toma una decisión en particular, que es, por lejos, la mejor forma de
documentación de arquitectura. La sección Consecuencias agrega la pieza final a la documentación de
arquitectura al describir aspectos adicionales de una decisión en particular, como el análisis de compensaciones
de elegir el rendimiento sobre la escalabilidad.
pocas personas les gustan los estándares. La mayoría de las veces, los estándares parecen estar establecidos
más para controlar a las personas y la forma en que hacen las cosas que para algo útil. El uso de ADR para
estándares puede cambiar esta mala práctica. Por ejemplo, la sección Contexto de un ADR describe la situación
que está forzando el estándar en particular. La sección Decisión de un ADR se puede utilizar no solo para indicar
cuál es el estándar, sino más importante aún, por qué el estándar necesita existir. Esta es una manera maravillosa
de poder calificar si el estándar en particular debería existir en primer lugar. Si un arquitecto no puede justificar
el estándar, entonces tal vez no sea un buen estándar para crear y hacer cumplir. Además, cuanto más entiendan
los desarrolladores por qué existe un estándar en particular, más probabilidades habrá de que lo sigan (y, en
consecuencia, no lo cuestionen).
La sección de Consecuencias de un ADR es otro gran lugar en el que un arquitecto puede calificar si una norma
es válida y debería ser adoptada. En esta sección, el arquitecto debe pensar y documentar cuáles son las
implicaciones y consecuencias de una norma en particular que está adoptando. Al analizar las consecuencias,
el arquitecto podría decidir que la norma no debería ser aplicada después de todo.
Ejemplo
Existen muchas decisiones de arquitectura dentro de nuestro “Estudio de caso: se va, se va, se
fue” en la página 95. El uso de microservicios controlados por eventos, la división de las
interfaces de usuario del postor y el subastador, el uso del Protocolo de transporte en tiempo
real (RTP) para la captura de video, el uso de una sola capa de API y el uso de mensajes de
publicación y suscripción son solo algunas de las docenas de decisiones de arquitectura que se
toman para este sistema de subasta. Cada decisión de arquitectura que se toma en un sistema,
sin importar cuán obvia sea, debe documentarse y justificarse.
La Figura 194 ilustra una de las decisiones de arquitectura dentro del sistema de subasta Going,
Going, Gone, que es el uso de mensajes de publicación y suscripción (pub/sub) entre los
servicios de captura de ofertas, transmisor de ofertas y rastreador de ofertas.
El ADR para esta decisión de arquitectura podría verse similar a la Figura 195:
Figura 195. ADR 76. Mensajería asincrónica de publicación y suscripción entre servicios de licitación
CAPÍTULO 20
Toda arquitectura tiene riesgos asociados, ya sean riesgos relacionados con la disponibilidad, la
escalabilidad o la integridad de los datos. Analizar los riesgos de la arquitectura es una de las
actividades clave de la arquitectura. Al analizar los riesgos de forma continua, el arquitecto puede
abordar las deficiencias de la arquitectura y tomar medidas correctivas para mitigarlos. En este
capítulo, presentamos algunas de las técnicas y prácticas clave para calificar los riesgos, crear
evaluaciones de riesgos e identificarlos mediante una actividad denominada análisis de riesgos.
Matriz de riesgo
La matriz de riesgo de la arquitectura (ilustrada en la Figura 201) utiliza dos dimensiones para
calificar el riesgo: el impacto general del riesgo y la probabilidad de que ese riesgo ocurra. Cada
dimensión tiene una calificación baja (1), media (2) y alta (3). Estos números se multiplican entre
sí dentro de cada cuadrícula de la matriz, lo que proporciona un número numérico objetivo que
representa ese riesgo. Los números 1 y 2 se consideran de bajo riesgo (verde), los números 3 y
4 se consideran de riesgo medio (amarillo) y los números del 6 al 9 se consideran de alto riesgo
(rojo).
297
Machine Translated by Google
Para ver cómo se puede utilizar la matriz de riesgo, supongamos que existe una preocupación sobre la
disponibilidad con respecto a una base de datos central primaria utilizada en la aplicación. Primero,
considere la dimensión de impacto: ¿cuál es el impacto general si la base de datos deja de funcionar o
deja de estar disponible? En este caso, un arquitecto podría considerar que ese riesgo es alto, lo que
lo convierte en un riesgo de 3 (medio), 6 (alto) o 9 (alto). Sin embargo, después de aplicar la segunda
dimensión (probabilidad de que ocurra el riesgo), el arquitecto se da cuenta de que la base de datos
está en servidores de alta disponibilidad en una configuración en clúster, por lo que la probabilidad de
que la base de datos deje de estar disponible es baja. Por lo tanto, la intersección entre el alto impacto
y la baja probabilidad da una calificación de riesgo general de 3 (riesgo medio).
Evaluaciones de riesgos
La matriz de riesgos descrita en la sección anterior se puede utilizar para crear lo que se denomina una
evaluación de riesgos. Una evaluación de riesgos es un informe resumido del riesgo general de una arquitectura
con respecto a algún tipo de criterio de evaluación contextual y significativo.
Las evaluaciones de riesgo pueden variar mucho, pero en general contienen el riesgo (calificado a partir
de la matriz de riesgo) de algunos criterios de evaluación basados en servicios o áreas de dominio de
una aplicación. Este formato básico de informe de evaluación de riesgo se ilustra en la Figura 202,
donde el gris claro (12) es riesgo bajo, el gris medio (34) es riesgo medio y el gris oscuro (69) es
riesgo alto. Por lo general, estos están codificados por colores como verde (bajo), amarillo (medio) y
rojo (alto), pero el sombreado puede ser útil para la representación en blanco y negro y para el
daltonismo.
El riesgo cuantificado de la matriz de riesgo se puede acumular por criterios de riesgo y también por
área de servicio o dominio. Por ejemplo, observe en la Figura 202 que el riesgo acumulado para la
integridad de los datos es el área de riesgo más alta con un total de 17, mientras que el riesgo
acumulado para la disponibilidad es solo 10 (la menor cantidad de riesgo). El riesgo relativo de cada
área de dominio también se puede determinar mediante la evaluación de riesgo de ejemplo. Aquí, el
registro de clientes conlleva el área de riesgo más alta, mientras que el cumplimiento de pedidos
conlleva el riesgo más bajo. Luego, se pueden rastrear estos números relativos para demostrar mejoras
o degradación del riesgo dentro de una categoría de riesgo o dominio en particular.
área.
Aunque el ejemplo de evaluación de riesgos de la Figura 202 contiene todos los resultados del análisis
de riesgos, rara vez se presenta como tal. El filtrado es esencial para indicar visualmente un mensaje
particular dentro de un contexto determinado. Por ejemplo, supongamos que un arquitecto está en una
reunión con el propósito de presentar áreas del sistema que son de alto riesgo. En lugar de presentar la
evaluación de riesgos como se ilustra en la Figura 202, se puede utilizar el filtrado para mostrar solo
las áreas de alto riesgo (mostradas en la Figura 203), mejorando la relación señalruido general y
presentando una imagen clara del estado del sistema (bueno o malo).
Figura 203. Filtrado de la evaluación de riesgos solo para los de alto riesgo
Otro problema con la Figura 202 es que este informe de evaluación solo muestra una
instantánea en el tiempo; no muestra si las cosas están mejorando o empeorando. En otras
palabras, la Figura 202 no muestra la dirección del riesgo. Representar la dirección del
riesgo presenta un problema. Si se utilizara una flecha hacia arriba o hacia abajo para
indicar la dirección, ¿qué significaría una flecha hacia arriba? ¿Las cosas están mejorando o empeorando?
Hemos pasado años preguntando a la gente si una flecha hacia arriba significaba que las cosas estaban mejorando
o empeorando, y casi el 50% de las personas a las que se les preguntó dijo que la flecha hacia arriba significaba
que las cosas estaban empeorando progresivamente, mientras que casi el 50% dijo que una flecha hacia arriba
indicaba que las cosas estaban mejorando. Lo mismo sucede con las flechas izquierda y derecha. Por este motivo,
cuando se utilizan flechas para indicar la dirección, se debe utilizar una tecla. Sin embargo, también hemos
descubierto que esto tampoco funciona. Una vez que el usuario se desplaza más allá de la tecla, la confusión se
produce una vez más.
Generalmente, utilizamos el símbolo de dirección universal de un signo más (+) y menos ()
junto a la calificación de riesgo para indicar la dirección, como se ilustra en la Figura 204.
Observe en la Figura 204 que, aunque el rendimiento del registro de clientes es medio (4),
la dirección es un signo menos (rojo), lo que indica que está empeorando progresivamente
y se dirige hacia un alto riesgo. Por otro lado, observe que la escalabilidad del pago por
catálogo es alta (6) con un signo más (verde), lo que muestra que está mejorando. Las
calificaciones de riesgo sin un signo más o menos indican que el riesgo es estable y no está mejorando.
Ni peor.
Figura 204. Se muestra la dirección del riesgo con signos más y menos
En ocasiones, incluso los signos más y menos pueden resultar confusos para algunas personas.
Otra técnica para indicar la dirección es utilizar una flecha junto con el número de clasificación de
riesgo hacia el que tiende. Esta técnica, como se ilustra en la Figura 205, no requiere una clave
porque la dirección es clara. Además, el uso de colores (flecha roja para peor, flecha verde para
mejor) deja aún más claro hacia dónde se dirige el riesgo.
La dirección del riesgo se puede determinar mediante mediciones continuas a través de las funciones de
aptitud descritas anteriormente en el libro. Al analizar objetivamente cada criterio de riesgo, se pueden
observar tendencias que proporcionan la dirección de cada criterio de riesgo.
Tormenta de riesgo
Ningún arquitecto puede determinar por sí solo el riesgo general de un sistema. Esto se debe a dos razones.
En primer lugar, un solo arquitecto puede pasar por alto un área de riesgo y muy pocos arquitectos tienen
pleno conocimiento de cada parte del sistema. Aquí es donde la tormenta de riesgos puede resultar de ayuda.
La tormenta de riesgos es un ejercicio colaborativo que se utiliza para determinar el riesgo arquitectónico
dentro de una dimensión específica. Las dimensiones comunes (áreas de riesgo) incluyen tecnología no
probada, rendimiento, escalabilidad, disponibilidad (incluidas las dependencias transitivas), pérdida de datos,
puntos únicos de falla y seguridad. Si bien la mayoría de los esfuerzos de tormenta de riesgos involucran a
varios arquitectos, es aconsejable incluir también a desarrolladores sénior y líderes técnicos. No solo
brindarán una perspectiva de implementación del riesgo arquitectónico, sino que involucrar a los
desarrolladores los ayuda a comprender mejor la arquitectura.
El esfuerzo de análisis de riesgos implica tanto una parte individual como una parte colaborativa. En la parte
individual, todos los participantes asignan individualmente (sin colaboración) el riesgo a las áreas de la
arquitectura utilizando la matriz de riesgo descrita en la sección anterior. Esta parte no colaborativa del
análisis de riesgos es esencial para que los participantes no influyan ni desvíen la atención de áreas
particulares de la arquitectura. En la parte colaborativa del análisis de riesgos, todos los participantes trabajan
juntos para llegar a un consenso sobre las áreas de riesgo, analizar el riesgo y formular soluciones para
mitigarlo.
Se utiliza un diagrama de arquitectura para ambas partes del esfuerzo de evaluación de riesgos. Para las
evaluaciones de riesgos holísticas, normalmente se utiliza un diagrama de arquitectura integral, mientras que
para la evaluación de riesgos dentro de áreas específicas de la aplicación se utilizaría un diagrama de
arquitectura contextual. Es responsabilidad del arquitecto que lleva a cabo el esfuerzo de evaluación de
riesgos asegurarse de que estos diagramas estén actualizados y disponibles para todos los participantes.
La Figura 206 muestra un ejemplo de arquitectura que utilizaremos para ilustrar el proceso de asalto de
riesgos. En esta arquitectura, un Elastic Load Balancer se encuentra al frente de cada instancia EC2 que
contiene los servidores web (Nginx) y los servicios de aplicación. Los servicios de aplicación realizan llamadas
a una base de datos MySQL, un caché Redis y una base de datos MongoDB para el registro.
También realizan llamadas a los servidores de expansión Push. Los servidores de expansión, a su vez,
interactúan con la base de datos MySQL, la caché Redis y la función de registro MongoDB.
1. Identificación
2. Consenso
3. Mitigación
Identificación
La actividad de identificación de la evaluación de riesgos implica que cada participante identifique
individualmente las áreas de riesgo dentro de la arquitectura. Los siguientes pasos describen la
parte de identificación de la evaluación de riesgos:
1. El arquitecto que lleva a cabo la tormenta de riesgos envía una invitación a todos los
participantes uno o dos días antes de la parte colaborativa del esfuerzo. La invitación contiene
el diagrama de arquitectura (o la ubicación donde encontrarlo), el riesgo
dimensión de la tormenta (área de riesgo que se analiza para ese esfuerzo de tormenta de
riesgos en particular), la fecha en que se llevará a cabo la parte colaborativa de la tormenta de
riesgos y la ubicación.
2. Utilizando la matriz de riesgos descrita en la primera sección de este capítulo, los participantes
analizan individualmente la arquitectura y clasifican el riesgo como bajo (12), medio (34) o alto
(69).
3. Los participantes preparan pequeñas notas adhesivas con los colores correspondientes (verde,
amarillo y rojo) y escriben el número de riesgo correspondiente (que se encuentra en la matriz de
riesgos).
La mayoría de los esfuerzos de análisis de riesgos solo implican el análisis de una dimensión en
particular (como el rendimiento), pero puede haber ocasiones, debido a la disponibilidad de personal o
problemas de tiempo, en que se analicen múltiples dimensiones dentro de un solo esfuerzo de análisis
de riesgos (como el rendimiento, la escalabilidad y la pérdida de datos). Cuando se analizan múltiples
dimensiones dentro de un solo esfuerzo de análisis de riesgos, los participantes escriben la dimensión
junto al número de riesgo en las notas adhesivas para que todos estén al tanto de la dimensión
específica. Por ejemplo, supongamos que tres participantes encontraron riesgo dentro de la base de datos central.
Los tres identificaron el riesgo como alto (6), pero un participante encontró riesgo con respecto a la
disponibilidad, mientras que dos participantes encontraron riesgo con respecto al rendimiento. Estas
dos dimensiones se analizarán por separado.
Consenso
La actividad de consenso en la iniciativa de tormenta de riesgos es altamente colaborativa y tiene
como objetivo lograr un consenso entre todos los participantes con respecto al riesgo dentro de la
arquitectura. Esta actividad es más eficaz cuando se dispone de una versión impresa grande del
diagrama de arquitectura y se coloca en la pared. En lugar de una versión impresa grande, se puede
mostrar una versión electrónica en una pantalla grande.
Al llegar a la sesión de análisis de riesgos, los participantes comienzan a colocar sus notas adhesivas
en el diagrama de arquitectura en el área donde encontraron riesgos individualmente. Si se utiliza una
versión electrónica, el arquitecto que conduce la sesión de análisis de riesgos pregunta a cada
participante y coloca electrónicamente el riesgo en el diagrama en el área de la arquitectura donde se
identificó el riesgo (consulte la Figura 207).
Una vez que todas las notas adhesivas estén en su lugar, puede comenzar la parte colaborativa de la
evaluación de riesgos. El objetivo de esta actividad de evaluación de riesgos es analizar las áreas de riesgo
en equipo y llegar a un consenso en términos de calificación de riesgo. Observe que se identificaron varias
áreas de riesgo en la arquitectura, ilustradas en la Figura 207:
1. Dos participantes identificaron individualmente el Elastic Load Balancer como de riesgo medio
(3), mientras que un participante lo identificó como de alto riesgo (6).
2. Un participante identificó individualmente los servidores de expansión Push como de alto riesgo.
(9).
3. Tres participantes identificaron individualmente la base de datos MySQL como de riesgo medio.
(3).
6. No se consideró que todas las demás áreas de la arquitectura conllevaran ningún riesgo, por lo que no
No hay notas Postit en ninguna otra área de la arquitectura.
Los puntos 3 y 5 de la lista anterior no necesitan más discusión en esta actividad, ya que todos
los participantes estuvieron de acuerdo con el nivel y la calificación del riesgo. Sin embargo,
observe que hubo una diferencia de opinión en el punto 1 de la lista, y los puntos 2 y 4 solo
tuvieron un participante que identificó el riesgo. Estos puntos deben discutirse durante esta actividad.
El elemento 1 de la lista mostró que dos participantes identificaron individualmente el Elastic Load
Balancer como de riesgo medio (3), mientras que un participante lo identificó como de riesgo alto
(6). En este caso, los otros dos participantes preguntan al tercer participante por qué identificaron
el riesgo como alto. Supongamos que el tercer participante dice que asignó el riesgo como alto
porque si el Elastic Load Balancer deja de funcionar, no se puede acceder a todo el sistema.
Si bien esto es cierto y, de hecho, eleva la calificación de impacto general a alta, los otros dos
participantes convencen al tercer participante de que existe un riesgo bajo de que esto suceda.
Después de mucho debate, el tercer participante está de acuerdo, lo que reduce ese nivel de
riesgo a medio (3). Sin embargo, es posible que el primer y el segundo participante no hayan
visto un aspecto particular del riesgo en Elastic Load Balancer que el tercero sí vio, de ahí la
necesidad de colaboración dentro de esta actividad de análisis de riesgos.
El ejemplo del punto 4 de la lista ilustra por qué es prudente (e importante) incluir a los
desarrolladores en las sesiones de análisis de riesgos. Los desarrolladores no solo pueden
aprender más sobre la arquitectura, sino que el hecho de que un participante (que en este caso
era un desarrollador del equipo) no conociera una tecnología determinada le proporciona al
arquitecto información valiosa sobre el riesgo general.
Este proceso continúa hasta que todos los participantes estén de acuerdo con las áreas de riesgo identificadas.
Una vez que se hayan consolidado todas las notas adhesivas, esta actividad finaliza y puede comenzar la siguiente.
El resultado final de esta actividad se muestra en la Figura 208.
Mitigación
Una vez que todos los participantes están de acuerdo con la calificación de las áreas de riesgo de la arquitectura,
se lleva a cabo la actividad final y más importante: la mitigación de riesgos. La mitigación de riesgos dentro de
una arquitectura generalmente implica cambios o mejoras en ciertas áreas de la arquitectura que, de otro modo,
podrían haberse considerado perfectas tal como estaban.
Esta actividad, que también suele ser colaborativa, busca formas de reducir o eliminar el riesgo identificado en la
primera actividad. Puede haber casos en los que sea necesario cambiar por completo la arquitectura original en
función de la identificación del riesgo, mientras que otros pueden ser una simple refactorización de la arquitectura,
como agregar una cola para la contrapresión para reducir un problema de cuello de botella en el rendimiento.
Independientemente de los cambios necesarios en la arquitectura, esta actividad suele implicar un coste adicional.
Por ese motivo, las partes interesadas clave suelen decidir si el coste supera el riesgo. Por ejemplo, supongamos
que, mediante una sesión de análisis de riesgos, se identificó que la base de datos central presenta un riesgo
medio (4) en relación con la disponibilidad general del sistema. En este caso, los participantes acordaron que
agrupar la base de datos,
En combinación con la división de la base de datos única en bases de datos físicas independientes, se
mitigaría ese riesgo. Sin embargo, aunque el riesgo se reduciría significativamente, esta solución costaría
20.000 dólares. El arquitecto llevaría a cabo una reunión con el principal interesado comercial para analizar
esta compensación. Durante esta negociación, el propietario de la empresa decide que el precio es
demasiado alto y que el costo no compensa el riesgo.
En lugar de darse por vencido, el arquitecto sugiere un enfoque diferente: ¿qué tal si se omite la agrupación
y se divide la base de datos en dos partes? El costo en este caso se reduce a $8000 y se mitiga la mayor
parte del riesgo. En este caso, la parte interesada acepta la solución.
El escenario anterior muestra el impacto que puede tener la tormenta de riesgos no solo en la arquitectura
en general, sino también en las negociaciones entre los arquitectos y las partes interesadas del negocio.
La tormenta de riesgos, combinada con las evaluaciones de riesgos descritas al comienzo de este capítulo,
proporciona un vehículo excelente para identificar y rastrear el riesgo, mejorar la arquitectura y gestionar
las negociaciones entre las partes interesadas clave.
La tormenta de riesgos se puede utilizar para otros aspectos del desarrollo de software además de la
arquitectura. Por ejemplo, hemos aprovechado la tormenta de riesgos para determinar el riesgo general
de finalización de la historia de usuario dentro de una iteración Agile determinada (y, en consecuencia, la
evaluación general del riesgo de esa iteración) durante la preparación de la historia. Mediante el uso de la
matriz de riesgos, el riesgo de la historia de usuario se puede identificar por la primera dimensión (el
impacto general si la historia no se completa dentro de la iteración) y la segunda dimensión (la probabilidad
de que la historia no se complete). Al utilizar la misma matriz de riesgos de arquitectura para las historias,
los equipos pueden identificar historias de alto riesgo, realizar un seguimiento cuidadoso de ellas y priorizarlas.
Para ilustrar el poder de la tormenta de riesgos y cómo puede mejorar la arquitectura general de un
sistema, considere el ejemplo de un sistema de centro de llamadas para apoyar a las enfermeras que
asesoran a los pacientes sobre diversas condiciones de salud. Los requisitos para un sistema de este tipo
son los siguientes:
• El sistema utilizará un motor de diagnóstico de terceros que formula preguntas y orienta a las
enfermeras o pacientes con respecto a sus problemas médicos.
• Los pacientes pueden llamar al centro de llamadas para hablar con una enfermera o elegir utilizar un
sitio web de autoservicio que accede directamente al motor de diagnóstico, sin pasar por el
enfermeras.
• El sistema debe soportar 250 enfermeras simultáneas en todo el país y hasta cientos de miles de
pacientes de autoservicio simultáneos en todo el país.
• Las enfermeras pueden acceder a los registros médicos de los pacientes a través de un sistema de
intercambio de registros médicos, pero los pacientes no pueden
acceder a sus propios registros médicos. • El sistema debe cumplir con la HIPAA en lo que respecta a los
registros médicos. Esto significa que es esencial que nadie más que las enfermeras tenga acceso a los registros médicos.
• Es necesario abordar los brotes y el alto volumen durante la temporada de resfriados y gripe.
el sistema.
• El enrutamiento de llamadas a las enfermeras se basa en el perfil de la enfermera (por ejemplo, las necesidades
bilingües). • El motor de diagnóstico de terceros puede manejar alrededor de 500 solicitudes por segundo.
El arquitecto del sistema creó la arquitectura de alto nivel que se ilustra en la Figura 209. En esta arquitectura hay tres
interfaces de usuario independientes basadas en la web: una para autoservicio, una para enfermeras que reciben
llamadas y una para que el personal administrativo agregue y mantenga el perfil de enfermería y los ajustes de
configuración. La parte del centro de llamadas del sistema consta de un receptor de llamadas que recibe llamadas y un
enrutador de llamadas que dirige las llamadas a la próxima enfermera disponible en función de su perfil (observe cómo
el enrutador de llamadas accede a la base de datos central para obtener información del perfil de la enfermera). En el
centro de esta arquitectura se encuentra una puerta de enlace API del sistema de diagnóstico, que realiza comprobaciones
de seguridad y dirige la solicitud al servicio de backend adecuado.
Figura 209. Ejemplo de arquitectura de alto nivel para un sistema de diagnóstico de enfermería
Este sistema consta de cuatro servicios principales: un servicio de gestión de casos, un servicio de gestión de perfiles de
enfermeras, una interfaz para el intercambio de registros médicos y un motor de diagnóstico externo de terceros. Todas
las comunicaciones utilizan REST, con excepción de los protocolos propietarios con los sistemas externos y los servicios
del centro de llamadas.
El arquitecto ha revisado esta arquitectura en numerosas ocasiones y cree que está lista para su implementación.
A modo de autoevaluación, estudie los requisitos y el diagrama de arquitectura de la Figura 209 e intente determinar
el nivel de riesgo dentro de esta arquitectura en términos de disponibilidad, elasticidad y seguridad. Después de
determinar el nivel de riesgo, determine qué cambios serían necesarios en la arquitectura para mitigar ese riesgo.
Las secciones que siguen contienen escenarios que se pueden utilizar como comparación.
Disponibilidad
Durante el primer ejercicio de análisis de riesgos, el arquitecto decidió centrarse primero en la disponibilidad, ya
que la disponibilidad del sistema es fundamental para el éxito de este. Después de las actividades de identificación
y colaboración del análisis de riesgos, los participantes idearon las siguientes áreas de riesgo utilizando la matriz
de riesgos (como se ilustra en la Figura 2010):
• El uso de una base de datos central se identificó como de alto riesgo (6) debido al alto impacto
(3) y probabilidad media (2).
• La disponibilidad del motor de diagnóstico se identificó como de alto riesgo (9) debido al alto impacto (3) y la
probabilidad desconocida (3). • La disponibilidad del
• Otras partes del sistema no se consideraron como riesgo de disponibilidad debido a las múltiples instancias de
cada servicio y la agrupación del gateway API.
Durante el esfuerzo de evaluación de riesgos, todos los participantes estuvieron de acuerdo en que, si bien las enfermeras pueden
escribir manualmente las notas de los casos si la base de datos deja de funcionar, el enrutador de llamadas no podría funcionar.
ción si la base de datos no estuviera disponible. Para mitigar el riesgo de la base de datos, los participantes
optaron por dividir la única base de datos física en dos bases de datos independientes: una base de datos
agrupada que contenía la información del perfil de la enfermera y una base de datos de instancia única para las
notas del caso. Este cambio de arquitectura no solo abordó las preocupaciones sobre la disponibilidad de la base
de datos, sino que también ayudó a proteger las notas del caso del acceso del administrador. Otra opción para
mitigar este riesgo habría sido almacenar en caché la información del perfil de la enfermera en el enrutador de
llamadas. Sin embargo, debido a que la implementación del enrutador de llamadas era desconocida y podría ser
un producto de terceros, los participantes optaron por el enfoque de la base de datos.
La mitigación del riesgo de disponibilidad de los sistemas externos (motor de diagnóstico e intercambio de
registros médicos) es mucho más difícil de gestionar debido a la falta de control de estos sistemas. Una forma de
mitigar este tipo de riesgo de disponibilidad es investigar si existe un acuerdo de nivel de servicio (SLA) o un
objetivo de nivel de servicio (SLO) publicado para cada uno de estos sistemas. Un SLA suele ser un acuerdo
contractual y es legalmente vinculante, mientras que un SLO no suele serlo. Con base en la investigación, el
arquitecto descubrió que el SLA para el motor de diagnóstico está garantizado con una disponibilidad del 99,99 %
(es decir, 52,60 minutos de inactividad por año) y el intercambio de registros médicos está garantizado con una
disponibilidad del 99,9 % (es decir, 8,77 horas de inactividad por año). Con base en el riesgo relativo, esta
información fue suficiente para eliminar el riesgo identificado.
Los cambios correspondientes a la arquitectura después de esta sesión de análisis de riesgos se ilustran en la
Figura 2011. Observe que ahora se utilizan dos bases de datos y que los acuerdos de nivel de servicio también
se publican en el diagrama de arquitectura.
Elasticidad
Durante la sesión de análisis de riesgos, todos los participantes identificaron la interfaz del motor
de diagnóstico como de alto riesgo (9). Con solo 500 solicitudes por segundo, los participantes
calcularon que no había forma de que la interfaz del motor de diagnóstico pudiera mantener el
ritmo de rendimiento previsto, en particular con la arquitectura actual que utiliza REST como
protocolo de interfaz.
Una forma de mitigar este riesgo es aprovechar las colas asincrónicas (mensajería) entre la
puerta de enlace de API y la interfaz del motor de diagnóstico para proporcionar un punto de
contrapresión si las llamadas al motor de diagnóstico se bloquean. Si bien esta es una buena
práctica, aún no mitiga el riesgo, porque las enfermeras (así como los pacientes de autoservicio)
esperarían demasiado tiempo las respuestas del motor de diagnóstico y esas solicitudes
probablemente se agotarían. Aprovechar lo que se conoce como el Patrón de ambulancia Se
daría a las enfermeras una mayor prioridad sobre el autoservicio. Por lo tanto, se necesitarían
dos canales de mensajes. Si bien esta técnica ayuda a mitigar el riesgo, todavía no resuelve los
tiempos de espera. Los participantes decidieron que, además de la técnica de colas para
proporcionar contrapresión, el almacenamiento en caché de las preguntas de diagnóstico
específicas relacionadas con un brote eliminaría las llamadas por brotes y gripe de tener que
llegar a la interfaz del motor de diagnóstico.
Seguridad
Alentado por los resultados y el éxito de los dos primeros esfuerzos de evaluación de riesgos, el arquitecto decide
realizar una sesión final de evaluación de riesgos sobre otra característica importante de la arquitectura que debe
ser compatible con el sistema para garantizar su éxito: la seguridad.
Debido a los requisitos normativos de la HIPAA, el acceso a los registros médicos a través de la interfaz de
intercambio de registros médicos debe ser seguro, permitiendo que solo las enfermeras accedan a los registros
médicos si es necesario. El arquitecto cree que esto no es un problema debido a los controles de seguridad en la
puerta de enlace API (autenticación y autorización), pero tiene curiosidad por saber si los participantes encuentran
otros elementos de riesgo para la seguridad.
Durante la evaluación de riesgos, todos los participantes identificaron la puerta de enlace de la API del sistema
de diagnóstico como un riesgo de seguridad alto (6). La razón de esta alta calificación fue el alto impacto del
acceso de los pacientes a los registros médicos por parte del personal administrativo o del autoservicio (3)
combinado con una probabilidad media (2). La probabilidad de que se produzca el riesgo no se calificó como alta
debido a los controles de seguridad para cada llamada a la API, pero aun así se calificó como media porque
todas las llamadas (autoservicio, administración y enfermeras) pasan por la misma puerta de enlace de la API. El
arquitecto, que solo calificó el riesgo como bajo (2), se convenció durante la actividad de consenso de la evaluación
de riesgos de que el riesgo era de hecho alto y necesitaba mitigación.
Todos los participantes estuvieron de acuerdo en que tener puertas de enlace API separadas para cada tipo de
usuario (administrador, autoservicio/diagnóstico y enfermeras) evitaría que las llamadas desde la interfaz de
usuario web de administrador o la interfaz de usuario web de autoservicio lleguen a la interfaz de intercambio de
registros médicos. El arquitecto estuvo de acuerdo y creó la arquitectura final, como se ilustra en la Figura 2013.
El escenario anterior ilustra el poder de la tormenta de riesgos. Al colaborar con otros arquitectos,
desarrolladores y partes interesadas clave en las dimensiones de riesgo que son vitales para el éxito
del sistema, se identifican áreas de riesgo que de otro modo habrían pasado desapercibidas.
Compare las figuras 209 y 2013 y observe la diferencia significativa en la arquitectura antes de la
tormenta de riesgos y después de ella. Esos cambios significativos abordan problemas de
disponibilidad, elasticidad y seguridad dentro de la arquitectura.
La prevención de riesgos no es un proceso que se realiza una sola vez, sino que es un proceso continuo a lo largo
de la vida de cualquier sistema para detectar y mitigar las áreas de riesgo antes de que se produzcan en
producción. La frecuencia con la que se lleva a cabo la prevención de riesgos depende de muchos factores, entre
ellos la frecuencia de los cambios, los esfuerzos de refactorización de la arquitectura y el desarrollo incremental de
la arquitectura. Es habitual realizar una prevención de riesgos en alguna dimensión en particular después de añadir
una característica importante o al final de cada iteración.
CAPÍTULO 21
Los arquitectos recién llegados suelen comentar lo sorprendidos que están de lo variado que es el trabajo
más allá de los conocimientos y la experiencia técnicos, que les permitieron pasar al rol de arquitecto en un
principio. En particular, la comunicación eficaz se vuelve fundamental para el éxito de un arquitecto. No
importa cuán brillantes sean las ideas técnicas de un arquitecto, si no puede convencer a los gerentes para
que las financien y a los promotores para que las construyan, su brillantez nunca se manifestará.
Diagramar y presentar arquitecturas son dos habilidades interpersonales fundamentales para los arquitectos.
Si bien existen libros completos sobre cada tema, abordaremos algunos puntos destacados de cada uno.
Estos dos temas aparecen juntos porque tienen algunas características similares: cada uno forma una
representación visual importante de una visión arquitectónica, presentada mediante diferentes medios. Sin
embargo, la coherencia representacional es un concepto que los une.
Al describir visualmente una arquitectura, el creador a menudo debe mostrar diferentes vistas de la misma.
Por ejemplo, el arquitecto probablemente mostrará una descripción general de toda la topología de la
arquitectura y luego profundizará en las partes individuales para ahondar en los detalles del diseño. Sin
embargo, si el arquitecto muestra una parte sin indicar dónde se encuentra dentro de la arquitectura general,
confunde a los espectadores. La coherencia representacional es la práctica de mostrar siempre la relación
entre las partes de una arquitectura, ya sea en diagramas o presentaciones, antes de cambiar de vista.
Por ejemplo, si un arquitecto quisiera describir los detalles de cómo los complementos se relacionan entre sí
en la solución Silicon Sandwiches, la arquitectura mostraría la topología completa y luego profundizaría en la
estructura de los complementos, mostrando a los espectadores la relación entre ellos; un ejemplo de esto
aparece en la Figura 211.
315
Machine Translated by Google
Figura 211. Uso de la coherencia representacional para indicar el contexto en un diagrama más grande
El uso cuidadoso de la coherencia representativa garantiza que los espectadores comprendan el alcance de
los elementos que se presentan, eliminando una fuente común de confusión.
Diagramación
La topología de la arquitectura siempre resulta de interés para los arquitectos y los desarrolladores porque
refleja cómo encaja la estructura y genera una valiosa comprensión compartida por todo el equipo. Por lo
tanto, los arquitectos deben perfeccionar sus habilidades de diagramación hasta lograr una agudeza máxima.
Herramientas
Uno de los beneficios del enfoque de bajo ritual utilizado en el desarrollo de software ágil gira en torno a la creación
de artefactos justo a tiempo, con la menor ceremonia posible (esto ayuda a explicar la dedicación de muchos agilistas
a las fichas y las notas adhesivas).
El uso de herramientas de baja tecnología permite a los miembros del equipo descartar aquello que no está bien, lo
que les da la libertad de experimentar y permitir que la verdadera naturaleza del artefacto emerja a través de la
revisión, la colaboración y la discusión.
La variante favorita de un arquitecto de la foto de una pizarra hecha con un teléfono celular (junto con el
inevitable imperativo de “¡No borrar!”) utiliza una tableta conectada a un retroproyector en lugar de una
pizarra. Esto ofrece varias ventajas. En primer lugar, la tableta tiene un lienzo ilimitado y puede contener
tantos dibujos como un equipo pueda necesitar. En segundo lugar, permite copiar y pegar escenarios
hipotéticos que oscurecen el original cuando se hace en una pizarra. En tercer lugar, las imágenes
capturadas en una tableta ya están digitalizadas y no tienen el inevitable resplandor asociado con las fotos
de pizarras hechas con teléfonos celulares.
Al final, un arquitecto necesita crear diagramas bonitos en una herramienta sofisticada, pero asegurarse de
que el equipo haya iterado el diseño lo suficiente como para invertir tiempo en capturar algo.
Existen herramientas poderosas para crear diagramas en todas las plataformas. Si bien no recomendamos
necesariamente una sobre otra (usamos OmniGraffle con bastante gusto) Para todos los diagramas de
este libro), los arquitectos deberían buscar al menos esta base de características:
Capas
Las herramientas de dibujo suelen admitir capas, algo que los arquitectos deberían aprender a
aprender. Una capa permite que el dibujante vincule un grupo de elementos de forma lógica para
poder ocultar o mostrar capas individuales. Mediante el uso de capas, un arquitecto puede crear un
diagrama completo, pero ocultar detalles abrumadores cuando no son necesarios. El uso de capas
también permite a los arquitectos crear imágenes de forma incremental para presentaciones
posteriores (consulte “Creaciones incrementales” en la página 322).
Diagramación | 317
Machine Translated by Google
Los artefactos dentro de una organización crean consistencia dentro de los diagramas de arquitectura
y permiten al arquitecto construir nuevos diagramas rápidamente.
Imanes
Muchas herramientas de dibujo ofrecen ayuda para dibujar líneas entre formas. Los imanes representan
los lugares de esas formas donde las líneas se conectan automáticamente, lo que proporciona una
alineación automática y otras mejoras visuales. Algunas herramientas permiten al arquitecto agregar
más imanes o crear los suyos propios para personalizar el aspecto de las conexiones dentro de sus
diagramas.
Además de estas funciones útiles específicas, la herramienta debería, por supuesto, admitir líneas, colores
y otros artefactos visuales, así como la capacidad de exportar en una amplia variedad de formatos.
El lenguaje de modelado unificado (UML) fue un estándar que unificó tres filosofías de diseño en competencia
que coexistieron en la década de 1980. Se suponía que era lo mejor de ambos mundos, pero, como muchas
cosas diseñadas por comités, no logró crear mucho impacto fuera de las organizaciones que exigían su uso.
Los arquitectos y desarrolladores todavía utilizan diagramas de clases y secuencias UML para comunicar la
estructura y el flujo de trabajo, pero la mayoría de los otros tipos de diagramas UML han caído en desuso.
C4
C4 es una técnica de diagramación desarrollada por Simon Brown para abordar las deficiencias de UML y
modernizar su enfoque. Las cuatro C de C4 son las siguientes:
Contexto
Representa el contexto completo del sistema, incluidos los roles de los usuarios y las dependencias
externas.
Recipiente
Los límites físicos (y a menudo lógicos) de implementación y los contenedores dentro de la arquitectura.
Esta vista constituye un buen punto de encuentro para operaciones y arquitectos.
Componente
La vista de componentes del sistema; esto se alinea perfectamente con la vista del sistema que tiene
un arquitecto.
La
clase C4 utiliza el mismo estilo de diagramas de clases de UML, que son efectivos, por lo que no es necesario
reemplazarlos.
Si una empresa busca estandarizar una técnica de diagramación, C4 ofrece una buena alternativa. Sin embargo,
como todas las herramientas técnicas de diagramación, presenta la incapacidad de expresar todos los tipos de
diseño que una arquitectura podría llevar a cabo. C4 es más adecuado para arquitecturas monolíticas donde las
relaciones entre los contenedores y los componentes pueden diferir, y es menos adecuado para arquitecturas
distribuidas, como los microservicios.
ArchiMate
ArchiMate es un lenguaje de modelado de The Open Group que ofrece un lenguaje de modelado más liviano
para ecosistemas empresariales. El objetivo de ArchiMate es ser “lo más pequeño posible”, no cubrir todos los
casos extremos. Por eso, se ha convertido en una opción popular entre muchos arquitectos.
diagramas Independientemente de si un arquitecto utiliza su propio lenguaje de modelado o uno de los formales,
debe crear su propio estilo al crear diagramas y sentirse libre de tomar prestadas representaciones que
considere particularmente efectivas. A continuación se presentan algunas pautas generales que se deben
utilizar al crear diagramas técnicos.
Títulos
Asegúrese de que todos los elementos del diagrama tengan títulos o sean bien conocidos por la audiencia.
Utilice la rotación y otros efectos para que los títulos sean “pegajosos” a lo que asocian y para hacer un uso
eficiente del espacio.
Pauta
Las líneas deben ser lo suficientemente gruesas para que se puedan ver bien. Si las líneas indican un flujo de
información, utilice flechas para indicar el tráfico direccional o bidireccional. Los distintos tipos de puntas de
flecha pueden sugerir diferentes semánticas, pero los arquitectos deben ser coherentes.
Generalmente, uno de los pocos estándares que existen en los diagramas de arquitectura es que las líneas
continuas tienden a indicar comunicación sincrónica y las líneas punteadas indican comunicación asincrónica.
Diagramación | 319
Machine Translated by Google
Formas
Si bien todos los lenguajes de modelado formal descritos tienen formas estándar, no existen formas
estándar generalizadas en todo el mundo del desarrollo de software. Por lo tanto, cada arquitecto tiende a
crear su propio conjunto estándar de formas, a veces difundiéndolas en toda la organización para crear un
lenguaje estándar.
Tendemos a utilizar cajas tridimensionales para indicar artefactos desplegables y rectángulos para indicar
portacontenedores, pero no tenemos ninguna clave particular más allá de eso.
Etiquetas
Los arquitectos deben etiquetar cada elemento de un diagrama, especialmente si existe alguna posibilidad
de ambigüedad para los lectores.
Color
Los arquitectos no suelen utilizar el color lo suficiente: durante muchos años, los libros se imprimían
necesariamente en blanco y negro, por lo que los arquitectos y desarrolladores se acostumbraron a los
dibujos monocromáticos. Si bien aún preferimos el monocromo, utilizamos el color cuando ayuda a distinguir
un artefacto de otro. Por ejemplo, cuando analizamos las estrategias de comunicación de microservicios en
“Comunicación” en la página 254, utilizamos el color para indicar que dos microservicios diferentes
participan en la coordinación, no dos instancias del mismo servicio, como se reproduce en la Figura 212.
Claves Si las formas son ambiguas por cualquier motivo, incluya una clave en el diagrama que
indique claramente lo que representa cada forma. No hay nada peor que un diagrama que lleve a
una interpretación errónea, que es peor que no tener diagrama.
Presentación
La otra habilidad blanda que requieren los arquitectos modernos es la capacidad de realizar presentaciones
efectivas utilizando herramientas como PowerPoint y Keynote. Estas herramientas son la lengua franca de
las organizaciones modernas y las personas de toda la organización esperan que se las utilice de manera
competente. Desafortunadamente, a diferencia de los procesadores de texto y las hojas de cálculo, nadie
parece dedicar mucho tiempo a estudiar cómo utilizar bien estas herramientas.
Neal, uno de los coautores de este libro, escribió un libro hace varios años titulado Patrones de presentación .
(AddisonWesley Professional), sobre cómo adoptar el enfoque de patrones/antipatrones común en el
mundo del software y aplicarlo a presentaciones técnicas.
Presentation Patterns hace una observación importante sobre la diferencia fundamental entre crear un
documento y una presentación para defender algo: el tiempo. En una presentación, el presentador controla
la velocidad con la que se desarrolla una idea, mientras que el lector de un documento controla eso. Por lo
tanto, una de las habilidades más importantes que un arquitecto puede aprender en su herramienta de
presentación preferida es cómo manipular el tiempo.
herramientas de presentación ofrecen dos formas de manipular el tiempo en las diapositivas: transiciones
y animaciones. Las transiciones se mueven de una diapositiva a otra, y las animaciones permiten al
diseñador crear movimiento dentro de una diapositiva. Normalmente, las herramientas de presentación
permiten solo una transición por diapositiva, pero una serie de animaciones para cada elemento:
incorporación (aparición), incorporación (desaparición) y acciones (como movimiento, escala y otros comportamientos dinámicos)
Si bien las herramientas ofrecen una variedad de efectos llamativos, como yunques que caen, los arquitectos
usan transiciones y animaciones para ocultar los límites entre diapositivas. Un antipatrón común que se
menciona en Patrones de presentación se llama CookieCutter Establece que las ideas no tienen un número
predeterminado de palabras y, en consecuencia, los diseñadores no deberían rellenar artificialmente el
contenido para que parezca que llena una diapositiva. De manera similar, muchas ideas son más grandes
que una sola diapositiva. El uso de combinaciones sutiles de transiciones y animaciones, como la disolución,
permite a los presentadores ocultar los límites de las diapositivas individuales, uniendo un conjunto de
diapositivas para contar una sola historia. Para indicar el final de una idea, los presentadores deben usar
una transición claramente diferente (como una puerta o un cubo) para proporcionar una pista visual de que
están pasando a un tema diferente.
Presentando | 321
Machine Translated by Google
Construcciones incrementales
El libro Presentation Patterns denuncia el cadáver acribillado a balazos como un patrón antipatrón común de las
presentaciones corporativas, donde cada diapositiva es esencialmente las notas del orador, proyectadas para que
todos las vean. La mayoría de los lectores tienen la experiencia insoportable de ver una diapositiva llena de texto
aparecer durante una presentación, luego leerla entera (porque nadie puede resistirse a leerla entera tan pronto
como aparece), solo para sentarse durante los siguientes 10 minutos mientras el presentador lee lentamente los
puntos a la audiencia. ¡No es de extrañar que tantas presentaciones corporativas sean aburridas!
Al realizar una presentación, el orador tiene dos canales de información: verbal y visual. Al colocar demasiado texto
en las diapositivas y luego decir básicamente las mismas palabras, el presentador sobrecarga un canal de
información y priva al otro de información. La mejor solución a este problema es utilizar presentaciones incrementales
para las diapositivas, creando información (ojalá gráfica) según sea necesario en lugar de hacerlo todo de una vez.
Por ejemplo, supongamos que un arquitecto crea una presentación en la que explica los problemas que supone
utilizar ramificaciones de características y quiere hablar de las consecuencias negativas de mantener activas las
ramificaciones durante demasiado tiempo. Considere la diapositiva gráfica que se muestra en la Figura 213.
Figura 213. Versión incorrecta de una diapositiva que muestra un antipatrón negativo
En la Figura 213, si el presentador muestra la diapositiva completa de inmediato, la audiencia puede ver que algo
malo sucede hacia el final, pero tiene que esperar a que la exposición llegue a ese punto.
En lugar de ello, el arquitecto debería utilizar la misma imagen pero ocultar partes de ella al mostrar la diapositiva
(utilizando un cuadro blanco sin bordes) y exponer una porción a la vez (realizando una construcción en el cuadro
de cobertura), como se muestra en la Figura 214.
En la Figura 214, el presentador aún tiene una oportunidad de mantener vivo algo de suspenso,
haciendo que la charla sea inherentemente más interesante.
Presentando | 323
Machine Translated by Google
Algunos arquitectos crean presentaciones en diapositivas con herramientas como PowerPoint y Keynote, pero
nunca las presentan. En lugar de eso, se envían por correo electrónico como si fueran artículos de revista y
cada individuo las lee a su propio ritmo. Las presentaciones de información son presentaciones en diapositivas
que no están pensadas para proyectarse, sino que resumen la información gráficamente, utilizando básicamente
una herramienta de presentación como un paquete de autoedición.
La diferencia entre estos dos medios es la amplitud del contenido y el uso de transiciones y animaciones. Si
alguien va a hojear las diapositivas como si se tratara de un artículo de revista, el autor de las diapositivas no
necesita agregar ningún elemento de tiempo. La otra diferencia clave entre las diapositivas informativas y las
presentaciones es la cantidad de material.
Dado que las diapositivas informativas están pensadas para ser independientes, contienen toda la información
que el creador desea transmitir. Al hacer una presentación, las diapositivas están pensadas (intencionadamente)
para ser la mitad de la presentación, y la otra mitad es la persona que está allí hablando.
historia Un error común que cometen los presentadores es incluir todo el contenido de la presentación
en diapositivas. Sin embargo, si las diapositivas son exhaustivas, el presentador debe ahorrarles a todos
el tiempo de sentarse a escuchar una presentación y simplemente enviarla por correo electrónico a
todos como una presentación. Los presentadores cometen el error de agregar demasiado material a las
diapositivas cuando pueden presentar puntos importantes de manera más convincente. Recuerde, los
presentadores tienen dos canales de información, por lo que usarlos estratégicamente puede agregar
más impacto al mensaje. Un gran ejemplo de eso es el uso estratégico de la invisibilidad.
Invisibilidad La
invisibilidad es un patrón simple en el que el presentador inserta una diapositiva negra en blanco dentro
de una presentación para volver a centrar la atención únicamente en el orador. Si alguien tiene dos
canales de información (diapositivas y orador) y desactiva uno de ellos (las diapositivas), automáticamente
agrega más énfasis al orador. Por lo tanto, si un presentador quiere hacer hincapié en un punto, inserte
una diapositiva en blanco: todos en la sala centrarán su atención nuevamente en el orador porque ahora
es lo único interesante en la sala para mirar.
Aprender los conceptos básicos de una herramienta de presentación y algunas técnicas para mejorar las
presentaciones es una gran incorporación a las habilidades de los arquitectos. Si un arquitecto tiene una gran
idea pero no puede encontrar una manera de presentarla de manera efectiva, nunca tendrá la oportunidad de
hacer realidad esa visión. La arquitectura requiere colaboración; para conseguir colaboradores, los arquitectos
deben convencer a la gente de que se sume a su visión. Los modernos foros corporativos son herramientas
de presentación, por lo que vale la pena aprender a utilizarlos bien.
CAPÍTULO 22
325
Machine Translated by Google
Los arquitectos que crean demasiadas restricciones forman una caja hermética alrededor de los equipos de
desarrollo, impidiendo el acceso a muchas de las herramientas, bibliotecas y prácticas que se requieren
para implementar el sistema de manera efectiva. Esto causa frustración dentro del equipo, lo que
generalmente hace que los desarrolladores abandonen el proyecto en busca de oportunidades más felices y saludables.
entornos.
También puede ocurrir lo contrario. Un arquitecto de software puede crear restricciones demasiado
laxas (o ninguna restricción en absoluto), dejando todas las decisiones importantes sobre la
arquitectura en manos del equipo de desarrollo. En este escenario, que es tan malo como el de las
restricciones estrictas, el equipo asume básicamente el papel de un arquitecto de software,
realizando pruebas de concepto y luchando por tomar decisiones de diseño sin el nivel adecuado
de orientación, lo que da como resultado improductividad, confusión y frustración.
Existen tres tipos básicos de personalidades de arquitectos: el arquitecto controlador (Figura 222),
el arquitecto de sillón (Figura 223) y el arquitecto eficaz (Figura 225). Cada personalidad coincide
con un tipo de límite particular que se analizó en la sección anterior sobre límites de equipo: los
arquitectos controladores generan límites estrictos, los arquitectos de sillón generan límites laxos y
los arquitectos eficaces generan los tipos de límites adecuados.
326 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
El arquitecto obsesivo del control intenta controlar cada aspecto detallado del proceso de desarrollo de software.
Cada decisión que toma un arquitecto obsesivo del control suele ser demasiado detallada y de bajo nivel, lo que
genera demasiadas restricciones en el proceso de desarrollo.
equipo.
Los arquitectos fanáticos del control producen los límites estrictos discutidos en la sección anterior.
Un arquitecto maniático del control podría restringir al equipo de desarrollo la descarga de bibliotecas de código
abierto o de terceros útiles y, en su lugar, insistir en que los equipos escriban todo desde cero utilizando la API del
lenguaje. Los arquitectos maniáticos del control también podrían imponer restricciones estrictas sobre las
convenciones de nombres, el diseño de clases, la longitud de los métodos, etc. Incluso podrían llegar al punto de
escribir pseudocódigo para los equipos de desarrollo.
En esencia, los arquitectos fanáticos del control roban el arte de la programación a los desarrolladores, lo que
genera frustración y una falta de respeto hacia el arquitecto.
Es muy fácil convertirse en un arquitecto obsesionado con el control, en particular cuando se pasa de desarrollador
a arquitecto. El papel de un arquitecto es crear los bloques de construcción de la aplicación (los componentes) y
determinar las interacciones entre esos componentes. El papel del desarrollador en este esfuerzo es luego tomar
esos componentes y determinar cómo se implementarán utilizando diagramas de clases y patrones de diseño.
Sin embargo, en la transición de desarrollador a arquitecto, es demasiado tentador querer crear también los
diagramas de clases y los patrones de diseño, ya que ese era el rol anterior del recién nombrado arquitecto.
Como veremos en “¿Cuánto control?” en la página 331, a veces un arquitecto necesita desempeñar
el papel de un fanático del control, dependiendo de la complejidad del proyecto y el nivel de habilidad
del equipo. Sin embargo, en la mayoría de los casos, un arquitecto fanático del control interrumpe al
equipo de desarrollo, no proporciona el nivel adecuado de orientación, se interpone en el camino y
es ineficaz a la hora de dirigir al equipo a través de la implementación de la arquitectura.
Arquitecto de sillón
El arquitecto de sillón es el tipo de arquitecto que no ha codificado en mucho tiempo (si es que lo ha
hecho) y no tiene en cuenta los detalles de implementación al crear una arquitectura. Por lo general,
están desconectados de los equipos de desarrollo, nunca
328 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
alrededor, o simplemente pasar de un proyecto a otro una vez que se hayan completado los diagramas de
arquitectura iniciales.
En algunos casos, el arquitecto de sillón simplemente está muy por encima de sus posibilidades en términos
de tecnología o dominio empresarial y, por lo tanto, no puede dirigir ni guiar a los equipos desde el punto de
vista técnico o de problemas comerciales. Por ejemplo, ¿qué hacen los desarrolladores? Pues codifican, por
supuesto. Escribir código de programa es realmente difícil de falsificar; un desarrollador escribe código de
software o no lo hace. Sin embargo, ¿qué hace un arquitecto?
¡Nadie lo sabe! La mayoría de los arquitectos dibujan muchas líneas y recuadros, pero ¿cuán detallados
deben ser los diagramas? Aquí hay un secreto sucio sobre la arquitectura: ¡es muy fácil fingir que eres
arquitecto!
Supongamos que un arquitecto de sillón está muy sobrepasado de sus posibilidades o no tiene tiempo para
diseñar una solución adecuada para un sistema de compraventa de acciones. En ese caso, el diagrama de
arquitectura podría parecerse al que se ilustra en la Figura 224. No hay nada malo con esta arquitectura,
simplemente es de un nivel demasiado alto para ser de alguna utilidad para alguien.
Figura 224. Arquitectura del sistema de comercio creada por un arquitecto de sillón
Los arquitectos de sillón crean límites poco definidos en torno a los equipos de desarrollo, como se explicó
en la sección anterior. En este escenario, los equipos de desarrollo terminan asumiendo el papel de arquitecto,
haciendo básicamente el trabajo que se supone que debe hacer un arquitecto. Como resultado, la velocidad
y la productividad del equipo se ven afectadas y los equipos se confunden sobre cómo debería funcionar el
sistema.
Al igual que el arquitecto maniático del control, es muy fácil convertirse en un arquitecto de sillón. El mayor
indicador de que un arquitecto puede estar cayendo en la personalidad del arquitecto de sillón es no tener
suficiente tiempo para pasar con los equipos de desarrollo que implementan la arquitectura (o elegir no pasar
tiempo con los equipos de desarrollo).
Los equipos de desarrollo necesitan el apoyo y la orientación de un arquitecto, y necesitan que éste esté
disponible para responder a las preguntas técnicas o comerciales que surjan. Otros indicadores de un arquitecto
de sillón son los siguientes:
Arquitecto eficaz
Un arquitecto de software eficaz establece las restricciones y los límites adecuados para el equipo, lo que
garantiza que los miembros del equipo trabajen bien juntos y tengan el nivel adecuado de orientación. El
arquitecto eficaz también se asegura de que el equipo cuente con las herramientas y tecnologías adecuadas y
correctas. Además, elimina cualquier obstáculo que pueda impedir que los equipos de desarrollo alcancen sus
objetivos.
330 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
Aunque esto suene obvio y fácil, no lo es. Hay un arte para convertirse en un líder eficaz en el equipo de
desarrollo. Convertirse en un arquitecto de software eficaz requiere trabajar en estrecha colaboración con el
equipo y ganarse el respeto del equipo también. Veremos otras formas de convertirse en un arquitecto de
software eficaz en capítulos posteriores de esta parte del libro. Pero por ahora, presentaremos algunas pautas
para saber cuánto control debe ejercer un arquitecto eficaz en un equipo de desarrollo.
equipo.
¿Cuánto control?
Para convertirse en un arquitecto de software eficaz es necesario saber cuánto control se debe ejercer sobre
un determinado equipo de desarrollo. Este concepto se conoce como liderazgo elástico . y es ampliamente
difundido por el autor y consultor Roy Osherove. Nos desviaremos un poco del trabajo que Osherove ha
realizado en esta área y nos centraremos en factores específicos de la arquitectura de software.
Para saber en qué medida un arquitecto de software eficaz debe ser un maniático del control y en qué medida
un arquitecto de salón, hay que tener en cuenta cinco factores principales. Estos factores también determinan
cuántos equipos (o proyectos) puede gestionar un arquitecto de software a la vez.
una vez:
Familiaridad del
equipo ¿Qué tan bien se conocen los miembros del equipo? ¿Han trabajado juntos antes en un proyecto?
Por lo general, cuanto mejor se conocen los miembros del equipo, menos control se necesita porque los
miembros del equipo comienzan a autoorganizarse.
Por el contrario, cuanto más nuevos sean los miembros del equipo, más control se necesitará para
ayudar a facilitar la colaboración entre los miembros del equipo y reducir las camarillas dentro del equipo.
¿Qué tan grande es el equipo? (Consideramos que más de 12 desarrolladores en el mismo equipo son
un equipo grande y 4 o menos son un equipo pequeño). Cuanto más grande es el equipo, más control se
necesita. Cuanto más pequeño es el equipo, menos control se necesita. Esto se analiza con más detalle
en “Señales de advertencia del equipo” en la página 335.
Experiencia general
¿Cuántos miembros del equipo son senior? ¿Cuántos son junior? ¿Es un equipo mixto de desarrolladores
junior y senior? ¿Qué tan bien conocen la tecnología y el dominio comercial? Los equipos con muchos
desarrolladores junior requieren más control y tutoría, mientras que los equipos con más desarrolladores
senior requieren menos control. En estos últimos casos, el arquitecto pasa del rol de mentor al de
facilitador.
Complejidad del
proyecto ¿El proyecto es muy complejo o se trata simplemente de un sitio web? Los proyectos muy
complejos requieren que el arquitecto esté más disponible para el equipo y ayude con los problemas
que surgen, por lo que se necesita más control en el equipo. Los proyectos relativamente
simples son sencillos y, por lo tanto, no requieren mucho control.
Duración del
proyecto ¿El proyecto es de duración corta (dos meses), larga (dos años) o media (seis
meses)? Cuanto más corta sea la duración, menos control se necesita; por el contrario,
cuanto más largo sea el proyecto, más control se necesita.
Aunque la mayoría de los factores tienen sentido en relación con un mayor o menor control, el
factor de duración del proyecto puede no parecerlo. Como se indica en la lista anterior, cuanto
más corta sea la duración del proyecto, menos control se necesita; cuanto más larga sea la
duración del proyecto, más control se necesita. Intuitivamente, esto podría parecer al revés, pero
no es así. Consideremos un proyecto rápido de dos meses. Dos meses no es mucho tiempo para
calificar los requisitos, experimentar, desarrollar el código, probar cada escenario y lanzarlo a
producción. En este caso, el arquitecto debería actuar más como un arquitecto de sillón, ya que el
equipo de desarrollo ya tiene un agudo sentido de urgencia. Un arquitecto maniático del control
solo se interpondría y probablemente retrasaría el proyecto. Por el contrario, piense en una
duración del proyecto de dos años. En este escenario, los desarrolladores están relajados, no
piensan en términos de urgencia y probablemente planifiquen vacaciones y tomen almuerzos
largos. El arquitecto necesita más control para garantizar que el proyecto avance de manera
oportuna y que las tareas complejas se realicen primero.
Es habitual que en la mayoría de los proyectos se utilicen estos factores para determinar el nivel
de control al comienzo de un proyecto; pero a medida que el sistema continúa evolucionando, el
nivel de control cambia. Por lo tanto, recomendamos que estos factores se analicen continuamente
durante todo el ciclo de vida de un proyecto para determinar cuánto control se debe ejercer sobre
el equipo de desarrollo.
Para ilustrar cómo se puede utilizar cada uno de estos factores para determinar el nivel de control que
debe tener un arquitecto sobre un equipo, supongamos una escala fija de 20 puntos para cada factor.
Los valores negativos apuntan más a ser un arquitecto de sillón (menos control y participación),
mientras que los valores positivos apuntan más a ser un arquitecto obsesivo del control (más
control y participación). Esta escala se ilustra en la Figura 226.
332 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
La aplicación de este tipo de escala no es exacta, por supuesto, pero ayuda a determinar
el control relativo que se ejerce sobre un equipo. Por ejemplo, considere el escenario del proyecto
se muestra en la Tabla 221 y la Figura 227. Como se muestra en la tabla, los factores apuntan a
O bien un maniático del control (+20) o un arquitecto de sillón (20). Estos factores se suman y
con una puntuación acumulada de 60, lo que indica que el arquitecto debería jugar un papel más importante.
desempeñar el papel de arquitecto de sillón y no estorbar al equipo.
Familiaridad del equipo Nuevos miembros del equipo +20 Obsesionado con el control
En el escenario 1, todos estos factores se tienen en cuenta para demostrar que un sistema eficaz
334 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
Es difícil objetivar estos factores, ya que algunos de ellos (como la experiencia general del equipo)
pueden tener más peso que otros. En estos casos, las métricas se pueden ponderar o modificar
fácilmente para adaptarse a cualquier escenario o condición en particular. En cualquier caso, el
mensaje principal aquí es que la cantidad de control y participación que tiene un arquitecto de
software en el equipo varía según estos cinco factores principales y que al tenerlos en cuenta, un
arquitecto puede evaluar qué tipo de control ejercer sobre el equipo y cómo debe ser el marco en el
que los equipos de desarrollo pueden trabajar (límites y restricciones estrictos o laxos).
Como se indicó en la sección anterior, el tamaño del equipo es uno de los factores que influyen en
el grado de control que debe ejercer un arquitecto sobre un equipo de desarrollo. Cuanto más
grande sea el equipo, más control necesitará; cuanto más pequeño, menos control necesitará. Hay
tres factores que entran en juego a la hora de considerar el tamaño más eficaz del equipo de desarrollo:
• Pérdida de proceso
• Ignorancia pluralista •
Difusión de la responsabilidad
Pérdida de proceso, también conocida como ley de Brooks, El término fue acuñado originalmente
por Fred Brooks en su libro The Mythical Man Month (AddisonWesley). La idea básica de la pérdida
de proceso es que cuantas más personas se incorporen a un proyecto, más tiempo llevará el
proyecto. Como se ilustra en la Figura 229, el potencial del grupo se define por los esfuerzos
colectivos de todos los miembros del equipo. Sin embargo, en cualquier equipo, la productividad
real siempre será menor que el potencial del grupo, siendo la diferencia la pérdida de proceso del equipo.
Figura 229. El tamaño del equipo afecta la productividad real (ley de Brook)
La ignorancia pluralista también ocurre cuando el tamaño del equipo se vuelve demasiado grande.
La ignorancia pluralista es cuando todos están de acuerdo con una norma (pero la rechazan en
privado) porque creen que están pasando por alto algo obvio. Por ejemplo, supongamos que en un
equipo grande la mayoría está de acuerdo en que usar mensajería entre dos servicios remotos es la
mejor solución. Sin embargo, una persona en el equipo piensa que es una idea tonta debido a un
firewall seguro entre los dos servicios. Sin embargo, en lugar de decir lo que piensa, esa persona
también está de acuerdo con el uso de mensajería (pero rechaza la idea en privado) porque teme
estar pasando por alto algo obvio o teme que puedan considerarla tonta si lo hiciera. En este caso, la
persona que rechaza la norma tenía razón: la mensajería no funcionaría debido a un firewall seguro
entre los dos servicios remotos. Si hubiera dicho lo que pensaba (y si el tamaño del equipo hubiera
sido menor), se habría cuestionado la solución original y se habría utilizado otro protocolo (como
REST) en su lugar, que sería una mejor solución en este caso.
El concepto de ignorancia pluralista se hizo famoso gracias al cuento infantil danés “El traje nuevo del
emperador”. de Hans Christian Andersen. En la historia, el rey está convencido de que su nueva ropa es
invisible para cualquier persona que no sea digna de verla.
Se pasea totalmente desnudo y pregunta a todos sus sujetos qué les parece su nueva ropa.
Todos los súbditos, temerosos de ser considerados estúpidos o indignos, responden al rey.
336 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
que su nueva ropa es lo mejor que le ha pasado. Esta locura continúa hasta que un niño finalmente le
grita al rey que no lleva ninguna ropa puesta.
Un arquitecto de software eficaz debería observar continuamente las expresiones faciales y el lenguaje
corporal durante cualquier tipo de reunión o debate colaborativo y actuar como facilitador si percibe que
se da un caso de ignorancia pluralista. En este caso, el arquitecto eficaz podría interrumpir y preguntar
a la persona qué piensa sobre la solución propuesta y estar de su lado y apoyarla cuando hable.
El tercer factor que indica el tamaño adecuado del equipo se denomina difusión de la responsabilidad.
La difusión de la responsabilidad se basa en el hecho de que, a medida que aumenta el tamaño del
equipo, tiene un impacto negativo en la comunicación. La confusión sobre quién es responsable de qué
en el equipo y el abandono de tareas son buenas señales de que el equipo es demasiado grande.
Esta imagen muestra a alguien de pie junto a un coche averiado al costado de una pequeña carretera
rural. En este escenario, ¿cuántas personas podrían detenerse y preguntarle al automovilista si todo
está bien? Debido a que es una carretera pequeña en una comunidad pequeña, probablemente todos
los que pasan por allí lo harían. Sin embargo, ¿cuántas veces los automovilistas se han quedado
atrapados al costado de una autopista concurrida en medio de una gran ciudad y miles de autos
simplemente han pasado sin que nadie se detenga y les pregunte si todo está bien? Todo el tiempo.
Este es un buen ejemplo de la difusión de la responsabilidad. A medida que las ciudades se vuelven
más concurridas y concurridas, la gente asume que el automovilista ya ha llamado o que la ayuda está
en camino debido a la gran cantidad de personas que presencian el evento. Sin embargo, en la mayoría
de estos casos, la ayuda no está en camino y el automovilista se queda atrapado con un teléfono
celular sin batería u olvidado, sin poder pedir ayuda.
Un arquitecto eficaz no solo ayuda a guiar al equipo de desarrollo a través de la implementación de la arquitectura,
sino que también garantiza que el equipo esté sano, feliz y trabajando en conjunto para lograr un objetivo común.
Buscar estas tres señales de advertencia y, en consecuencia, ayudar a corregirlas ayuda a garantizar un desarrollo
eficaz.
equipo.
Los pilotos de las aerolíneas utilizan listas de verificación en cada vuelo, incluso los pilotos más experimentados y
veteranos. Los pilotos tienen listas de verificación para el despegue, el aterrizaje y miles de otras situaciones,
tanto comunes como casos extremos inusuales. Utilizan listas de verificación porque un error en un ajuste de la
aeronave (como colocar los flaps a 10 grados) o en un procedimiento (como obtener autorización para ingresar a
un área de control de terminal) puede significar la diferencia entre un vuelo seguro y uno desastroso.
El Dr. Atul Gawande escribió un excelente libro llamado El Manifiesto de la Lista de Verificación (Picador), en el
que describe el poder de las listas de verificación para los procedimientos quirúrgicos. Alarmado por la alta tasa
de infecciones por estafilococos en los hospitales, el Dr. Gawande creó listas de verificación quirúrgicas para
intentar reducir esta tasa. En el libro, demuestra que las tasas de infección por estafilococos en los hospitales que
utilizan las listas de verificación se redujeron a casi cero, mientras que las tasas de infección por estafilococos en
los hospitales de control que no utilizan las listas de verificación siguieron aumentando.
Las listas de verificación funcionan. Son un vehículo excelente para asegurarse de que todo esté cubierto y
abordado. Si las listas de verificación funcionan tan bien, ¿por qué la industria del desarrollo de software no las
aprovecha? Creemos firmemente, por experiencia personal, que las listas de verificación marcan una gran
diferencia en la eficacia de los equipos de desarrollo. Sin embargo, esta afirmación tiene sus salvedades. En
primer lugar, la mayoría de los desarrolladores de software no vuelan en aviones comerciales ni realizan cirugías
a corazón abierto. En otras palabras, los desarrolladores de software no necesitan listas de verificación para todo.
La clave para que los equipos sean eficaces es saber cuándo aprovechar las listas de verificación y cuándo no.
338 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
Considere la lista de verificación que se muestra en la Figura 2211 para crear una nueva tabla de base de datos.
No se trata de una lista de verificación, sino de un conjunto de pasos de procedimiento y, como tal, no debería estar en una lista
de verificación. Por ejemplo, no se puede verificar la tabla de la base de datos si aún no se ha enviado el formulario. Los procesos
que tienen un flujo de procedimiento de tareas dependientes no deberían estar en una lista de verificación. Los procesos simples
y conocidos que se ejecutan con frecuencia sin errores tampoco necesitan una lista de verificación.
Los procesos que son buenos candidatos para las listas de verificación son aquellos que no tienen ningún orden de procedimiento
o tareas dependientes, así como aquellos que tienden a ser propensos a errores o tienen pasos que se omiten o se pasan por
alto con frecuencia. La clave para que las listas de verificación sean efectivas es no exagerar al convertir todo en una lista de
verificación. Los arquitectos descubren que las listas de verificación, de hecho, hacen que los equipos de desarrollo sean más
efectivos y, como tal, comienzan a convertir todo en una lista de verificación, invocando lo que se conoce como la ley de los
rendimientos decrecientes. Cuantas más listas de verificación cree un arquitecto, menos posibilidades habrá de que los
desarrolladores las utilicen. Otro factor clave de éxito al crear listas de verificación es hacerlas lo más pequeñas posible, pero que
al mismo tiempo capturen todos los pasos necesarios dentro de un proceso. Los desarrolladores generalmente no seguirán listas
de verificación que sean demasiado grandes. Busque elementos que se puedan realizar a través de la automatización y elimínelos
de la lista de verificación.
Tres listas de verificación clave que consideramos más efectivas son una lista de verificación de finalización de código para
desarrolladores, una lista de verificación de pruebas unitarias y funcionales, y una lista de verificación de lanzamiento de software.
El efecto Hawthorne
Uno de los problemas asociados con la introducción de listas de verificación en un equipo de desarrollo es
lograr que los desarrolladores las utilicen. Es muy común que algunos desarrolladores se queden sin tiempo
y simplemente marquen todos los elementos de una lista de verificación en particular como completados
sin haber realizado realmente las tareas.
Una de las formas de abordar este problema es hablar con el equipo sobre la importancia de usar listas de
verificación y cómo estas pueden marcar la diferencia en el equipo. Pida a los miembros del equipo que
lean The Checklist Manifesto de Atul Gawande para comprender completamente el poder de una lista de
verificación y asegúrese de que cada miembro del equipo comprenda el razonamiento detrás de cada lista
de verificación y por qué se usa. También ayuda que los desarrolladores colaboren en lo que debe y no
debe incluirse en una lista de verificación.
Cuando todo lo demás falla, los arquitectos pueden invocar lo que se conoce como el efecto Hawthorne. El
efecto Hawthorne significa básicamente que si las personas saben que están siendo observadas o
monitoreadas, su comportamiento cambia y, en general, harán lo correcto. Algunos ejemplos incluyen
cámaras muy visibles dentro y alrededor de los edificios que en realidad no funcionan o que en realidad no
graban nada (¡esto es muy común!) y software de monitoreo de sitios web (¿cuántos de esos informes se
ven realmente?).
El efecto Hawthorne también se puede utilizar para regular el uso de listas de verificación. Un arquitecto
puede hacer saber al equipo que el uso de listas de verificación es fundamental para la eficacia del equipo
y, como resultado, se verificarán todas las listas de verificación para asegurarse de que la tarea se haya
realizado realmente, cuando en realidad el arquitecto solo revisa ocasionalmente las listas de verificación
para comprobar su exactitud. Al aprovechar el efecto Hawthorne, los desarrolladores tendrán muchas
menos probabilidades de omitir elementos o marcarlos como completados cuando, en realidad, la tarea no se realizó.
desarrollador La lista de verificación para completar el código del desarrollador es una herramienta
eficaz, en particular cuando un desarrollador de software afirma que ya “terminó” con el código. También
es útil para definir lo que se conoce como la “definición de terminado”. Si se completa todo lo que figura
en la lista de verificación, entonces el desarrollador puede afirmar que realmente terminó con el código.
Estas son algunas de las cosas que se deben incluir en una lista de verificación de finalización de código para desarrolladores:
pasan por alto con frecuencia (como excepciones absorbidas) • Estándares específicos del
340 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
La figura 2212 ilustra un ejemplo de una lista de verificación de finalización de código para desarrollador.
Figura 2212. Ejemplo de una lista de verificación para completar el código del desarrollador
Observe las tareas obvias “Ejecutar limpieza y formateo de código” y “Asegurarse de que no haya excepciones absorbidas” en la
lista de verificación. ¿Cuántas veces un desarrollador ha estado apurado, ya sea al final del día o al final de una iteración, y se
ha olvidado de ejecutar la limpieza y el formateo de código desde el IDE? Muchas veces. En The Checklist Manifesto, Gawande
encontró este mismo fenómeno con respecto a los procedimientos quirúrgicos: los obvios eran a menudo los que se pasaban por
alto.
Tenga en cuenta también las tareas específicas del proyecto en los elementos 2, 3, 6 y 7. Si bien estos son buenos elementos
para tener en una lista de verificación, un arquitecto siempre debe revisar la lista de verificación para ver si algún elemento se
puede automatizar o escribir como complemento para un verificador de validación de código. Por ejemplo, si bien "Incluir
@ServiceEntrypoint en la clase de API de servicio" podría no tener una verificación automatizada, la "Verificar que solo los
métodos públicos están llamando a setFailure()" ciertamente puede (esta es una verificación automatizada sencilla con cualquier
tipo de herramienta de rastreo de código). Verificar las áreas de automatización ayuda a reducir tanto el tamaño como el ruido
de las listas de verificación más efectivas es la lista de verificación de pruebas unitarias y funcionales.
Esta lista de verificación contiene algunas de las pruebas más inusuales y de casos extremos que los desarrolladores de software
tienden a olvidar probar. Siempre que alguien de control de calidad encuentre un problema con el código en función de un caso
de prueba en particular, dicho caso de prueba debe agregarse a esta lista de verificación.
Esta lista de verificación en particular suele ser una de las más extensas debido a todos los tipos de pruebas que se pueden
ejecutar en el código. El propósito de esta lista de verificación es garantizar la codificación más completa posible para que
cuando el desarrollador haya terminado con la lista de verificación, el código esté esencialmente listo para producción.
A continuación se muestran algunos de los elementos que se encuentran en una lista de verificación típica de pruebas unitarias y funcionales:
• Campos faltantes
Al igual que la lista de verificación de finalización del código del desarrollador, cualquier elemento que pueda
escribirse como prueba automatizada debe eliminarse de la lista de verificación. Por ejemplo, supongamos que
hay un elemento en la lista de verificación para una aplicación de compraventa de acciones para probar acciones
negativas (como una COMPRA por 1000 acciones de Apple [AAPL]). Si esta verificación se automatiza a través
de una prueba unitaria o funcional dentro del conjunto de pruebas, entonces el elemento debe eliminarse de la
lista de verificación.
A veces, los desarrolladores no saben por dónde empezar a la hora de escribir pruebas unitarias o cuántas
pruebas unitarias escribir. Esta lista de verificación proporciona una forma de asegurarse de que se incluyan
escenarios de prueba generales o específicos en el proceso de desarrollo del software. Esta lista de verificación
también es eficaz para cerrar la brecha entre desarrolladores y evaluadores en entornos en los que estas
actividades las realizan equipos separados. Cuantos más equipos de desarrollo realicen pruebas completas, más
fácil será el trabajo de los equipos de prueba, lo que les permitirá centrarse en determinados escenarios
empresariales que no se cubren en las listas de verificación.
El lanzamiento de software a producción es quizás uno de los aspectos más propensos a errores del ciclo de vida
del desarrollo de software y, por lo tanto, constituye una excelente lista de verificación. Esta lista de verificación
ayuda a evitar compilaciones e implementaciones fallidas y reduce significativamente la cantidad de riesgo
asociado con el lanzamiento de software.
La lista de verificación de lanzamiento de software suele ser la más volátil de todas, ya que cambia continuamente
para abordar nuevos errores y circunstancias cada vez que una implementación falla o tiene problemas.
A continuación se muestran algunos de los elementos que normalmente se incluyen en la lista de verificación de lanzamiento de software:
342 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
Cada vez que falla una compilación o una implementación, el arquitecto debe analizar la causa raíz del
error y agregar una entrada correspondiente a la lista de verificación de la versión de software. De esta
manera, el elemento se verificará en la próxima compilación o implementación, lo que evitará que ese
problema vuelva a ocurrir.
Proporcionar orientación
Un arquitecto de software también puede hacer que los equipos sean eficaces al brindar orientación
mediante el uso de principios de diseño. Esto también ayuda a formar el marco (restricciones), como se
describe en la primera sección de este capítulo, en el que los desarrolladores pueden trabajar para
implementar la arquitectura. Comunicar eficazmente estos principios de diseño es una de las claves para
crear un equipo exitoso.
Para ilustrar este punto, considere brindar orientación a un equipo de desarrollo sobre el uso de lo que generalmente se
denomina pila en capas: la colección de bibliotecas de terceros (como archivos JAR y DLL) que componen la aplicación. Los
equipos de desarrollo suelen tener muchas preguntas sobre la pila en capas, incluidas si pueden tomar sus propias
decisiones sobre varias bibliotecas, cuáles son adecuadas y cuáles no.
Usando este ejemplo, un arquitecto de software eficaz puede brindar orientación al equipo de desarrollo
pidiendo primero al desarrollador que responda las siguientes preguntas:
La primera pregunta lleva a los desarrolladores a examinar las bibliotecas existentes para ver si la
funcionalidad que ofrece la nueva biblioteca se puede satisfacer mediante una biblioteca o una
funcionalidad existente. Según nuestra experiencia, a veces los desarrolladores ignoran esta actividad y
crean una gran cantidad de funcionalidad duplicada, en particular en proyectos grandes con equipos
numerosos.
La segunda pregunta lleva al desarrollador a preguntarse por qué la nueva biblioteca o funcionalidad es
realmente necesaria. En este caso, un arquitecto de software eficaz pedirá una justificación tanto técnica
como comercial de por qué se necesita la biblioteca adicional. Esta puede ser una técnica eficaz para
crear conciencia dentro del equipo de desarrollo sobre la necesidad de justificaciones comerciales.
Como posdata, los dos desarrolladores clave permanecieron en el proyecto hasta el final.
344 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
Propósito especial
Son bibliotecas específicas que se utilizan para cosas como representación de PDF, escaneo de
códigos de barras y circunstancias que no justifican la escritura de software personalizado.
Propósito general
Estas bibliotecas son envoltorios sobre la API del lenguaje e incluyen cosas como Apache Commons
y Guava para Java.
Estructura
Estas bibliotecas se utilizan para tareas como la persistencia (como Hibernate) y la inversión de
control (como Spring). En otras palabras, estas bibliotecas conforman una capa o estructura completa
de la aplicación y son altamente invasivas.
Una vez categorizado (las categorías anteriores son solo un ejemplo; puede haber muchas más definidas),
el arquitecto crea el cuadro alrededor de este principio de diseño. Observe en el ejemplo ilustrado en la
Figura 2213 que para esta aplicación o proyecto en particular, el arquitecto ha especificado que para las
bibliotecas de propósito especial, el desarrollador
Resumen
Lograr que los equipos de desarrollo sean eficaces es una tarea ardua. Requiere mucha experiencia
y práctica, así como sólidas habilidades interpersonales (que analizaremos en los capítulos siguientes
de este libro). Dicho esto, las técnicas sencillas que se describen en este capítulo sobre liderazgo
flexible, uso de listas de verificación y orientación mediante la comunicación eficaz de los principios
de diseño funcionan de hecho y han demostrado ser eficaces para lograr que los equipos de
desarrollo trabajen de forma más inteligente y eficaz.
Se podría cuestionar el papel de un arquitecto para tales actividades, y en su lugar asignar el esfuerzo
de hacer que los equipos sean efectivos al gerente de desarrollo o al gerente de proyecto. Estamos
totalmente en desacuerdo con esta premisa. Un arquitecto de software no solo proporciona orientación
técnica al equipo, sino que también lo dirige a través de la implementación de la arquitectura. La
estrecha relación de colaboración entre un arquitecto de software y un equipo de desarrollo le permite
al arquitecto observar la dinámica del equipo y, por lo tanto, facilitar los cambios para que el equipo
sea más efectivo. Esto es exactamente lo que diferencia a un arquitecto técnico de un arquitecto de
software efectivo.
346 | Capítulo 22: Cómo hacer que los equipos sean efectivos
Machine Translated by Google
CAPÍTULO 23
Las habilidades de negociación y liderazgo son difíciles de adquirir. Se necesitan muchos años de
aprendizaje, práctica y experiencias de “lecciones aprendidas” para adquirir las habilidades necesarias
para convertirse en un arquitecto de software eficaz. Sabiendo que este libro no puede convertir a un
arquitecto en un experto en negociación y liderazgo de la noche a la mañana, las técnicas presentadas
en este capítulo proporcionan un buen punto de partida para adquirir estas importantes habilidades.
Negociación y facilitación
Al principio de este libro, enumeramos las expectativas básicas de un arquitecto, siendo la última la
expectativa de que un arquitecto de software debe comprender el clima político de la empresa y ser
capaz de navegar en la política. La razón de esta expectativa clave es que casi todas las decisiones que
toma un arquitecto de software serán cuestionadas. Las decisiones serán cuestionadas por los
desarrolladores que piensan que saben más que el arquitecto y, por lo tanto, tienen un mejor enfoque.
Las decisiones serán cuestionadas por otros arquitectos dentro de la organización que piensan que
tienen una mejor idea o forma de abordar el problema. Finalmente, las decisiones serán cuestionadas
por las partes interesadas que argumentarán que la decisión es demasiado costosa o llevará demasiado
tiempo.
La negociación es una de las habilidades más importantes que puede tener un arquitecto de software.
Los arquitectos de software eficaces comprenden la política de la organización, tienen una sólida
347
Machine Translated by Google
habilidades de negociación y facilitación, y pueden superar desacuerdos cuando ocurren para crear
soluciones en las que estén de acuerdo todas las partes interesadas.
Considere el siguiente escenario del mundo real (escenario 1) que involucra a un actor comercial clave y un
arquitecto líder:
Escenario 1
El patrocinador del proyecto, vicepresidente sénior, insiste en que el nuevo sistema comercial debe
admitir cinco nueves de disponibilidad (99,999 %). Sin embargo, el arquitecto principal está convencido,
basándose en investigaciones, cálculos y conocimientos del dominio empresarial y la tecnología, de
que tres nueves de disponibilidad (99,9 %) serían suficientes. El problema es que al patrocinador del
proyecto no le gusta equivocarse ni que le corrijan y realmente odia a las personas que son
condescendientes. El patrocinador no es demasiado técnico (pero cree que lo es) y, como resultado,
tiende a involucrarse en los aspectos no funcionales de los proyectos. El arquitecto debe convencer al
patrocinador del proyecto a través de la negociación de que tres nueves (99,9 %) de disponibilidad
serían suficientes.
En este tipo de negociación, el arquitecto de software debe tener cuidado de no ser demasiado egoísta y
enérgico en su análisis, pero también asegurarse de no pasar por alto nada que pueda demostrar que está
equivocado durante la negociación. Hay varias técnicas de negociación clave que un arquitecto puede
utilizar para ayudar con este tipo de negociación con las partes interesadas.
Frases como “debemos tener cero tiempo de inactividad” y “necesitaba esas características ayer”
generalmente no tienen sentido, pero sin embargo proporcionan información valiosa al arquitecto que está
a punto de iniciar una negociación. Por ejemplo, cuando se le pregunta al patrocinador del proyecto cuándo
se necesita una característica en particular y responde “la necesitaba ayer”, eso es una indicación para el
arquitecto de software de que el tiempo de comercialización es importante para esa parte interesada. De
manera similar, la frase “este sistema debe ser increíblemente rápido” significa que el rendimiento es una
gran preocupación. La frase “cero tiempo de inactividad” significa que la disponibilidad es crítica en la
aplicación. Un arquitecto de software eficaz aprovechará este tipo de gramática sin sentido para comprender
mejor las preocupaciones reales y, en consecuencia, aprovechará ese uso de la gramática durante una
negociación.
Consideremos el escenario 1 descrito anteriormente. En este caso, el patrocinador clave del proyecto quiere
cinco nueves de disponibilidad. El uso de esta técnica le indica al arquitecto que la disponibilidad es muy
importante. Esto conduce a una segunda técnica de negociación:
La frase “cinco nueves” es una expresión gramatical que indica alta disponibilidad. Sin embargo, ¿qué
son exactamente los cinco nueves de disponibilidad? Si se investiga esto con anticipación y se reúnen
los conocimientos antes de la negociación, se obtiene la información que se muestra en la Tabla 231.
(por
El escenario de negociación 1 incluiría validar las inquietudes de las partes interesadas ("Entiendo que la
disponibilidad es muy importante para este sistema") y luego llevar la negociación del lenguaje sencillo a
uno de horas y minutos razonables.
Tiempo de inactividad no planificado. Tres nueves (que el arquitecto consideró suficiente) promedian 86
segundos de tiempo de inactividad no planificado por día, ciertamente una cantidad razonable dado el
contexto del sistema de comercio global descrito en el escenario. El arquitecto siempre puede recurrir a
este consejo:
Cuando todo lo demás falla, plantee las cosas en términos de costo y tiempo.
Recomendamos dejar esta táctica de negociación para el final. Hemos visto demasiadas negociaciones
que comienzan con el pie izquierdo debido a declaraciones iniciales como: "Eso va a costar mucho
dinero" o "No tenemos tiempo para eso". El dinero y el tiempo (esfuerzo)
Las justificaciones y racionalizaciones implicadas son sin duda factores clave en cualquier negociación, pero deberían
utilizarse como último recurso para que se puedan intentar primero otras justificaciones y racionalizaciones más importantes.
Una vez que se llega a un acuerdo, se pueden considerar el costo y el tiempo si son atributos
importantes para la negociación.
El antiguo guerrero chino Sun Tzu escribió en El arte de la guerra: “Si sus fuerzas están unidas,
sepárelas”. Esta misma táctica de dividir y vencer también puede ser aplicada por un arquitecto
durante las negociaciones. Consideremos el escenario 1 descrito anteriormente. En este caso, el
patrocinador del proyecto insiste en una disponibilidad de cinco nueves (99,999 %) para el nuevo
sistema comercial. Sin embargo, ¿necesita todo el sistema cinco nueves de disponibilidad?
Calificar el requisito para el área específica del sistema que realmente requiere cinco nueves de
disponibilidad reduce el alcance de requisitos difíciles (y costosos) y también el alcance de la
negociación.
Escenario 2
El arquitecto principal de un proyecto cree que la mensajería asincrónica sería el enfoque
adecuado para la comunicación entre un grupo de servicios con el fin de aumentar tanto el
rendimiento como la escalabilidad. Sin embargo, el otro arquitecto del proyecto vuelve a estar
en total desacuerdo e insiste en que REST sería una mejor opción, porque REST siempre es
más rápido que la mensajería y puede escalar igual de bien (“¡Compruébelo usted mismo
buscándolo en Google!”). Este no es el primer debate acalorado entre los dos arquitectos, ni
será el último. El arquitecto principal debe convencer al otro arquitecto de que la mensajería
es la solución adecuada.
En este escenario, el arquitecto principal ciertamente puede decirle al otro arquitecto que su
opinión no importa e ignorarla basándose en su antigüedad en el proyecto.
Sin embargo, esto solo generará más animosidad entre los dos arquitectos y creará una relación
poco saludable y no colaborativa, lo que, en consecuencia, terminará teniendo un impacto negativo
en el equipo de desarrollo. La siguiente técnica ayudará en este tipo de situaciones:
En lugar de discutir con otro arquitecto sobre el uso de REST frente a la mensajería, el arquitecto
principal debería demostrarle al otro arquitecto que la mensajería sería una mejor opción en su
entorno específico. Cada entorno es diferente, por lo que una simple búsqueda en Google nunca
arrojará la respuesta correcta. Si se realiza una comparación entre las dos opciones en un entorno
similar al de producción y se muestran los resultados al otro arquitecto, probablemente se evitaría la
discusión.
Evite ser demasiado argumentativo o dejar que las cosas se vuelvan demasiado
personales en una negociación: un liderazgo tranquilo combinado con un
razonamiento claro y conciso siempre ganará una negociación.
Esta técnica es una herramienta muy poderosa cuando se trata de relaciones adversas como la
descrita en el escenario 2. Una vez que las cosas se vuelven demasiado personales o polémicas, lo
mejor que se puede hacer es detener la negociación y volver a entablarla en otro momento, cuando
ambas partes se hayan calmado. Las discusiones se producirán entre arquitectos; sin embargo,
abordar estas situaciones con un liderazgo tranquilo generalmente obligará a la otra persona a dar
marcha atrás cuando las cosas se pongan demasiado acaloradas.
arquitectos de software eficaces no utilizan su título de arquitectos para decirles a los desarrolladores
qué deben hacer. En lugar de ello, trabajan con los equipos de desarrollo para ganarse el respeto de
modo que, cuando se les haga una solicitud, no termine en una discusión o resentimiento. Trabajar
con equipos de desarrollo puede ser difícil a veces. En muchos casos, los equipos de desarrollo se
sienten desconectados de la arquitectura (y también del arquitecto) y, como resultado, se sienten
excluidos de las decisiones que toma el arquitecto.
Este es un ejemplo clásico del antipatrón de la arquitectura de torre de marfil. Los arquitectos de torre
de marfil son aquellos que simplemente dictan desde arriba, diciéndoles a los equipos de desarrollo
qué hacer sin tener en cuenta su opinión o preocupaciones. Esto generalmente conduce a una pérdida
de respeto por el arquitecto y a una ruptura eventual de la dinámica del equipo. Una técnica de
negociación que puede ayudar a abordar esta situación es proporcionar siempre una justificación:
Al proporcionar un motivo por el cual se debe hacer algo, es más probable que los desarrolladores
acepten la solicitud. Por ejemplo, considere la siguiente conversación entre un arquitecto y un
desarrollador con respecto a la realización de una consulta simple dentro de una arquitectura
tradicional de n niveles:
Arquitecto: “Para realizar esa llamada hay que pasar por la capa empresarial”.
Desarrollador: “No. Es mucho más rápido llamar a la base de datos directamente”.
Hay varios aspectos erróneos en esta conversación. En primer lugar, observe el uso de las palabras
“debe”. Este tipo de voz autoritaria no solo es denigrante, sino que es una de las peores formas de
iniciar una negociación o conversación. Observe también que el desarrollador respondió a la
demanda del arquitecto con una razón para contrarrestarla (pasar por la capa empresarial será
más lento y llevará más tiempo). Ahora, considere un enfoque alternativo a esta demanda:
Arquitecto: “Como el control de cambios es lo más importante para nosotros, hemos creado una arquitectura
de capas cerradas. Esto significa que todas las llamadas a la base de datos deben provenir de la capa
empresarial”.
Desarrollador: “Está bien, lo entiendo, pero en ese caso, ¿cómo voy a lidiar con los problemas de rendimiento
de las consultas simples?”
Observe que aquí el arquitecto está proporcionando la justificación para la demanda de que todas
las solicitudes deben pasar por la capa empresarial de la aplicación. Proporcionar la justificación o
el motivo primero siempre es un buen enfoque. La mayoría de las veces, una vez que una persona
escucha algo con lo que no está de acuerdo, deja de escuchar. Al indicar el motivo primero, el
arquitecto está seguro de que se escuchará la justificación. Observe también que el arquitecto
eliminó la naturaleza personal de esta demanda. Al no decir "debe" o "necesita", el arquitecto
convirtió efectivamente la demanda en una simple declaración de hechos ("esto significa..."). Ahora
observe la respuesta del desarrollador. Observe que la conversación pasó de estar en desacuerdo
con las restricciones de la arquitectura en capas a una pregunta sobre cómo aumentar el
rendimiento de las llamadas simples. Ahora, el arquitecto y el desarrollador pueden participar en
una conversación colaborativa para encontrar formas de hacer consultas simples más rápidas y, al
mismo tiempo, preservar las capas cerradas de la arquitectura.
Otra táctica de negociación eficaz cuando se negocia con un desarrollador o se intenta convencerlo
de que acepte una decisión de diseño o arquitectura en particular con la que no está de acuerdo
es que el desarrollador llegue a la solución por sí solo. Esto crea una situación en la que todos
ganan y el arquitecto no puede perder. Por ejemplo, supongamos que un arquitecto está eligiendo
entre dos marcos, el Marco X y el Marco Y. El arquitecto ve que el Marco Y no satisface los
requisitos de seguridad del sistema y, por lo tanto, elige naturalmente el Marco X. Un desarrollador
del equipo está en total desacuerdo y
El arquitecto insiste en que el marco Y sigue siendo la mejor opción. En lugar de discutir el asunto, le
dice al desarrollador que el equipo utilizará el marco Y si el desarrollador puede demostrar cómo
abordar los requisitos de seguridad si se utiliza el marco Y. Ocurrirá una de dos cosas:
2. El desarrollador encuentra una forma de abordar los requisitos de seguridad con Framework Y y
se lo demuestra al arquitecto. Esto también es una victoria. En este caso, el arquitecto pasó por
alto algo en Framework Y, y también terminó siendo un mejor framework que el otro.
En realidad, es a través de la colaboración con el equipo de desarrollo que el arquitecto puede ganarse
el respeto del equipo y crear mejores soluciones. Cuanto más respeten los desarrolladores a un
arquitecto, más fácil será para este negociar con ellos.
Las 4 C de la arquitectura
Cada día las cosas parecen volverse más y más complejas, ya sea una mayor complejidad en los
procesos de negocios o una mayor complejidad de los sistemas e incluso de la arquitectura. La
complejidad existe tanto en la arquitectura como en el desarrollo de software, y siempre existirá.
Algunas arquitecturas son muy complejas, como las que admiten seis nueves de disponibilidad
(99,9999 %), lo que equivale a un tiempo de inactividad no planificado de aproximadamente 86
milisegundos al día, o 31,5 segundos de inactividad al año. Este tipo de complejidad se conoce como
complejidad esencial; en otras palabras, “tenemos un problema difícil”.
Una de las trampas en las que caen muchos arquitectos es la de añadir complejidad innecesaria a las
soluciones, los diagramas y la documentación. A los arquitectos (y también a los desarrolladores) parece
gustarles la complejidad. Como dice Neal:
Los desarrolladores se sienten atraídos por la complejidad como las polillas por la llama, frecuentemente con el mismo
resultado.
Considere el diagrama de la Figura 231 que ilustra los principales flujos de información para los sistemas
de procesamiento backend de un banco global muy grande. ¿Es esto necesariamente complejo?
Nadie sabe la respuesta a esta pregunta porque el arquitecto la ha hecho compleja.
Este tipo de complejidad se denomina complejidad accidental; en otras palabras, “hemos complicado
un problema”. A veces, los arquitectos hacen esto para demostrar su valía cuando las cosas parecen
demasiado simples o para garantizar que siempre se les mantenga informados de las discusiones y
decisiones que se toman con respecto al negocio o la arquitectura. Otros arquitectos lo hacen para
mantener la seguridad laboral. Cualquiera sea la razón, introducir complejidad accidental en algo que
no es complejo es una de las mejores formas de convertirse en un líder ineficaz como arquitecto.
Una forma eficaz de evitar la complejidad accidental es lo que llamamos las 4 C de la arquitectura:
comunicación, colaboración, claridad y concisión. Estos factores (ilustrados en la Figura 232)
trabajan juntos para crear un comunicador y colaborador eficaz en el equipo.
Como líder, facilitador y negociador, es vital que un arquitecto de software sea capaz de comunicarse
de manera eficaz, clara y concisa. Es igualmente importante que un arquitecto también sea capaz de
colaborar con desarrolladores, partes interesadas de la empresa y otros arquitectos para debatir y
formular soluciones en conjunto. Centrarse en las 4 C de la arquitectura ayuda a un arquitecto a
ganarse el respeto del equipo y convertirse en la persona de referencia en el proyecto a la que todos
acuden no solo para hacer preguntas, sino también para pedir consejo, tutoría, entrenamiento y
liderazgo.
arquitecto de software eficaz debe ser pragmático, pero visionario. Hacerlo no es tan fácil como
parece y requiere un nivel bastante alto de madurez y mucha práctica para lograrlo. Para comprender
mejor esta afirmación, considere la definición de visionario:
Visionario
Pensar o planificar el futuro con imaginación o sabiduría.
Ser visionario significa aplicar el pensamiento estratégico a un problema, que es exactamente lo que
se supone que debe hacer un arquitecto. La arquitectura consiste en planificar el futuro y asegurarse
de que la vitalidad arquitectónica (la validez de una arquitectura) se mantenga así durante mucho
tiempo. Sin embargo, muchas veces los arquitectos adoptan una actitud demasiado teórica en sus
planes y diseños, creando soluciones que se vuelven demasiado difíciles de entender o incluso de
implementar. Ahora consideremos la definición de ser pragmático:
Pragmático
Tratar las cosas de manera sensata y realista, de un modo que se basa en consideraciones
prácticas más que teóricas.
Si bien los arquitectos deben ser visionarios, también deben aplicar soluciones prácticas y realistas. Ser pragmático
significa tener en cuenta todos los siguientes factores y limitaciones al crear una solución arquitectónica:
Un buen arquitecto de software es aquel que se esfuerza por encontrar un equilibrio adecuado entre ser pragmático y,
al mismo tiempo, aplicar imaginación y sabiduría a la solución de problemas (véase la Figura 233). Por ejemplo,
considere la situación en la que un arquitecto se enfrenta a un problema difícil relacionado con la elasticidad (aumentos
repentinos y significativos desconocidos en la carga de usuarios simultáneos). Un visionario podría idear una forma
elaborada de abordar esto mediante el uso de una malla de datos compleja, que es una colección de bases de datos
distribuidas y basadas en dominios. En teoría, este podría ser un buen enfoque, pero ser pragmático significa aplicar la
razón y la practicidad a la solución. Por ejemplo, ¿la empresa ha utilizado alguna vez una malla de datos? ¿Cuáles son
las desventajas de utilizar una malla de datos?
Figura 233. Los buenos arquitectos encuentran el equilibrio entre ser pragmáticos y, al mismo tiempo, visionarios.
Mantener un buen equilibrio entre pragmatismo y visión de futuro es una excelente manera de ganarse el respeto de
los arquitectos. Los interesados en el negocio apreciarán las soluciones visionarias que se ajusten a un conjunto de
limitaciones, y los desarrolladores apreciarán tener una solución práctica (en lugar de teórica) para implementar.
Un arquitecto pragmático primero analizaría cuál es el factor limitante cuando se necesitan altos niveles de elasticidad.
¿Es la base de datos el cuello de botella? Tal vez sea un cuello de botella con respecto a algunos de los servicios
invocados u otras fuentes externas necesarias. Encontrar y aislar el cuello de botella sería una primera aproximación
práctica al problema.
De hecho, incluso si se trata de la base de datos, ¿se podrían almacenar en caché algunos de los datos necesarios para
no tener que acceder a la base de datos en absoluto?
malos arquitectos de software aprovechan su título para conseguir que la gente haga lo que ellos
quieren que hagan. Los arquitectos de software eficaces consiguen que la gente haga cosas no
aprovechando su título de arquitecto, sino más bien liderando con el ejemplo, no con el título. Se trata
de ganarse el respeto de los equipos de desarrollo, las partes interesadas del negocio y otras personas
de toda la organización (como el jefe de operaciones, los gerentes de desarrollo y los propietarios de
productos).
La clásica historia de “predicar con el ejemplo, no con el título” involucra a un capitán y un sargento
durante una batalla militar. El capitán de alto rango, que está en gran parte apartado de las tropas,
ordena a todas las tropas que avancen durante la batalla para tomar una colina particularmente difícil.
Sin embargo, en lugar de escuchar al capitán de alto rango, los soldados, llenos de dudas, miran al
sargento de menor rango para ver si deben tomar la colina o no. El sargento observa la situación,
asiente con la cabeza ligeramente y los soldados avanzan inmediatamente con confianza para tomar
la colina.
La moraleja de esta historia es que el rango y el título significan muy poco cuando se trata de dirigir a
la gente. El informático Gerald Weinberg Es famoso por decir: “No importa cuál sea el problema, es un
problema de personas”. La mayoría de las personas piensa que resolver problemas técnicos no tiene
nada que ver con las habilidades interpersonales, sino con el conocimiento técnico.
Si bien es cierto que tener conocimientos técnicos es necesario para resolver un problema, es solo
una parte de la ecuación general para resolver cualquier problema. Supongamos, por ejemplo, que un
arquitecto está celebrando una reunión con un equipo de desarrolladores para resolver un problema
que ha surgido en producción. Uno de los desarrolladores hace una sugerencia y el arquitecto
responde: "Bueno, esa es una idea tonta". No solo ese desarrollador no hará más sugerencias, sino
que ninguno de los otros desarrolladores se atreverá a decir nada. En este caso, el arquitecto ha
impedido que todo el equipo colabore en la solución.
Ganarse el respeto y liderar equipos es una cuestión de habilidades interpersonales básicas. Considere
el siguiente diálogo entre un arquitecto y un cliente, un cliente potencial o un equipo de desarrollo con
respecto a un problema de rendimiento en la aplicación:
Al utilizar las palabras “lo que tienes que hacer es…” o “debes hacerlo”, el arquitecto está imponiendo
su opinión al desarrollador y, en esencia, cerrando la colaboración. Este es un buen ejemplo de cómo
utilizar la comunicación, no la colaboración. Ahora, consideremos el diálogo revisado:
Observe el uso de las palabras “¿ha considerado…” o “¿qué tal si…” en el diálogo. Al hacer la
pregunta, se devuelve el control al desarrollador o cliente, creando una conversación colaborativa
donde tanto el arquitecto como el desarrollador trabajan juntos para formar una solución. El uso de
la gramática es de vital importancia cuando se intenta crear un entorno colaborativo. Ser un líder
como arquitecto no solo significa poder colaborar con otros para crear una arquitectura, sino también
ayudar a promover la colaboración en el equipo actuando como facilitador. Como arquitecto, intente
observar la dinámica del equipo y note cuándo ocurren situaciones como el primer diálogo. Al tomar
a los miembros del equipo a un lado y capacitarlos en el uso de la gramática como un medio de
colaboración, no solo creará una mejor dinámica de equipo, sino que también ayudará a crear
respeto entre los miembros del equipo.
Otra técnica básica de habilidades sociales que puede ayudar a generar respeto y relaciones
saludables entre un arquitecto y el equipo de desarrollo es tratar siempre de usar el nombre de la
persona durante una conversación o negociación. A la gente no solo le gusta escuchar su nombre
durante una conversación, sino que también ayuda a generar familiaridad. Practique recordar los
nombres de las personas y úselos con frecuencia. Dado que a veces los nombres son difíciles de
pronunciar, asegúrese de pronunciarlos correctamente y luego practique esa pronunciación hasta
que sea perfecta. Siempre que preguntamos el nombre de alguien, se lo repetimos a la persona y le
preguntamos si esa es la forma correcta de pronunciarlo. Si no es correcto, repetimos este proceso
hasta que lo hagamos bien.
Si un arquitecto conoce a alguien por primera vez o sólo ocasionalmente, siempre estreche la mano
de la persona y establezca contacto visual. Un apretón de manos es una importante habilidad social
que se remonta a la época medieval. El vínculo físico que se produce durante un simple apretón de
manos permite que ambas personas sepan que son amigos, no enemigos, y crea un vínculo entre
ellos. Sin embargo, a veces es difícil lograr un simple apretón de manos correcto.
Al estrechar la mano de alguien, hazlo con firmeza (pero sin arrogancia) mientras miras a la persona
a los ojos. Mirar hacia otro lado mientras estrechas la mano de alguien es una señal de falta de
respeto, y la mayoría de las personas lo notarán. Además, no mantengas el apretón de manos
demasiado tiempo. Un simple apretón de manos firme de dos a tres segundos es todo lo que se
necesita para iniciar una conversación o saludar a alguien. También existe el problema de exagerar
con la técnica del apretón de manos y hacer que la otra persona se sienta lo suficientemente
incómoda como para no querer comunicarse o colaborar contigo. Por ejemplo, imagina a un
arquitecto de software que llega todas las mañanas y comienza a estrechar la mano de todos. Esto
no solo es un poco extraño, sino que crea una situación incómoda. Sin embargo, imagina a un
arquitecto de software que debe reunirse con el jefe de operaciones mensualmente. Esta es la
oportunidad perfecta para ponerse de pie, decir "Hola Ruth, me alegro de verte de nuevo" y dar un saludo.
Un apretón de manos rápido y firme. Saber cuándo dar un apretón de manos y cuándo no es parte del
complejo arte de relacionarse con las personas.
Un arquitecto de software, como líder, facilitador y negociador, debe tener cuidado de preservar los límites
que existen entre las personas en todos los niveles. El apretón de manos, como se describió anteriormente,
es una técnica eficaz y profesional para formar un vínculo físico con la persona con la que se está comunicando
o colaborando. Sin embargo, si bien un apretón de manos es bueno, un abrazo en un entorno profesional,
independientemente del entorno, no lo es. Un arquitecto puede pensar que ejemplifica una mayor conexión y
vínculo físico, pero lo único que hace es, a veces, hacer que la otra persona en el trabajo se sienta más
incómoda y, lo que es más importante, puede dar lugar a posibles problemas de acoso en el lugar de trabajo.
Evite los abrazos por completo, independientemente del entorno profesional, y limítese al apretón de manos
(a menos, por supuesto, que todos en la empresa se abracen, lo que sería… extraño).
A veces es mejor convertir una solicitud en un favor como una forma de lograr que alguien haga algo que de
otra manera no querría hacer. En general, a la gente no le gusta que le digan qué hacer, pero en su mayoría,
la gente quiere ayudar a los demás. Esto es parte de la naturaleza humana básica. Considere la siguiente
conversación entre un arquitecto y un desarrollador sobre un esfuerzo de refactorización de la arquitectura
durante una iteración intensa:
Arquitecto: “Voy a necesitar que dividas el servicio de pago en cinco servicios diferentes, y que cada servicio contenga la
funcionalidad para cada tipo de pago que aceptamos, como crédito en la tienda, tarjeta de crédito, PayPal, tarjeta de regalo
y puntos de recompensa, para brindar una mejor tolerancia a fallas y escalabilidad en el sitio web. No debería llevar
demasiado tiempo”.
Desarrollador: “De ninguna manera, hombre. Esta iteración está demasiado ocupada para eso. Lo siento, no puedo hacerlo”.
Observe la respuesta del desarrollador. Es un rechazo inmediato de la tarea, a pesar de que el arquitecto lo
justificó con una mejor tolerancia a fallas y escalabilidad. En este caso, observe que el arquitecto le está
diciendo al desarrollador que haga algo que simplemente está demasiado ocupado para hacer. Observe
también que la exigencia ni siquiera incluye el nombre de la persona. Ahora considere la técnica de convertir
la solicitud en un favor:
Arquitecto: “Hola, Sridhar. Escucha, estoy en un verdadero aprieto. Realmente necesito dividir el servicio de pago en
servicios separados para cada tipo de pago para obtener una mejor tolerancia a fallas y escalabilidad, y esperé demasiado
para hacerlo. ¿Hay alguna manera de que puedas incluir esto en esta iteración? Realmente me ayudaría”.
Desarrollador: “(Pausa)… Estoy muy ocupado en esta iteración, pero supongo que sí. Veré qué puedo
hacer”.
Arquitecto: “Gracias, Sridhar, realmente aprecio tu ayuda. Te debo una”.
Desarrollador: “No te preocupes, me encargaré de que se haga en esta iteración”.
En segundo lugar, observe que el arquitecto admite que se encuentra en un “verdadero aprieto” y
que dividir los servicios realmente “lo ayudaría mucho”. Esta técnica no siempre funciona, pero jugar
con la naturaleza humana básica de ayudarse mutuamente tiene más probabilidades de éxito que la
primera conversación. Pruebe esta técnica la próxima vez que se enfrente a este tipo de situación y
vea los resultados. En la mayoría de los casos, los resultados serán mucho más positivos que decirle
a alguien qué hacer.
Para dirigir un equipo y convertirse en un líder eficaz, un arquitecto de software debe intentar
convertirse en la persona de referencia del equipo, la persona a la que los desarrolladores acuden
para sus preguntas y problemas. Un arquitecto de software eficaz aprovechará la oportunidad y
tomará la iniciativa de dirigir el equipo, independientemente de su título o función en el equipo.
Cuando un arquitecto de software observa a alguien luchando con un problema técnico, debe
intervenir y ofrecer ayuda u orientación. Lo mismo es válido para las situaciones no técnicas también.
Supongamos que un arquitecto observa a un miembro del equipo que llega al trabajo con un aspecto
deprimido y molesto: claramente algo anda mal. En esta circunstancia, un arquitecto de software
eficaz se daría cuenta de la situación y se ofrecería a hablar, algo así como: "Oye, Antonio, voy a
tomar un café. ¿Por qué no vamos juntos?" y luego, durante el paseo, preguntaría si todo está bien.
Esto al menos proporciona una oportunidad para una discusión más personal; y, en el mejor de los
casos, una oportunidad de ser mentor y entrenador a un nivel más personal. Sin embargo, un líder
eficaz también reconocerá los momentos en los que no debe ser demasiado agresivo y dará marcha
atrás leyendo diversas señales verbales y expresiones faciales.
Otra técnica para empezar a ganarse el respeto como líder y convertirse en la persona de referencia
del equipo es organizar almuerzos informales periódicos para hablar sobre una técnica o tecnología
específica. Todos los que leen este libro tienen una habilidad o conocimiento particular que los demás
no tienen. Al organizar un almuerzo informal periódico, el arquitecto no solo puede exhibir su destreza
técnica, sino también practicar sus habilidades de oratoria y de mentoría. Por ejemplo, organice un
almuerzo sobre una revisión de patrones de diseño o las últimas características del lanzamiento del
lenguaje de programación. Esto no solo proporciona información valiosa a los desarrolladores, sino
que también comienza a identificarlo como líder y mentor en el equipo.
La clave para ser un arquitecto de software eficaz es dedicar más tiempo al equipo de desarrollo, y esto
implica controlar las reuniones. Hay dos tipos de reuniones en las que puede participar un arquitecto: las
impuestas (se invita al arquitecto a una reunión) y las impuestas por (el arquitecto convoca la reunión).
Estos tipos de reuniones se ilustran en la Figura 235.
Las reuniones impuestas son las más difíciles de controlar. Debido a la cantidad de partes interesadas
con las que un arquitecto de software debe comunicarse y colaborar, los arquitectos son invitados a casi
todas las reuniones que se programan. Cuando se lo invita a una reunión, un arquitecto de software
eficaz siempre debe preguntar al organizador de la reunión por qué es necesario que asista a esa
reunión. Muchas veces, los arquitectos son invitados a las reuniones simplemente para mantenerse al
tanto de la información que se está discutiendo. Para eso están las notas de las reuniones. Al preguntar
por qué, un arquitecto puede comenzar a calificar a qué reuniones debe asistir y cuáles puede omitir.
Otra técnica relacionada para ayudar a reducir la cantidad de reuniones en las que participa un arquitecto
es solicitar la agenda de la reunión antes de aceptar una invitación a la misma. El organizador de la
reunión puede sentir que el arquitecto es necesario, pero al mirar la agenda, el arquitecto puede calificar
si realmente necesita estar en la reunión o no. Además, muchas veces no es necesario asistir a toda la
reunión.
Al revisar la agenda, un arquitecto puede optimizar su tiempo, ya sea asistiendo cuando se está
discutiendo información relevante o retirándose una vez que la discusión relevante ha terminado. No
pierda tiempo en una reunión si puede dedicarlo a trabajar con el equipo de desarrollo.
Otra técnica eficaz para mantener a un equipo de desarrollo encaminado y ganarse su respeto es hacer
un favor al equipo cuando también se invita a los desarrolladores a una reunión.
En lugar de que el líder técnico asista a la reunión, vaya en su lugar, en particular si tanto el líder técnico
como el arquitecto están invitados a una reunión. Esto permite que el equipo de desarrollo se concentre
en la tarea en cuestión en lugar de asistir continuamente a las reuniones.
Si bien desviar las reuniones de los miembros útiles del equipo aumenta el tiempo que un arquitecto pasa
en reuniones, también aumenta la productividad del equipo de desarrollo.
Las reuniones que un arquitecto impone a los demás (el arquitecto convoca la reunión) también son una
necesidad a veces, pero deben reducirse al mínimo. Este es el tipo de reuniones sobre las que un
arquitecto tiene control. Un arquitecto de software eficaz siempre preguntará si la reunión que está
convocando es más importante que el trabajo del que está apartando a los miembros de su equipo.
Muchas veces, un correo electrónico es todo lo que se necesita para comunicar alguna información
importante, lo que le ahorra a todos una gran cantidad de tiempo perdido. Cuando convoque una reunión
como arquitecto, siempre establezca una agenda y cúmplala. Con demasiada frecuencia, las reuniones
que un arquitecto convoca se descarrilan debido a algún otro problema, y ese otro problema puede no
ser relevante para todos los demás en la reunión. Además, como arquitecto, preste mucha atención al
flujo de trabajo de los desarrolladores y asegúrese de no interrumpirlo convocando una reunión.
El flujo es un estado mental en el que los desarrolladores entran frecuentemente, donde el cerebro se
involucra al 100 % en un problema en particular, lo que permite una atención total y una creatividad máxima.
Además de gestionar reuniones, otra cosa que puede hacer un arquitecto de software eficaz para
integrarse mejor con el equipo de desarrollo es sentarse con él. Sentarse en un cubículo alejado
del equipo transmite el mensaje de que el arquitecto es especial, y las paredes físicas que rodean
el cubículo transmiten un mensaje claro de que no hay que molestar ni perturbar al arquitecto.
Sentarse junto a un equipo de desarrollo transmite el mensaje de que el arquitecto es parte integral
del equipo y está disponible para responder preguntas o inquietudes a medida que surjan. Al
mostrar físicamente que forma parte del equipo de desarrollo, el arquitecto gana más respeto y
está mejor capacitado para ayudar a guiar y orientar al equipo.
A veces no es posible que un arquitecto se siente con un equipo de desarrollo. En estos casos, lo
mejor que puede hacer un arquitecto es caminar continuamente y ser visto.
Los arquitectos que están estancados en un piso diferente o que siempre están en sus oficinas o
cubículos y nunca son vistos no pueden ayudar a guiar al equipo de desarrollo a través de la
implementación de la arquitectura. Reserve tiempo por la mañana, después del almuerzo o al final
del día y tómese el tiempo para conversar con el equipo de desarrollo, ayudar con los problemas,
responder preguntas y realizar una capacitación y tutoría básicas. Los equipos de desarrollo
aprecian este tipo de comunicación y lo respetarán por dedicar tiempo a ellos durante el día. Lo
mismo se aplica a otras partes interesadas. Pasar a saludar al jefe de operaciones mientras va a
buscar más café es una excelente manera de mantener la comunicación abierta y disponible con la
empresa y otras partes interesadas clave.
Resumen
Los consejos de negociación y liderazgo que se presentan y analizan en este capítulo tienen como
objetivo ayudar al arquitecto de software a establecer una mejor relación de colaboración con el
equipo de desarrollo y otras partes interesadas. Estas son habilidades necesarias que un arquitecto
debe tener para convertirse en un arquitecto de software eficaz. Si bien los consejos que
presentamos en este capítulo son buenos consejos para comenzar el viaje hacia convertirse en un
líder más eficaz, tal vez el mejor consejo de todos proviene de una cita de Theodore Roosevelt: El
26º presidente de Estados Unidos:
El ingrediente más importante en la fórmula del éxito es saber cómo llevarse bien con la
gente.
—Theodore Roosevelt
Resumen | 363
Machine Translated by Google
Machine Translated by Google
CAPÍTULO 24
Convertirse en arquitecto requiere tiempo y esfuerzo, pero, según las muchas razones que hemos esbozado
a lo largo de este libro, gestionar una trayectoria profesional después de convertirse en arquitecto es
igualmente complicado. Si bien no podemos trazar una trayectoria profesional específica para usted, podemos
indicarle algunas prácticas que hemos visto que funcionan bien.
Un arquitecto debe seguir aprendiendo a lo largo de su carrera. El mundo de la tecnología cambia a un ritmo
vertiginoso. Uno de los antiguos compañeros de trabajo de Neal era un experto en Clipper de renombre
mundial. Se lamentaba de no poder tomar el enorme conjunto de conocimientos (ahora inútiles) de Clipper y
reemplazarlo por algo más. También especulaba (y esto sigue siendo una pregunta abierta): ¿alguna vez en
la historia ha habido un grupo que haya aprendido y desechado tanto conocimiento detallado a lo largo de
sus vidas como desarrolladores de software?
Cada arquitecto debe estar atento a los recursos relevantes, tanto tecnológicos como comerciales, y
agregarlos a su arsenal personal. Desafortunadamente, los recursos aparecen y desaparecen demasiado
rápido, por lo que no enumeramos ninguno en este libro. Hablar con colegas o expertos sobre los recursos
que utilizan para mantenerse actualizados es una buena manera de buscar las últimas noticias, sitios web y
grupos que están activos en un área de interés en particular. Los arquitectos también deben reservar algo de
tiempo en su día para mantener la amplitud utilizando esos recursos.
Como se ilustra en la Figura 26, la amplitud tecnológica es más importante para los arquitectos que la
profundidad. Sin embargo, mantener la amplitud requiere tiempo y esfuerzo, algo que los arquitectos deberían
incorporar a su día a día. Pero, ¿cómo puede alguien tener tiempo para ir a varios sitios web para leer
artículos, ver presentaciones y escuchar podcasts? La respuesta es... no muchos lo hacen. Tanto los
desarrolladores como los arquitectos luchan por encontrar el equilibrio entre trabajar en un empleo regular,
pasar tiempo con la familia y estar disponibles para
365
Machine Translated by Google
nuestros hijos, reservando tiempo personal para sus intereses y pasatiempos, y tratando de desarrollar
sus carreras, mientras al mismo tiempo intentamos mantenernos al día con las últimas tendencias y
palabras de moda.
Una técnica que utilizamos para mantener este equilibrio es algo que llamamos la regla de los 20 minutos. La idea de esta
técnica, como se ilustra en la Figura 241, es dedicar al menos 20 minutos al día a su carrera como arquitecto aprendiendo
algo nuevo o profundizando en un tema específico. La Figura 241 ilustra ejemplos de algunos de los tipos de recursos a los
que se pueden dedicar 20 minutos al día, como InfoQ, Tarjeta de referencia de DZone, y el Radar Tecnológico de ThoughtWorks.
Dedica un mínimo de 20 minutos a buscar en Google algunas palabras de moda que no conozcas (“las cosas que no sabes
que no sabes” del Capítulo 2) para aprender un poco sobre ellas y convertir ese conocimiento en “las cosas que sabes que no
sabes”. O tal vez dedica los 20 minutos a profundizar en un tema en particular para adquirir un poco más de conocimiento
sobre él. El objetivo de esta técnica es poder reservar algo de tiempo para desarrollar una carrera como arquitecto y ganar
continuamente conocimientos técnicos.
Muchos arquitectos adoptan este concepto y planean dedicar 20 minutos a la hora del almuerzo o por la tarde después del
trabajo para hacerlo. Lo que hemos experimentado es que esto rara vez funciona.
La hora del almuerzo se hace cada vez más corta y se convierte más en un momento para ponerse al día con el trabajo que
para tomar un descanso y comer. Las tardes son aún peores: las situaciones cambian, se hacen planes, el tiempo en familia
se vuelve más importante y la regla de los 20 minutos nunca se cumple.
Recomendamos encarecidamente aplicar la regla de los 20 minutos a primera hora de la mañana, cuando el día está
comenzando. Sin embargo, este consejo también tiene una salvedad. Por ejemplo, ¿qué es lo primero que hace un arquitecto
después de ponerse a trabajar por la mañana? Bueno, lo primero que hace un arquitecto después de empezar a trabajar por la mañana.
Lo primero que hace un arquitecto es tomarse una taza de café o té. Bien, en ese caso, ¿qué es lo
segundo que hace todo arquitecto después de tomarse ese café o té tan necesario? Revisar el correo
electrónico. Una vez que un arquitecto revisa el correo electrónico, se produce una distracción, se escriben
las respuestas y se termina el día. Por lo tanto, nuestra recomendación enfática es aplicar la regla de los
20 minutos a primera hora de la mañana, justo después de tomarse una taza de café o té y antes de
revisar el correo electrónico. Ir a trabajar un poco antes. Hacer esto aumentará la amplitud técnica de un
arquitecto y ayudará a desarrollar el conocimiento necesario para convertirse en un arquitecto de software
eficaz.
También enseñó una lección importante sobre las burbujas tecnológicas. Cuando se invierte mucho en
una tecnología, un desarrollador vive en una burbuja memética, que también funciona como una cámara
de eco. Las burbujas creadas por los proveedores son particularmente peligrosas, porque los
desarrolladores nunca escuchan evaluaciones honestas desde dentro de la burbuja. Pero el mayor peligro
de vivir en una burbuja surge cuando comienza a derrumbarse, algo que los desarrolladores nunca notan
desde adentro hasta que es demasiado tarde.
Lo que les faltaba era un radar tecnológico: un documento vivo para evaluar los riesgos y las ventajas de
las tecnologías existentes y emergentes. El concepto de radar proviene de ThoughtWorks; primero,
describiremos cómo surgió este concepto y luego cómo usarlo para crear un radar personal.
Poco a poco, la TAB se adaptó a un ritmo de producción de radar de dos veces al año. Luego, como suele
ocurrir, surgieron efectos secundarios inesperados. En algunas de las conferencias en las que Neal habló,
los asistentes lo buscaron y le agradecieron por ayudar a producir el radar y dijeron que su empresa había
comenzado a producir su propia versión.
Neal también se dio cuenta de que esta era la respuesta a una pregunta omnipresente en los paneles de oradores de
conferencias en todas partes: "¿Cómo se mantienen ustedes (los oradores) al día con la tecnología?
¿Cómo sabes qué cosas seguir?” La respuesta, por supuesto, es que todos tienen algún tipo de radar interno.
Regiones
El radar de ThoughtWorks consta de cuatro cuadrantes que intentan cubrir la mayor parte del panorama del desarrollo de
software:
Herramientas
Herramientas en el espacio de desarrollo de software, todo, desde herramientas para desarrolladores como
IDE para herramientas de integración de nivel empresarial
Técnicas
Cualquier práctica que ayude al desarrollo de software en general; esto puede incluir procesos de desarrollo de
software, prácticas de ingeniería y asesoramiento.
Plataformas
Plataformas tecnológicas, incluidas bases de datos, proveedores de nube y sistemas operativos
Anillos
Retener La intención original del anillo de retención era “retener por ahora”, para representar tecnologías
que eran demasiado nuevas para evaluarlas razonablemente todavía, tecnologías que estaban
generando mucho revuelo pero que aún no estaban probadas. El anillo de retención ha
evolucionado para indicar “no comience nada nuevo con esta tecnología”. No hay nada de malo
en usarlo en proyectos existentes, pero los desarrolladores deberían pensarlo dos veces antes de
usarlo para un nuevo desarrollo.
Evaluar
El anillo de evaluación indica que vale la pena explorar una tecnología con el objetivo de comprender
cómo afectará a una organización. Los arquitectos deben invertir algo de esfuerzo (como picos de
desarrollo, proyectos de investigación y sesiones de conferencias) para ver si tendrá un impacto en la
organización. Por ejemplo, muchas grandes empresas pasaron visiblemente por esta fase al formular
una estrategia móvil.
Prueba El anillo de prueba es para tecnologías que vale la pena explorar; es importante entender cómo
desarrollar esta capacidad. Ahora es el momento de poner a prueba un proyecto de bajo riesgo para
que los arquitectos y desarrolladores puedan comprender realmente la tecnología.
Adoptar
En el caso de las tecnologías en el círculo de adopción, ThoughtWorks cree firmemente que la industria
debería adoptar esos elementos.
En la Figura 242, cada punto representa una tecnología o técnica diferente, con breves descripciones
asociadas. Si bien ThoughtWorks utiliza el radar para transmitir sus opiniones sobre el mundo del software,
muchos desarrolladores y arquitectos también lo utilizan como una forma de estructurar su proceso de
evaluación de la tecnología. Los arquitectos pueden utilizar la herramienta descrita en “Bits de visualización
de código abierto” en la página 371 para crear las mismas imágenes que utiliza ThoughtWorks como una
forma de organizar su pensamiento sobre en qué invertir tiempo.
Al utilizar el radar para uso personal, sugerimos modificar el significado de los cuadrantes de la siguiente
manera:
Mantener Un arquitecto puede incluir no solo tecnologías y técnicas que debe evitar, sino también
hábitos que intenta romper. Por ejemplo, un arquitecto del mundo .NET puede estar acostumbrado
a leer las últimas noticias o chismes en foros sobre cuestiones internas del equipo. Si bien es
entretenido, puede ser un flujo de información de bajo valor. Poner eso en espera constituye un
recordatorio para que un arquitecto evite cosas problemáticas.
Los
arquitectos deben utilizar la evaluación para tecnologías prometedoras de las que han oído hablar bien
pero que aún no han tenido tiempo de evaluar por sí mismos (consulte “Uso de las redes sociales” en
la página 371). Este anillo forma un área de preparación para una investigación más seria en algún
momento en el futuro.
Prueba El anillo de prueba indica investigación y desarrollo activos, como un arquitecto que realiza
experimentos de picos dentro de una base de código más grande. Este anillo representa tecnologías
en las que vale la pena invertir tiempo para comprenderlas más profundamente, de modo que un
arquitecto pueda realizar un análisis de compensaciones eficaz.
Adoptar
El anillo de adopción representa las cosas nuevas que más entusiasman a un arquitecto y las
mejores prácticas para resolver problemas particulares.
Es peligroso adoptar una actitud laissezfaire con respecto a una cartera de tecnologías. La mayoría de
los tecnólogos eligen tecnologías de forma más o menos ad hoc, en función de lo que está de moda o
de lo que impulsa su empleador. La creación de un radar tecnológico ayuda a un arquitecto a formalizar
su pensamiento sobre la tecnología y a equilibrar criterios de decisión opuestos (como el factor de la
tecnología “más interesante” y la menor probabilidad de conseguir un nuevo trabajo frente a un mercado
laboral enorme pero con trabajos menos interesantes). Los arquitectos deberían tratar su cartera de
tecnologías como una cartera financiera: en muchos sentidos, son lo mismo. ¿Qué le dice un planificador
financiero a la gente sobre su cartera? ¡Diversificar!
Los arquitectos deberían elegir algunas tecnologías o habilidades que tengan una amplia demanda y
seguir esa demanda. Pero también podrían querer probar algunas tácticas tecnológicas, como el
desarrollo de código abierto o de dispositivos móviles. Abundan las anécdotas sobre desarrolladores
que se liberaron de la servidumbre de vivir en un cubículo trabajando hasta altas horas de la noche en
proyectos de código abierto que se volvieron populares, comprables y, con el tiempo, destinos
profesionales. Esta es otra razón más para centrarse en la amplitud en lugar de la profundidad.
Los arquitectos deberían reservar tiempo para ampliar su cartera de tecnologías, y la construcción de un
radar proporciona un buen andamiaje. Sin embargo, el ejercicio es más importante que el resultado.
Crear la visualización proporciona una excusa para pensar en estas cosas.
Y, para los arquitectos ocupados, encontrar una excusa para sacar tiempo en una agenda apretada es la única
forma en que este tipo de pensamiento puede ocurrir.
demanda popular, ThoughtWorks lanzó una herramienta en noviembre de 2016 para ayudar a los tecnólogos a
construir su propia visualización de radar. Cuando ThoughtWorks hace este ejercicio para las empresas,
capturan el resultado de la reunión en una hoja de cálculo, con una página para cada cuadrante. La herramienta
Build Your Own Radar de ThoughtWorks utiliza una hoja de cálculo de Google como entrada y genera la
visualización del radar utilizando un lienzo HTML 5. Por lo tanto, si bien la parte importante del ejercicio son las
conversaciones que genera, también genera visualizaciones útiles.
¿Dónde puede un arquitecto encontrar nuevas tecnologías y técnicas que pueda tener en cuenta? En el libro
Enterprise 2.0 (Harvard Business Review Press), Andrew McAfee hace una observación interesante sobre los
medios sociales y las redes sociales en general. Al pensar en la red de contactos de una persona con otras
personas, existen tres categorías, como se ilustra en la Figura 243.
En la Figura 243, los vínculos fuertes representan a miembros de la familia, compañeros de trabajo y otras
personas con las que una persona se comunica regularmente. Una prueba de fuego para saber cuán cercanas
son estas conexiones: pueden decirle qué almorzó una persona en sus vínculos fuertes al menos un día de la
semana pasada. Los vínculos débiles son conocidos casuales, parientes lejanos y otras personas que se ven
Solo unas pocas veces al año. Antes de las redes sociales, era difícil mantenerse al día con este círculo de
personas. Finalmente, los enlaces potenciales representan personas que aún no has conocido.
La observación más interesante de McAfee sobre estas conexiones fue que es más probable que el próximo
trabajo de alguien provenga de un vínculo débil que de uno fuerte. Las personas con vínculos fuertes lo saben
todo dentro del grupo con vínculos fuertes: son personas que se ven todo el tiempo. Los vínculos débiles, por
otro lado, ofrecen consejos ajenos a la experiencia normal de alguien, incluidas nuevas ofertas de trabajo.
Los arquitectos pueden aprovechar las características de las redes sociales para mejorar su alcance técnico. Si
utilizan redes sociales como Twitter de manera profesional, deberían encontrar tecnólogos cuyo asesoramiento
respeten y seguirlos en las redes sociales. Esto les permite crear una red sobre tecnologías nuevas e
interesantes para evaluar y mantenerse al día con los rápidos cambios en el mundo de la tecnología.
¿Cómo conseguimos grandes diseñadores? Los grandes diseñadores diseñan, por supuesto.
—Fred Brooks
Entonces, ¿cómo vamos a conseguir grandes arquitectos si sólo tienen la oportunidad de ejercer la
arquitectura menos de media docena de veces en su carrera?
—Ted Neward
Una pregunta común que recibimos sobre los katas: ¿hay una guía de respuestas en alguna parte?
Lamentablemente, no existe una clave de respuestas. Para citar al autor, Neal:
Cuando empezamos a utilizar el ejercicio de katas de arquitectura durante las clases de formación en
directo, al principio conservamos los dibujos que habían elaborado los estudiantes con el objetivo de crear
un repositorio de respuestas. Sin embargo, nos dimos por vencidos rápidamente porque nos dimos cuenta
de que teníamos artefactos incompletos. En otras palabras, los equipos habían capturado la topología y
explicado sus decisiones en clase, pero no tenían tiempo para crear registros de decisiones de arquitectura.
Si bien la forma en que implementaron sus soluciones fue interesante, el por qué fue mucho más interesante
porque contiene las compensaciones que consideraron al tomar esa decisión. Quedarse solo en el cómo fue
solo la mitad de la historia. Por lo tanto, nuestro último consejo de despedida: ¡siempre aprenda, siempre
practique y haga algo de arquitectura!
APÉNDICE
Preguntas de autoevaluación
Capítulo 1: Introducción
1. ¿Cuáles son las cuatro dimensiones que definen la arquitectura de software?
2. Enumere los tres niveles de conocimiento en el triángulo del conocimiento y proporcione un ejemplo de cada
uno.
3. ¿Por qué es más importante para un arquitecto centrarse en la amplitud técnica en lugar de...
¿Que profundidad técnica?
4. ¿Cuáles son algunas de las formas de mantener su profundidad técnica y seguir siendo práctico como
arquitecto?
373
Machine Translated by Google
Capítulo 3: Modularidad
1. ¿Cuáles son los tres criterios que debe cumplir un atributo para ser considerado una característica de arquitectura?
¿caracteristica?
6. ¿Qué característica de la arquitectura es más importante que debemos esforzarnos por lograr: la disponibilidad o la
¿actuación?
1. Dé una razón por la cual es una buena práctica limitar la cantidad de características (“ ilidades”) que una
arquitectura debe soportar.
2. Verdadero o falso: la mayoría de las características de la arquitectura provienen de los requisitos del negocio.
y historias de usuario.
3. Si una parte interesada del negocio afirma que el tiempo de comercialización (es decir, ofrecer nuevas características
y correcciones de errores a los usuarios lo más rápido posible) es la preocupación comercial más importante,
¿qué características de arquitectura debería soportar la arquitectura?
5. Te enteras de que tu empresa está a punto de realizar varias adquisiciones importantes para aumentar
significativamente su base de clientes. ¿Qué características arquitectónicas deberían preocuparte?
1. ¿Por qué la complejidad ciclomática es una métrica tan importante para analizar en la arquitectura?
¿ley?
2. ¿Qué es una función de aptitud de arquitectura? ¿Cómo se pueden utilizar para analizar una
¿arquitectura?
3. Proporcione un ejemplo de una función de aptitud de arquitectura para medir la escalabilidad de una
arquitectura.
4. ¿Cuál es el criterio más importante para que una característica de arquitectura permita a los arquitectos y
desarrolladores crear funciones de aptitud?
2. Supongamos que un sistema consta de una única interfaz de usuario con cuatro servicios implementados de
forma independiente, cada uno de los cuales contiene su propia base de datos. ¿Este sistema tendría un
único quantum o cuatro quantums? ¿Por qué?
3. Supongamos que tenemos un sistema con una parte administrativa que gestiona datos de referencia estáticos
(como el catálogo de productos y la información del almacén) y una parte orientada al cliente que gestiona
la realización de pedidos. ¿Cuántos cuantos debería tener este sistema y por qué? Si imaginamos varios
cuantos, ¿podrían compartir una base de datos el cuanto administrativo y el cuanto orientado al cliente? Si
es así, ¿en qué cuanto debería residir la base de datos?
1. Definimos el término componente como un elemento básico de una aplicación, algo que la aplicación hace.
Un componente suele estar formado por un grupo de clases o archivos fuente. ¿Cómo se manifiestan
normalmente los componentes dentro de una aplicación o servicio?
4. ¿En qué circunstancias la partición técnica sería una mejor opción que...
¿particionamiento de dominio?
5. ¿Qué es la trampa de entidad? ¿Por qué no es un buen enfoque para los componentes?
¿identificación?
6. ¿Cuándo se debe elegir el enfoque de flujo de trabajo en lugar del enfoque Actor/Acciones?
¿Cuál es el mejor enfoque para identificar los componentes principales?
2. Nombra tres desafíos que tienen las arquitecturas distribuidas que son arquitecturas monolíticas.
Las texturas no lo son.
2. Describe el concepto de capas de aislamiento y cuáles son los beneficios de este concepto.
4. ¿Cuáles son algunas de las principales características de la arquitectura que lo llevarían a utilizar una arquitectura
en capas?
5. ¿Por qué la capacidad de prueba no está bien respaldada en el estilo de arquitectura en capas?
4. ¿El estilo de arquitectura de la canalización está particionado técnicamente o particionado por dominio?
2. ¿En qué situaciones está bien que los componentes enchufables dependan de otros?
¿componentes enchufables?
3. ¿Cuáles son algunas de las herramientas y marcos que se pueden utilizar para administrar complementos?
4. ¿Qué haría si tuviera un complemento de terceros que no cumpliera con las normas?
¿Contrato de complemento estándar en el sistema central?
7. ¿Por qué la arquitectura del microkernel es siempre una única arquitectura cuántica?
2. ¿Es necesario dividir una base de datos en una arquitectura basada en servicios?
4. ¿Qué técnica puede utilizar para gestionar los cambios de la base de datos dentro de un servicio?
¿arquitectura?
6. ¿Qué características de la arquitectura están bien soportadas por la arquitectura basada en servicios?
¿Estilo de arquitectura?
7. ¿Por qué la elasticidad no está bien soportada en una arquitectura basada en servicios?
1. ¿Cuáles son las principales diferencias entre las topologías de intermediario y mediador?
2. Para un mejor control del flujo de trabajo, ¿utilizaría la topología de mediador o de intermediario?
3. ¿La topología del bróker suele aprovechar un modelo de publicación y suscripción con
¿Temas o un modelo punto a punto con colas?
8. ¿Cuáles son algunas de las técnicas para evitar la pérdida de datos al enviar y recibir mensajes de una cola?
9. ¿Cuáles son las tres características principales de la arquitectura impulsora para el uso de eventos?
¿arquitectura?
10. ¿Cuáles son algunas de las características de la arquitectura que no están bien soportadas en
¿Arquitectura basada en eventos?
2. ¿Cuál es el aspecto principal de la arquitectura basada en el espacio que la diferencia de otros estilos de arquitectura?
3. Nombra los cuatro componentes que forman el middleware virtualizado dentro de una arquitectura basada en el
espacio.
6. ¿En qué condiciones un servicio necesitaría acceder a los datos a través de la base de datos?
¿lector?
7. ¿Un tamaño de caché pequeño aumenta o disminuye las posibilidades de una colisión de datos?
9. Enumere tres de las características arquitectónicas más fuertemente respaldadas en la arquitectura basada en el
espacio.
10. ¿Por qué la capacidad de prueba tiene una tasa tan baja para la arquitectura basada en el espacio?
2. ¿Cuáles son los cuatro tipos de servicios principales dentro de una arquitectura orientada a servicios?
3. Enumere algunos de los factores que llevaron a la caída de la arquitectura orientada a servicios.
4. ¿La arquitectura orientada a servicios está técnicamente particionada o particionada por dominio?
1. ¿Por qué el concepto de contexto delimitado es tan crítico para la arquitectura de microservicios?
4. ¿Cuál es la diferencia entre orquestación y coreografía? ¿Cuál de ellas es compatible con los microservicios?
¿Hay algún estilo de comunicación que sea más sencillo en los microservicios?
6. ¿Por qué la agilidad, la capacidad de prueba y la capacidad de implementación están tan bien respaldadas en los microservicios?
7. ¿Cuáles son dos razones por las que el rendimiento suele ser un problema en los microservicios?
8. ¿Los microservicios son una arquitectura particionada por dominio o una arquitectura particionada técnicamente?
¿uno?
9. Describe una topología donde un ecosistema de microservicios podría ser solo uno.
cuántico.
10. ¿Cómo se abordó la reutilización de dominios en los microservicios? ¿Cómo se abordó la reutilización operativa?
¿dirigido?
1. ¿De qué manera la arquitectura de datos (estructura de los datos lógicos y físicos)
¿Los modelos influyen en la elección del estilo arquitectónico?
3. Describa los pasos que utiliza un arquitecto para determinar el estilo de arquitectura, la partición de datos y los
estilos de comunicación.
2. ¿Cuáles son algunas técnicas para evitar la arquitectura basada en correo electrónico anti
¿patrón?
3. ¿Cuáles son los cinco factores que Michael Nygard define para identificar algo como
arquitectónicamente significativo?
4. ¿Cuáles son las cinco secciones básicas de un registro de decisiones de arquitectura?
5. ¿En qué sección de un ADR se suele incluir la justificación de una propuesta arquitectónica?
¿Decisión creativa?
6. Suponiendo que no necesita una sección de Alternativas separada, ¿en qué sección de una
ADR ¿Podrías enumerar las alternativas a la solución que propones?
7. ¿Cuáles son los tres criterios básicos con los que calificaría el estado de un ADR como
¿Propuesto?
2. ¿Cuáles son algunas formas de mostrar la dirección de un riesgo particular dentro de una evaluación de
riesgos? ¿Se le ocurren otras formas de indicar si el riesgo está mejorando o empeorando?
4. ¿Por qué es necesario que la actividad de identificación dentro de la tormenta de riesgos sea una
¿Actividad individual y no colaborativa?
5. ¿Qué haría si tres participantes identificaran el riesgo como alto (6) para un área particular de la
arquitectura, pero otro participante lo identificara solo como medio (3)?
1. ¿Qué es el apego irracional a los artefactos y por qué es importante con respecto a...
¿Documentar y diagramar la arquitectura?
3. Al diagramar la arquitectura, ¿qué significan las líneas punteadas entre los componentes?
¿significar?
4. ¿Qué es el antipatrón del cadáver acribillado a balazos? ¿Cómo se puede evitar este antipatrón al
crear presentaciones?
5. ¿Cuáles son los dos canales de información principales que tiene un presentador cuando da una conferencia?
¿presentación?
1. ¿Cuáles son los tres tipos de personalidades arquitectónicas? ¿Qué tipo de límites crea cada una de ellas?
2. ¿Cuáles son los cinco factores que intervienen en la determinación del nivel de control que debe tener?
¿exposición en el equipo?
3. ¿Cuáles son las tres señales de advertencia que puedes observar para determinar si tu equipo está obteniendo buenos resultados?
¿demasiado grande?
4. Enumere tres listas de verificación básicas que serían útiles para un equipo de desarrollo.
2. Nombra algunas técnicas de negociación cuando una parte interesada en el negocio insiste en cinco
nueves de disponibilidad, pero realmente sólo se necesitan tres nueves.
4. ¿Por qué es importante dejar una discusión sobre el tiempo y el costo para el final de una reunión?
¿negociación?
5. ¿Qué es la regla de dividir y vencer? ¿Cómo se puede aplicar al negociar las características de la arquitectura
con un actor comercial? Dé un ejemplo.
8. ¿Cuáles son algunas técnicas para gestionar y reducir el número de reuniones a las que te invitan?
2. ¿Qué son los cuatro anillos del radar tecnológico de ThoughtWorks y qué significan? ¿Cómo se pueden
aplicar a su radar?
3. Describe la diferencia entre profundidad y amplitud del conocimiento tal como se aplica a
Arquitectos de software. ¿Qué deberían aspirar a maximizar los arquitectos?
Índice
Una aceleración de la tasa de cambio en el desarrollo de software creación de artefactos justo a tiempo, 317
presentación, 321 enfoque actor/acciones para diseñar Gran bola de barro, 85, 120
componentes, Cadáver acribillado a balazos en presentaciones
corporativas, 322
111 en el estudio de caso Going, Going, Gone, 112
Cortador de galletas, 321
productividad real (de equipos de desarrollo),
335 Cómo proteger sus activos, 282
Arquitectura basada en correo electrónico, 283
adaptabilidad, 62
administradores (red), 129 Trampa de entidad, 110
Hombre de las cavernas congelado, 30
Herramientas ADR, 285
383
Machine Translated by Google
riesgos de seguridad de la puerta de enlace de API del medición y gobierno, preguntas de autoevaluación, 375
sistema de operacional, 58
diagnóstico, 313 lógica de aplicación en unidades de listado parcial de,
procesamiento, 213 58 calificaciones en
problemas con la escalabilidad de los arquitectura basada en eventos, 207209
servidores de aplicaciones, 211 proveedores que luchan con
los Calificaciones en arquitectura en capas, 139
proveedores de servidores de bases de datos, 235 servicios de aplicación, 237 Calificaciones en arquitectura de microkernel, 160
ArchiMate, 319 Calificaciones en arquitectura de microservicios,
arquitectos (ver arquitectos de software) 263265
384 | Índice
Machine Translated by Google
elegir entre monolítico y des flechas que indican la dirección del riesgo, 301
arquitecturas homenajeadas en Going, Going, El arte de la guerra (Sun Tzu), 350
Diseño de componentes de Gone, 115116 en comunicación asincrónica, 254, 270 en arquitectura
arquitectura orientada a servicios impulsada por basada en eventos, 196197 en implementación
orquestación, 242 de microservicios de Going,
límites cuánticos para arquitectura distribuida Estudio de Going, Gone, 276
caso de Going, Going, Gone, 276 connascence asincrónico, 92, 94 auditabilidad
cuantos separados en la arquitectura basada en servicios, en Going,
175 riesgo Going, Gone caso de estudio, 96 rendimiento y,
de arquitectura, análisis, 297314 67 autenticación/
Análisis de riesgos de historias ágiles, autorización, 59 autenticidad, 61 modo de
308 evaluaciones de riesgos, reconocimiento
298 matriz de riesgos automático, 202 automatización
para, 297 tormenta de riesgos,
302308 consenso, apalancamiento,
304 identificación de áreas de riesgo, 35 en proyectos de software, impulsar hacia, 82
303 mitigación de riesgos, 307 disponibilidad, 57
ejemplos de tormenta de riesgos, 308314 disponibilidad básica en transacciones BASE, 132 en
disponibilidad del sistema de diagnóstico de enfermería, Going, Going, Gone caso de estudio, 97
310 característica de arquitectura implícita, 73 en Going,
elasticidad del sistema de diagnóstico de enfermería, Going, Gone: descubrimiento de componentes caso de
312 estudio, 114 en el sistema de
Sistema de diagnóstico de enfermería, diagnóstico de enfermería riesgo de asalto ejemplo, 310
308 Seguridad en el sistema de diagnóstico de
enfermería, 313 Preguntas de autoevaluación, 380 Italiailidad y, 60 en
Arquitectura Sumidero antipatrón, 138 arquitectura arquitectura en capas, 141
sumidero antipatrón negociación con las partes interesadas comerciales
arquitectura de microkernel y, 161 estilos de sobre, 349
Índice | 385
Machine Translated by Google
Interfaz de usuario como parte de, capacidades, moda nueva y cambiante en la arquitectura, 268
253 capacidades de transmisión en arquitectura basada en capacidad, 61
eventos, trayectoria
203 Topología del intermediario (arquitectura basada en profesional, desarrollo, 365372 desarrollo de
eventos), 180185 un radar personal, 367371 consejo de despedida,
beneficios y desventajas de, 185 ejemplo, 182 372 preguntas de
ley de Brooks, autoevaluación, 381 regla de los veinte
335 Brooks, Fred, 68, minutos, 365367 uso de las redes
335, 372 Brown, Simon, 102, 318 sociales, 371 ingeniería del
correcciones de errores, caos, 88
trabajando en, 35 animaciones Gorila del caos, 88 años
integradas, 321 animaciones Mono del caos, 88 años
integradas, 321 Construir Manifiesto de la lista de verificación (Gawande), 89, 338 listas
arquitecturas evolutivas (Ford et al.), 16, 82, 91 antipatrón de verificación, aprovechamiento, 338343
BulletRiddled lista de verificación de finalización del código del
Corpse, 322 justificaciones comerciales y técnicas para desarrollador, 340 lista de verificación de
decisiones de arquitectura, 282, 343 patrón de delegado la versión de software, 342 lista de verificación de
comercial, 136 dominios comerciales pruebas unitarias y
conocimiento de, 11 en arquitectura en funcionales, 341 coreografía de servicios de contexto
capas, 135 impulsores acotados
motores de gestión de procesos de negocio (BPM), de escritorio y de base de datos, 122 tres
187 niveles, 122 capas
cachés con nombre y lectores de datos, 222 Arquitectura del agente de solicitud de objetos comunes
(CORBA), 122
cachés con nombre en arquitectura basada en el espacio,
216 comunicación, 355 comunicar
386 | Índice
Machine Translated by Google
en diagramas C4, 318 ejemplo de sistema de Costo general en arquitecturas en capas, 140 Costo
venta de entradas para conciertos (arquitectura basada en el general en la arquitectura de microkernel, 160 Costo general
espacio), 231 concisión, en la arquitectura de canalización, 147 Costo general
355 confidencialidad, en la arquitectura basada en servicios,
61 configurabilidad, 59 176
contenedores en diagramas C4, 318 arquitectura o puerta, 321 capacidad de personalización, características
de contexto de la
katas y, 68 contexto acotado y, 245 arquitectura y, 72 dependencias cíclicas entre componentes,
8486
complejidad ciclomática
Índice | 387
Machine Translated by Google
arquitectura basada en el finalización del código del desarrollador, 340 flujo del
desarrollador, 362
espacio, 168 mapeo relacional de componentes del
marco de trabajo desarrolladores
atraídos por la complejidad, 354
a, 111 bomba de datos que envía datos a, 220 licencias
de servidores de bases negociación con, 351 rol en
los componentes, 108 roles en la
de datos, problemas con,
235 arquitectura en capas, 133 proceso de
desarrollo, separación de la arquitectura de software, 14, 101
En el sistema central de la arquitectura del microkernel,
151 equipos de desarrollo,
388 | Índice
Machine Translated by Google
322 infodecks vs. presentaciones, 324 particionamiento de Silicon Sandwiches, 271 Estudio de caso
invisibilidad, 324 de
manipulación del tiempo con herramientas de particionamiento de Silicon Sandwiches, 107 Particionado técnico versus, 249
presentación, Diseño impulsado por el dominio (DDD), 94
321 las diapositivas son la mitad de la Particionamiento de componentes y, 104
historia, 324 consistencia representacional, Event Storming, 112
315 preguntas de autoevaluación, 380 Influencia en microservicios, 245 Interfaz
directorio para almacenar ADR, 292 disolver transiciones isomorfismo de dominio/arquitectura, 256 dominios
y animaciones, 321 distancia desde la métrica de
Gone, 274277 arquitectura de microkernel con acceso Cambios de dominio y estilos de arquitectura, 268
remoto preocupaciones de dominio, traducción a la arquitectura
complementos, características, 6567
156 microservicios, 247 Servicios de dominio en arquitectura basada en servicios
Índice | 389
Machine Translated by Google
390 | Índice
Machine Translated by Google
Índice | 391
Machine Translated by Google
Función de aptitud ArchUnit para gobernar capas, gestión de registros de decisiones de arquitectura con
87 herramientas ADR publicación de
técnico en el caso de estudio de Silicon Sandwiches, 107 Doug, 144 tiempo medio
técnico de componentes, 107 topología, 133135 casos arquitectura en capas, 141 alto MTTR en arquitectura
apalancamiento, 59
392 | Índice
Machine Translated by Google
granularidad para servicios, 248 Caso práctico de los sándwiches de silicio, 271274
comunicación en, 254263 Entrada de blog "Más cáscara, menos huevo",
coreografía y orquestación, 256259 144 caché más utilizada (MFU), 230 caché más
utilizada recientemente (MRU), 230 Mule ESB, 186
Transacciones y sagas, 260263 Myers, Glenford J.,
Arquitectura distribuida, 247 interfaces, 37 The Mythical Man Month
253254 historia de, 245 (Brooks), 335
reutilización
operativa en, 250 referencias
sobre, 265 preguntas de
Arquitectura de n niveles (ver arquitectura en capas)
autoevaluación, 379 topología, 246
Naked Objects framework, 111 conflictos
mitigación del
de nombres en plataformas de programación, 39 espacios de
riesgo de la arquitectura, 307 riesgo de
nombres, 39
disponibilidad en un ejemplo de sistema de diagnóstico de
separados, para componentes de complemento de la
enfermería, 311 arquitectura de micronúcleo, 154
elasticidad de un ejemplo de sistema de diagnóstico de
Nearcache, consideraciones en la arquitectura basada
enfermería, en el espacio, 230
312 riesgos de seguridad en un ejemplo de sistema de
negociación y habilidades de liderazgo, 347363
diagnóstico de enfermería, 314
negociación y facilitación, 347353
Índice | 393
Machine Translated by Google
Negociando con las partes interesadas del negocio, Manejo de errores y orquestación en mediadores de
348 eventos, 186
Negociación con otros arquitectos, 350 Preguntas orquestación en arquitectura basada en el espacio,
de autoevaluación, 381 Arquitecto de 234
Paquetes P , 38
EL
componentes enchufables de arquitectura de microkernel
OmniGraffle, 317 implementados como, 154
implementaciones locales de arquitectura basada en el PageJones, Meilir, 92
espacio, 226 ejemplo particionamiento de componentes en
de sistema de subasta en línea (arquitectura basada en el arquitectura de microkernel, 161 en
espacio), 232 capas arquitectura de microservicios, 249 en
abiertas versus cerradas, 136 sistemas arquitectura orientada a servicios impulsada por orquestación
Antes del código abierto, las licencias eran costosas, arquitectura basada en el espacio, 234
235 Estudio de caso de Silicon Sandwiches, particionamiento
En plataformas tecnológicas, 368 técnico y de dominio, 271 habilidades
medidas operativas de características de arquitectura, 78 interpersonales, 357360
operaciones desempeño como
de intersección característica de la arquitectura, 58, 73 preocupaciones
con arquitectura de software, 17 características de de dominio traducidas a características de la arquitectura,
394 | Índice
Machine Translated by Google
PMD, 158
Marco de trabajo React, 254
componentes enchufables punto a punto en micro
arquitectura del núcleo, 154 recuperabilidad, 58
Italiailidad y, 60
política, comprensión y navegación, 12 portabilidad
rendimiento y, 67
como
característica de la arquitectura estructural, 59 definida, confiabilidad y, 61
Índice | 395
Machine Translated by Google
396 | Índice
Machine Translated by Google
Granularidad para, en microservicios, 248 en el Aprovechar las listas de verificación para los equipos
sistema central de la arquitectura de microkernel, de desarrollo,
151 338343 Hacer que los equipos de desarrollo sean efectivos,
en la implementación de microservicios de Going, Resumen de puntos importantes, 346
Going, Gone, 276 Habilidades de negociación y facilitación, 347353
evaluación de riesgos basada en, 299 Negociación con las partes interesadas comerciales,
en estilo de arquitectura basada en servicios, 163 348
instancias de servicio que utilizan caché con nombre Negociación con los desarrolladores, 351
en arquitectura basada en el espacio, Negociación con otros arquitectos, 350
217 colisiones de datos y, 225 Observación de las señales de advertencia del equipo de
capa de servicio, 104 desarrollo, 335338
Índice | 397
Machine Translated by Google
398 | Índice
Machine Translated by Google
Índice | 399
Machine Translated by Google
Lo que todo programador debería saber sobre Enfoque de flujo de trabajo para el diseño de componentes
Diseño orientado a objetos (PageJones), 92 componentes,
Por qué es más importante que cómo, 19 112 patrón de evento de flujo de trabajo, 197200
Servidor de aplicaciones Wildfly, 161 delegado de flujo de trabajo, 197
relaciones de procesador de flujo de trabajo, 198
bases de datos de flujos de trabajo identificadas incorrectamente
como, 111 Y
en arquitecturas técnicas y particionadas por dominio
Yoder, José, 120
tectura, 104
400 | Índice
Machine Translated by Google
Neal Ford es director, arquitecto de software y creador de memes en ThoughtWorks, una consultora de TI
global que se centra exclusivamente en el desarrollo y la entrega de software de extremo a extremo. Antes
de unirse a ThoughtWorks, Neal era director de tecnología en The DSW Group, Ltd., una empresa de
capacitación y desarrollo reconocida a nivel nacional.
Colofón
El animal que aparece en la portada de Fundamentos de ingeniería de software es el loro de abanico rojo
(Deroptyus accipitrinus), originario de América del Sur, donde se lo conoce con varios nombres, como loro
cacique en español o anacã, papagaiodecoleira y vanaquiá en portugués. Esta ave del Nuevo Mundo vive
en las copas de los árboles y en los huecos de los árboles de la selva amazónica, donde se alimenta de los
frutos del árbol Cecropia, acertadamente conocido como “dedos de serpiente”, así como de los frutos duros
de varias palmeras.
Como único miembro del género Deroptyus, el loro de abanico rojo se distingue por las plumas de color rojo
intenso que cubren su nuca. Su nombre proviene del hecho de que esas plumas se "despliegan" cuando se
siente excitado o amenazado y revelan el azul brillante que resalta cada punta. La cabeza está rematada por
una corona blanca y ojos amarillos, con mejillas marrones con vetas blancas. El pecho y el vientre del loro
están cubiertos de las mismas plumas rojas sumergidas en azul, en contraste con las plumas verdes brillantes
en capas de su espalda.
Entre diciembre y enero, el loro de abanico rojo encuentra a su pareja de por vida y luego comienza a poner
de 2 a 4 huevos al año. Durante los 28 días en que la hembra incuba los huevos, el macho le brinda cuidados
y apoyo. Después de aproximadamente 10 semanas, las crías están listas para comenzar a emplumar en la
naturaleza y comenzar su vida de 40 años en la selva tropical más grande del mundo.
Si bien el estado de conservación actual del loro de abanicos rojos está designado como de preocupación
menor, muchos de los animales en las portadas de O'Reilly están en peligro de extinción; todos ellos son
importantes para el mundo.
registrada
O'Reilly
Media,
©2019
marca
una
Inc.
de
es
|