Read in English · Lire en français · Auf Deutsch lesen
Sección 2.6 de 2.8 · Intermedio · 22 min de lectura
Modificabilidad, capacidad de prueba y desplegabilidad: diseñar para el cambio
Videolección
5 min · narrado en inglés, con subtítulosSolo escuchar (audio)
Leer la transcripción
La mayor parte del costo de un sistema de éxito llega después de su primer lanzamiento, a medida que se cambia una y otra vez. Esta lección trata de diseñar para ese cambio.
Piensa en una cocina. Si el horno está empotrado en la pared, con las tuberías enterradas en hormigón, cambiarlo supone derribar la pared. Si se conecta a un enchufe estándar, lo cambias en una tarde. Con el software ocurre lo mismo. Las partes que van a cambiar reciben conexiones estándar. Después facilitas comprobar que todo sigue funcionando tras el cambio, y haces que entregar la nueva versión sea una rutina y no un riesgo.
Esos tres pasos son tres cualidades. La modificabilidad trata del costo y el riesgo de hacer un cambio. La capacidad de prueba trata de la facilidad con la que puedes demostrar, mediante pruebas, que el sistema se comporta como se pretende. Y la desplegabilidad trata de la rapidez, la seguridad y la previsibilidad con que un cambio llega a producción, y de la rapidez con que puede retirarse de nuevo. Forman un ciclo: un sistema modular sin pruebas rápidas sigue cambiando despacio.
La modificabilidad no significa nada hasta que dices qué se espera que cambie. Planifica para todos los cambios posibles y sobrediseñarás; no planifiques para ninguno y cada cambio será una reescritura. Así que hazte cuatro preguntas. Primera: ¿qué puede cambiar: funciones, plataformas, socios o carga? Segunda: ¿qué probabilidad tiene? Los proveedores de pagos y las normas fiscales cambian a menudo. La idea de pedido rara vez cambia. Dedica el esfuerzo de diseño a donde el cambio es probable. Tercera: ¿quién hace el cambio, y cuándo? Un desarrollador en el código, un ingeniero mediante la configuración o un responsable de producto que activa un feature flag. El momento en que se fija una decisión se llama su momento de vinculación. Y cuarta: ¿cuánto cuesta, en esfuerzo, tiempo y riesgo? Las respuestas te dan un escenario que se puede probar.
Esta es una táctica clave: reducir el acoplamiento con un intermediario. Antes, el proceso de pago, los reembolsos y las suscripciones hablan cada uno directamente con todos los proveedores de pagos. Son seis dependencias, y un proveedor nuevo obliga a cambiar tres servicios. Después, los tres dependen de una única interfaz de pagos, que oculta detrás a los proveedores. Cada proveedor tiene su propio adaptador. Añadir un proveedor supone ahora añadir un adaptador, y quienes llaman no cambian en absoluto.
Una empresa de reparto de comida se conecta a los sistemas de punto de venta de los restaurantes. Cada nuevo proveedor requiere veinte días-persona de trabajo y pruebas. A seiscientas libras por día, son doce mil libras. Ventas prevé ocho proveedores nuevos este año: noventa y seis mil libras. El arquitecto propone una interfaz de adaptadores. Construirla cuesta dieciocho mil libras, una sola vez. Después, cada proveedor solo necesita cuatro días-persona: dos mil cuatrocientas libras. Así que ocho proveedores cuestan treinta y siete mil doscientas libras en total, con un ahorro de cincuenta y ocho mil ochocientas libras en el primer año. La inversión se amortiza con el segundo proveedor. Pero solo si los proveedores llegan de verdad. Por eso un requisito de modificabilidad debe decir qué es probable que cambie.
Ahora, la capacidad de prueba. Un componente se puede probar cuando una prueba puede controlar sus entradas y su estado, y observar lo que hizo. El código que llama a un servicio de pagos real o lee directamente el reloj del sistema es difícil de controlar. La solución es la inyección de dependencias. En producción, el servicio de pedidos solo depende de una interfaz de pasarela de pagos, implementada por una pasarela que hace llamadas de red reales. En una prueba unitaria, el mismo servicio de pedidos recibe en su lugar una pasarela falsa. Esta da respuestas preparadas y registra cada llamada, así que la prueba tiene el control total, sin red y sin esperas.
Por último, la desplegabilidad. La idea central son los lotes pequeños. Un lanzamiento con un solo cambio es fácil de razonar y fácil de revertir. Un lanzamiento con tres meses de trabajo contiene cientos de cambios que interactúan. Los lotes pequeños necesitan automatización: un pipeline que compila, prueba y despliega cada cambio de la misma manera, sin pasos manuales que alguien pueda olvidar. La arquitectura ayuda con partes desplegables de forma independiente, cambios compatibles con versiones anteriores y despliegues progresivos, primero a una pequeña parte del tráfico. La investigación del programa DevOps Research and Assessment, conocido como Dora, encontró cinco medidas del rendimiento de la entrega, y que los mejores equipos son rápidos y estables a la vez. La arquitectura débilmente acoplada va unida a puntuaciones más altas.
La sección completa trata el momento de vinculación, los tipos de doble de prueba, un costoso fallo de despliegue y, en detalle, las métricas de Dora. A continuación, en la Sección dos punto siete, veremos la seguridad, la usabilidad y más. Nos vemos allí.
Lo que necesitas saber
- La modificabilidad es el costo y el riesgo del cambio; especifícala diciendo qué es probable que cambie, quién hace el cambio, cuándo se vincula y cuánto puede costar el cambio.
- Las tácticas de modificabilidad aumentan la cohesión, reducen el acoplamiento (encapsular, usar un intermediario, restringir las dependencias) y difieren la vinculación, pero cada momento de vinculación más tardío añade maquinaria.
- La capacidad de prueba depende de la controlabilidad y la observabilidad; aísla las dependencias detrás de interfaces e inyéctalas para que las pruebas puedan usar dobles de prueba.
- La desplegabilidad se basa en lotes pequeños, automatización, unidades desplegables de forma independiente, cambios compatibles con versiones anteriores, despliegues progresivos y un rollback rápido.
- Las métricas actuales de entrega de software de DORA son el tiempo de entrega de cambios, la frecuencia de despliegue, el tiempo de recuperación de despliegues fallidos, la tasa de fallos de cambios y la tasa de retrabajo de despliegues.
- La mantenibilidad de ISO/IEC 25010:2023 tiene cinco subcaracterísticas: modularidad, reusabilidad, analizabilidad, modificabilidad y capacidad de prueba.
Tres cualidades relacionadas con el cambio
La mayor parte del costo de un sistema de éxito se produce después de su primer lanzamiento, a medida que se cambia una y otra vez. Tres cualidades relacionadas describen lo bien que una arquitectura lo facilita. La modificabilidad trata del costo y el riesgo de hacer un cambio. La capacidad de prueba (testabilidad) trata de la facilidad con la que puedes demostrar, mediante pruebas, que el sistema (o una parte de él) se comporta como se pretende, y de la facilidad con la que los defectos se ponen de manifiesto. La desplegabilidad trata de la rapidez, la seguridad y la previsibilidad con que un cambio puede ponerse en producción, y retirarse de nuevo.
Están unidas en un ciclo. Un cambio solo es barato si puedes hacerlo en un único lugar (modificabilidad), saber rápidamente que no has roto nada (capacidad de prueba) y ponerlo en producción sin ceremonias (desplegabilidad). Un sistema modular pero sin pruebas rápidas seguirá cambiando despacio, porque cada cambio necesita semanas de pruebas de regresión manuales. Un sistema con buenas pruebas pero con una ventana de lanzamiento trimestral seguirá entregando valor despacio.
Modificabilidad: cuatro preguntas sobre cualquier cambio
Bass, Clements y Kazman sostienen que la modificabilidad no tiene sentido hasta que dices qué se espera que cambie. Planificar para todos los cambios posibles produce un sistema sobrediseñado, lleno de puntos de extensión que no se usan; no planificar para ninguno produce un sistema en el que cada cambio es una reescritura. Cuatro preguntas precisan el requisito.
¿Qué puede cambiar? Funciones, plataformas (una nueva versión de la base de datos, el paso a otra nube), el entorno (una nueva API de un socio, una nueva normativa), las cualidades (el doble de carga) o la capacidad. ¿Qué probabilidad tiene el cambio? Dedica el esfuerzo de diseño a donde el cambio es probable: los proveedores de pagos, las normas fiscales y las interfaces de usuario cambian a menudo; el concepto de pedido rara vez lo hace. ¿Quién hace el cambio y cuándo? Un desarrollador al programar, un ingeniero de lanzamientos en el despliegue, un administrador mediante la configuración o un usuario final mediante los ajustes. El momento en que se fija una decisión se llama su momento de vinculación (binding time). ¿Cuánto cuesta el cambio? El esfuerzo, el tiempo transcurrido y el dinero necesarios para hacerlo, probarlo y desplegarlo, más el número de otros elementos afectados y el riesgo de introducir defectos.
Responder a esas preguntas da un escenario del tipo presentado en la Sección 2.3: Un desarrollador añade soporte para un nuevo proveedor de pagos, sin cambiar ningún módulo existente salvo la configuración, en 3 días-persona como máximo, incluidas las pruebas, sin aumento de los errores en el proceso de pago.
Escenarios de modificabilidad con distintas fuentes y momentos de vinculación
| Quién cambia | Qué cambia | Cuándo se vincula | Medida de la respuesta |
|---|---|---|---|
| Desarrollador | Añadir un nuevo socio de reparto a una plataforma de reparto de comida | Al programar | Solo cambia el adaptador del socio; hecho, probado y desplegado en 5 días |
| Responsable de producto | Activar un nuevo flujo de pago para el 10% de los usuarios | En ejecución (feature flag) | Surte efecto en 1 minuto, sin despliegue |
| Ingeniero de operaciones | Apuntar el sistema a un nuevo host de base de datos | En el despliegue (configuración) | Sin cambios de código; una ejecución del pipeline de menos de 15 minutos |
| Administrador del cliente | Añadir un campo personalizado a una factura | En ejecución (ajustes) | Sin intervención del proveedor; disponible de inmediato |
| Equipo de plataforma | Actualizar el framework web a una nueva versión principal | En la compilación | Cambian menos de 20 archivos fuera de una capa anticorrupción; menos de 2 semanas |
Tácticas de modificabilidad
Las tácticas de Software Architecture in Practice reducen el costo del cambio limitando hasta dónde se propaga. Se basan en dos ideas antiguas, tratadas a fondo en el Capítulo 3. La cohesión mide hasta qué punto las responsabilidades de un módulo van juntas; el acoplamiento mide cuánto depende un módulo de otro. Un cambio probable debería afectar a un único módulo cohesivo, y ese módulo debería estar débilmente acoplado al resto.
Aumentar la cohesión. Divide un módulo que hace dos tareas sin relación (un CustomerService que gestiona tanto el inicio de sesión como los puntos de fidelidad) y mueve las responsabilidades a donde corresponden, para que un cambio probable caiga en un solo lugar.
Reducir el acoplamiento. Encapsular: oculta el funcionamiento interno de un módulo detrás de una interfaz explícita, siguiendo el principio de ocultación de información de David Parnas (1972), para que quienes lo llaman no puedan depender de lo que puede cambiar. Usar un intermediario: pon algo entre dos partes para que ninguna conozca directamente a la otra: un adaptador, un intermediario de mensajes (message broker), un canal de publicación-suscripción, un repositorio delante de una base de datos o un API gateway. Restringir las dependencias: decide qué módulos pueden llamar a cuáles (reglas de capas, un módulo visible solo para su propio paquete) y hazlo cumplir con herramientas. Abstraer los servicios comunes: proporciona el comportamiento compartido una sola vez, detrás de una interfaz, en lugar de copiarlo.
Diferir la vinculación. Fija una decisión tan tarde como sea útil, para que el cambio pueda hacerse más adelante y por alguien más alejado del código: archivos de configuración, variables de entorno, plug-ins descubiertos al arrancar, descubrimiento de servicios y feature flags. Cada momento de vinculación más tardío añade maquinaria (configuración que validar, flags que eliminar, interfaces de plug-in versionadas), así que difiere solo las decisiones que realmente varían.
Usar un intermediario para contener el cambio
Momento de vinculación (binding time)
Guía de decisión
Guía de decisión: ¿cuánto debería retrasarse la vinculación de esta decisión?
Úsala cuando una parte interesada diga "esto podría cambiar". Empieza por arriba y detente en el primer sí.
- ¿Es poco probable el cambio, o necesitaría código nuevo y pruebas nuevas de todos modos?SíVincula al programar. Mantenlo simple y bien encapsulado para que el cambio siga siendo local cuando llegue.NoPasa a la siguiente pregunta.
- ¿El valor solo difiere entre entornos (pruebas, preproducción, producción) o entre las instalaciones de distintos clientes?SíVincula en el despliegue: variables de entorno o configuración inyectada por el pipeline, guardadas en el control de versiones.NoPasa a la siguiente pregunta.
- ¿Necesitan terceros u otros equipos añadir comportamiento sin cambiar tu código?SíVincula en el arranque o en ejecución con una interfaz de plug-ins o de extensión, y versiona esa interfaz con cuidado.NoPasa a la siguiente pregunta.
- ¿Deben personas que no son desarrolladores activar o desactivar un comportamiento rápidamente, o debes lanzar primero a una fracción de los usuarios?SíVincula en ejecución con un feature flag, y da a cada flag un responsable y una fecha de eliminación.NoVincula en la compilación o en el despliegue; una vinculación más tardía añadiría maquinaria que nadie necesita.
Ejemplo práctico
Ejemplo práctico: ¿cuánto vale el escenario de modificabilidad?
Una empresa de reparto de comida integra los sistemas de punto de venta de los restaurantes. Hoy, cada nuevo proveedor de punto de venta requiere cambios en los servicios de carta, pedidos y reembolsos: unos 15 días-persona de trabajo más un ciclo de pruebas de regresión de 5 días. Ventas prevé 8 nuevos proveedores en los próximos 12 meses. El arquitecto propone una interfaz de adaptadores para proveedores (como en el diagrama anterior). Supón un costo completo, con todos los gastos incluidos, de £600 por día-persona.
| Costo por proveedor hoy | 15 + 5 = 20 días-persona, así que 20 x £600 = £12 000 |
|---|---|
| Costo de 8 proveedores hoy | 8 x £12,000 = £96,000 |
| Costo único de la refactorización | Diseñar y construir la interfaz y migrar los 3 proveedores existentes: 30 días-persona = £18 000 |
| Costo por proveedor después | Escribir un adaptador (3 días) más pruebas de contrato contra la interfaz (1 día): 4 días-persona = £2400 |
| Costo de 8 proveedores después | £18,000 + 8 x £2,400 = £37,200 |
| Ahorro en el primer año | £96,000 - £37,200 = £58,800 |
| Punto de equilibrio | Cada proveedor ahorra £12 000 - £2400 = £9600, así que las £18 000 se recuperan tras £18 000 / £9600 = 1.9, es decir, con el segundo proveedor nuevo |
El cálculo solo es tan bueno como la predicción del cambio. Si ventas no consigue ningún proveedor nuevo, la refactorización es puro costo. Por eso los requisitos de modificabilidad deben decir qué es probable que cambie.
El plazo suele importar más que el costo: reducir la incorporación de un proveedor de unas 4 semanas a menos de 1 semana puede hacer ganar contratos, algo que ninguna suma de días-persona recoge.
La nueva interfaz de adaptadores es en sí misma una obligación. Cambiarla más adelante afecta a todos los adaptadores, así que merece un diseño y un versionado cuidadosos.
Capacidad de prueba: controlabilidad y observabilidad
Un componente se puede probar cuando una prueba puede ponerlo en un estado conocido, darle entradas elegidas y ver qué hizo. Dos propiedades lo recogen. La controlabilidad es la capacidad de fijar las entradas y el estado interno de un componente desde una prueba. La observabilidad (en el sentido de las pruebas) es la capacidad de ver sus salidas y el estado interno relevante. El código que lee directamente el reloj del sistema, llama a un servicio de pagos real, elige números aleatorios o escribe en una base de datos compartida es difícil de controlar; el código que oculta sus resultados en un estado privado o solo en el texto de los logs es difícil de observar.
Por eso, las tácticas arquitectónicas de capacidad de prueba buscan dar a las pruebas control y visibilidad, y limitar la complejidad. Aísla las dependencias detrás de interfaces y usa luego la inyección de dependencias: el componente recibe sus colaboradores (un reloj, una pasarela de pagos, un repositorio) desde fuera en lugar de crearlos, para que una prueba pueda pasarle un sustituto. Esos sustitutos son dobles de prueba, un término popularizado por Gerard Meszaros: un stub devuelve respuestas predefinidas, un fake es una implementación ligera que funciona (un repositorio en memoria), un mock comprueba que se hicieron las llamadas esperadas y un spy registra las llamadas para hacer aserciones después. Proporciona interfaces de prueba: ganchos para fijar el estado, grabar y reproducir tráfico o ejecutar en un entorno aislado (sandbox). Limita el no determinismo: evita la concurrencia oculta y el estado global, y haz que el tiempo y la aleatoriedad se puedan inyectar. Limita la complejidad estructural: menos dependencias y ningún ciclo significan preparaciones de prueba más pequeñas.
La arquitectura también da forma a la estrategia de pruebas en niveles superiores. En un sistema de servicios, cada límite necesita pruebas de contrato que comprueben que ambos lados están de acuerdo sobre la API, y unas pocas pruebas de extremo a extremo que recorran el camino real. Un diseño con límites limpios permite que la mayoría de las pruebas se ejecuten rápido y de forma aislada, mientras que un diseño enmarañado obliga a usar pruebas de extremo a extremo lentas y frágiles para todo.
La inyección de dependencias hace controlable un componente
class OrderService:
def __init__(self, gateway, clock):
self.gateway = gateway # anything with charge(amount, card)
self.clock = clock # anything with now()
def place(self, order):
if self.clock.now().hour >= 23:
return "kitchen closed"
return self.gateway.charge(order.total, order.card)
# In a test: full control, no network, no waiting until 11 pm
class FakeClock:
def __init__(self, t): self.t = t
def now(self): return self.t
class FakeGateway:
def __init__(self): self.calls = []
def charge(self, amount, card):
self.calls.append(amount)
return "approved"Desplegabilidad
La desplegabilidad mide con qué previsibilidad y a qué costo pasa un cambio del commit de un desarrollador a producción, y con qué rapidez se puede deshacer. Se convirtió en una cualidad de primera clase solo en la última década, cuando la entrega continua demostró que la frecuencia de lanzamiento y la estabilidad no son opuestas. La cuarta edición de Software Architecture in Practice (2021) le dedicó un capítulo.
La idea central son los lotes pequeños. Un lanzamiento que contiene un solo cambio es fácil de probar, fácil de razonar y fácil de revertir; un lanzamiento con tres meses de trabajo contiene cientos de cambios que interactúan, así que los fallos son probables y difíciles de diagnosticar. Los lotes pequeños requieren automatización: un pipeline de despliegue que compila, prueba y despliega cada cambio de la misma manera, infraestructura mediante scripts y ningún paso manual que alguien pueda olvidar. Entre las tácticas arquitectónicas están las unidades desplegables de forma independiente (para que el lanzamiento de un equipo no espere al de otro), las interfaces y migraciones de base de datos compatibles con versiones anteriores, los mecanismos de rollback y de roll forward, los despliegues progresivos (lanzamientos canario primero a una pequeña parte del tráfico, conmutación azul-verde entre dos entornos) y los feature flags, que separan desplegar el código de lanzar una función a los usuarios. Los pipelines y las estrategias se tratan en CI/CD y estrategias de despliegue.
El costo de ignorar la desplegabilidad puede ser grave. En agosto de 2012, la empresa de trading Knight Capital desplegó manualmente código nuevo en sus ocho servidores de enrutamiento de órdenes, pero se olvidó de uno. Un flag de configuración reutilizado activó entonces código obsoleto en ese servidor, que inundó el mercado de órdenes, produjo unos 4 millones de ejecuciones en aproximadamente 45 minutos y le costó a la empresa unos 460 millones de dólares estadounidenses. Un despliegue automatizado y verificado, o la eliminación del código muerto, lo habrían evitado cada uno por sí solo.
Medir la entrega: las métricas DORA
El programa de investigación DORA (DevOps Research and Assessment, descrito en Accelerate por Nicole Forsgren, Jez Humble y Gene Kim, 2018, y continuado en informes anuales que ahora se elaboran dentro de Google Cloud) descubrió que un pequeño conjunto de medidas predice el rendimiento de la entrega de software, y que los mejores equipos son rápidos y estables a la vez. El modelo actual tiene cinco métricas de rendimiento de la entrega de software, agrupadas en rendimiento (throughput) e inestabilidad. Sus nombres han evolucionado: el antiguo tiempo medio de restauración
pasó a ser el tiempo de recuperación de despliegues fallidos en 2023, y la tasa de retrabajo de despliegues se añadió en 2024.
Dos advertencias. Primera: estas métricas describen el sistema de entrega de un equipo, no a las personas; usarlas para clasificar a las personas invita a hacer trampas. Segunda: son resultados. La arquitectura influye mucho en ellas: los equipos que pueden desplegar su parte de forma independiente, probarla de forma aislada y revertirla rápidamente obtienen mejores resultados, y esa es una de las razones por las que la investigación de DORA relaciona la arquitectura débilmente acoplada con un mayor rendimiento de la entrega.
Métricas de rendimiento de la entrega de software de DORA (dora.dev, modelo actual)
| Métrica | Grupo | Qué mide | Palancas arquitectónicas |
|---|---|---|---|
| Tiempo de entrega de cambios | Rendimiento (throughput) | Tiempo desde que se hace commit de un cambio en el control de versiones hasta que se ejecuta en producción | Pruebas automatizadas rápidas, unidades pequeñas desplegables de forma independiente, sin traspasos entre equipos |
| Frecuencia de despliegue | Rendimiento (throughput) | Con qué frecuencia se despliegan cambios en producción (o el tiempo entre despliegues) | Desplegabilidad independiente, pipeline automatizado, feature flags |
| Tiempo de recuperación de despliegues fallidos | Rendimiento (throughput) | Tiempo para recuperarse de un despliegue que falla y requiere intervención inmediata | Rollback automatizado, lanzamientos canario, buena monitorización, cambios pequeños |
| Tasa de fallos de cambios | Inestabilidad | Proporción de despliegues que requieren intervención inmediata, como un rollback o un hotfix | Capacidad de prueba, pruebas de contrato, cambios compatibles con versiones anteriores |
| Tasa de retrabajo de despliegues | Inestabilidad | Proporción de despliegues no planificados que se producen a causa de un incidente en producción | Calidad de las pruebas y las revisiones; observabilidad que detecta los problemas pronto |
La mantenibilidad en ISO/IEC 25010
ISO/IEC 25010:2023 agrupa estas inquietudes bajo la característica mantenibilidad, con cinco subcaracterísticas: modularidad (el sistema está formado por componentes discretos, de modo que un cambio en uno tiene un impacto mínimo en los demás), reusabilidad (un activo puede usarse en más de un sistema o para construir otros activos), analizabilidad (la facilidad con la que puedes evaluar el impacto de un cambio, diagnosticar una deficiencia o encontrar las partes que hay que modificar), modificabilidad (el sistema puede cambiarse sin introducir defectos ni degradar la calidad) y capacidad de prueba (se pueden establecer criterios de prueba y realizar pruebas para determinar si se cumplen). La desplegabilidad no tiene una subcaracterística propia en la norma; la instalabilidad y la reemplazabilidad se encuentran bajo la flexibilidad. El modelo es una lista de comprobación, como explica la Sección 2.2; los escenarios son lo que hace concreto cada elemento.
Comprueba lo que has entendido
¿Por qué "el sistema deberá ser fácil de cambiar" no es un requisito útil?
No dice qué cambiará, quién lo cambiará, cuándo, ni qué costo es aceptable, así que nadie puede diseñar para cumplirlo ni comprobar si se ha cumplido.
¿Cuál es la diferencia entre un stub y un mock?
Un stub devuelve respuestas predefinidas para que la prueba pueda controlar las entradas; un mock además comprueba que se hicieron las llamadas esperadas, así que la prueba verifica las interacciones.
¿Por qué ayudan los feature flags a la desplegabilidad?
Separan desplegar el código de lanzar una función, de modo que las funciones incompletas o arriesgadas pueden desplegarse desactivadas, lanzarse de forma gradual y volver a desactivarse sin un nuevo despliegue.
Un equipo despliega una vez al mes y cada lanzamiento contiene unos 200 cambios. ¿Qué métricas DORA es probable que se resientan, y por qué?
El tiempo de entrega de cambios (los cambios esperan semanas al lanzamiento), la frecuencia de despliegue y, probablemente, la tasa de fallos de cambios y el tiempo de recuperación, porque los lotes grandes tienen más probabilidad de fallar y son más difíciles de diagnosticar y de revertir.
Fuentes y lecturas recomendadas
¿Tienes una pregunta sobre esta sección? ArchitectBot, el asistente de estudio con IA del curso, responde primero a partir del curso.
Pregunta: “Tenemos un monolito que necesita tres semanas de pruebas manuales antes de cada lanzamiento. ¿Qué cambios arquitectónicos nos permitirían desplegar cada semana sin más riesgo?”