Saltar al contenido principal
Jordi Izquierdo Montalbán
Lo que practico

Fundamentos

Arquitectura

Elijo la estructura según el problema y dejo cada decisión por escrito.

Qué decide realmente una arquitectura

Una arquitectura no es un dibujo de cajas: es el conjunto de decisiones caras de revertir que condicionan cómo evoluciona un sistema. Cómo se parte en piezas, cómo se hablan esas piezas, dónde vive cada dato y qué se despliega junto con qué. Todo lo demás (el framework de moda, el nombre de las carpetas) se puede cambiar con un fin de semana; esto no.

Dos ideas ordenan todo lo que sigue:

  • Cada estilo es una respuesta a un conjunto concreto de fuerzas. No hay estilos buenos y malos, hay estilos que encajan o no con el problema, el equipo y el momento.
  • Toda decisión tiene un precio. Lo que un estilo mejora, otro atributo lo paga. El trabajo del arquitecto es hacer ese intercambio explícito y consciente.

Atributos de calidad: lo que de verdad elige la arquitectura

Los requisitos funcionales casi nunca deciden la arquitectura; los atributos de calidad sí. El modelo de calidad del producto de ISO/IEC 25010 sirve como lista de comprobación común:

CaracterísticaPregunta que plantea
Adecuación funcional¿Hace lo que se necesita, de forma completa y correcta?
Eficiencia de desempeño¿Cuánto tarda, cuántos recursos consume, hasta dónde escala?
Compatibilidad¿Convive e intercambia información con otros sistemas?
Usabilidad¿Se aprende y se usa sin fricción?
Fiabilidad¿Madurez, disponibilidad, tolerancia a fallos, recuperación?
Seguridad¿Confidencialidad, integridad, trazabilidad, autenticidad?
Mantenibilidad¿Modularidad, reutilización, facilidad de análisis, de cambio y de prueba?
Portabilidad¿Se adapta, se instala y se sustituye con facilidad?

Como en cualquier sistema real no caben todas al máximo, se priorizan. Un buen ejercicio es elegir las tres o cuatro que dominan y hacerlas medibles: «la búsqueda responde en menos de medio segundo para el percentil 95» es un requisito; «tiene que ser rápido» no lo es.

Escenarios de calidad

La forma más útil de concretar un atributo es el escenario: fuente del estímulo, estímulo, entorno, artefacto afectado, respuesta esperada y medida de la respuesta.

Fuente:     usuarios finales
Estímulo:   pico de tráfico al abrir una campaña
Entorno:    funcionamiento normal
Artefacto:  servicio de catálogo
Respuesta:  sigue sirviendo páginas sin degradar el resto del sistema
Medida:     tiempo de respuesta del percentil 95 dentro del objetivo acordado

Con escenarios escritos se puede comparar objetivamente dos alternativas y, más tarde, comprobar si la arquitectura los cumple.

Compromisos, leyes y principios que condicionan todo

Los compromisos clásicos

Se ganaSe paga
Desacoplamiento entre piezasMás comunicación, más fallos posibles en la red
Escalado independienteMás infraestructura y más operación
Consistencia fuerteMenos disponibilidad y más latencia al repartir datos
Flexibilidad y extensibilidadIndirección y curva de aprendizaje
Despliegue independienteCoordinación de contratos y versiones
Simplicidad operativaMenos aislamiento de fallos

Teorema CAP y modelo PACELC

En un sistema de datos distribuido, ante una partición de red hay que elegir entre consistencia (todos ven el mismo dato) y disponibilidad (todos reciben respuesta). Las particiones no se eligen: ocurren. Por eso la elección real es qué sacrificar cuando ocurren. PACELC lo completa: incluso sin partición hay que elegir entre latencia y consistencia. De ahí salen decisiones como replicación síncrona frente a asíncrona, o consistencia eventual aceptada de forma explícita en ciertos flujos.

Ley de Conway

Las organizaciones diseñan sistemas que copian su propia estructura de comunicación.

Se puede usar a favor (la maniobra inversa de Conway): se diseña primero la estructura de equipos que se quiere y la arquitectura tiende a seguirla. Una arquitectura en la que dos equipos deben coordinarse para cada cambio es síntoma de que las fronteras del código no coinciden con las del equipo.

Principios de diseño que se repiten en todos los estilos

  • Alta cohesión, bajo acoplamiento dentro y entre módulos.
  • Separación de responsabilidades: cada pieza tiene una razón principal para cambiar.
  • Ocultar información: se expone un contrato estrecho y se esconde cómo está hecho por dentro.
  • Dependencias hacia lo estable: lo que cambia poco no debe depender de lo que cambia mucho.
  • Diseñar para el fallo: toda llamada que cruza una frontera puede fallar, tardar o duplicarse.

DDD estratégico: dónde poner las fronteras

Antes de elegir estilo hay que decidir qué se parte y por dónde. El diseño guiado por el dominio (DDD) aporta el vocabulario del lado estratégico:

  • Lenguaje ubicuo: negocio y equipo técnico usan los mismos términos, y el código los refleja.
  • Dominio y subdominios: el núcleo (lo que diferencia al negocio y merece más inversión), los de soporte (necesarios pero no diferenciales) y los genéricos (resueltos y comprables, como la facturación estándar o la autenticación).
  • Contexto delimitado: el límite dentro del cual un modelo y un término tienen un significado único. «Cliente» en ventas y «cliente» en soporte pueden ser conceptos distintos y conviene que lo sean.
  • Mapa de contextos: cómo se relacionan los contextos entre sí.

Relaciones habituales entre contextos:

RelaciónSignificado
Cliente-proveedorUn contexto aguas arriba sirve a otro aguas abajo, con necesidades negociadas
ConformistaEl de abajo acepta el modelo del de arriba tal cual
Capa anticorrupciónEl de abajo traduce el modelo ajeno para no contaminar el suyo
Servicio de lenguaje publicadoUn contrato público y estable que consumen muchos
Núcleo compartidoUn subconjunto del modelo que dos equipos mantienen juntos (se usa con cuidado)
Caminos separadosNo se integran: cada uno resuelve lo suyo

Un contexto delimitado es el candidato natural a módulo en un monolito modular y a servicio en microservicios. Partir por capas técnicas en lugar de por contextos suele producir sistemas donde cada cambio de negocio atraviesa todo.

Catálogo de estilos arquitectónicos

Para cada estilo: qué es, su flujo de trabajo y cuándo no conviene.

Monolito

Toda la aplicación, un único artefacto desplegable.

Una sola aplicación desplegable que contiene toda la lógica y habla con una base de datos.

Flujo de trabajo: un repositorio, una compilación, una batería de pruebas y un despliegue. Un cambio se prueba entero y se publica entero. Depurar es sencillo porque todo ocurre en un proceso, y las transacciones son las de la base de datos.

Fortalezas: simplicidad, rendimiento de las llamadas internas, operación barata, refactorización asistida por el compilador.

Cuándo no usarlo: cuando muchos equipos se bloquean entre sí en el mismo despliegue, o cuando una parte necesita escalar o desplegarse con un ritmo radicalmente distinto al resto.

Monolito modular

Un solo despliegue, pero con módulos delimitados que se comunican únicamente por interfaces públicas.

Un solo despliegue, pero con módulos que solo se hablan por interfaces públicas.

Flujo de trabajo: se identifican los contextos delimitados y cada uno se convierte en un módulo con su API interna. Los datos se separan por esquema o por propietario, y las reglas de importación se comprueban automáticamente. Si algún día un módulo debe salir como servicio, la frontera ya existe.

Fortalezas: casi toda la ventaja organizativa de los microservicios con la operación de un monolito.

Cuándo no usarlo: si no hay disciplina para mantener las fronteras. Sin comprobación automática, los módulos acaban importándose entre sí y el resultado es un monolito enredado con otro nombre.

Arquitectura en capas (N-tier)

Se organiza el código por responsabilidad técnica: presentación, lógica, acceso a datos. Una capa solo conoce a la inferior.

Cada capa solo conoce a la que tiene debajo.

Flujo de trabajo: una petición baja de la presentación a los datos y la respuesta sube por el mismo camino. Se distingue entre capas cerradas (solo se llama a la inmediatamente inferior) y abiertas (se puede saltar), y se documenta cuál es cuál.

Cuándo no usarlo: cuando las reglas de negocio son ricas y cambian mucho: acaban repartidas entre capas. Aparece también el antipatrón del «sumidero»: peticiones que atraviesan capas sin que ninguna aporte nada.

Cliente-servidor

Un servidor concentra la lógica y los datos; varios clientes los consumen por un protocolo común.

El cliente pide, el servidor responde y concentra la lógica y los datos.

Flujo de trabajo: el contrato entre ambos se define primero; cliente y servidor evolucionan por separado mientras lo respeten. Es la base de casi todo lo demás: una web, una app móvil y una integración externa son clientes distintos de un mismo servidor.

Cuándo no usarlo: si los clientes necesitan funcionar sin conexión de forma prolongada, o si el servidor es un punto único de fallo intolerable. En esos casos se miran estrategias offline-first o sin punto central.

Hexagonal (puertos y adaptadores)

El dominio define los puertos (interfaces que necesita) y la infraestructura los implementa con adaptadores. Protege la lógica de negocio de la tecnología.

El dominio queda en el centro y no depende de nada externo: todo lo demás se enchufa a través de puertos.

Flujo de trabajo: se escribe primero el dominio con sus pruebas, usando adaptadores falsos en memoria. Después se añaden los adaptadores reales (base de datos, cola, API externa) y se comprueba que cumplen el puerto. Cambiar de base de datos o de proveedor no toca las reglas.

Cuándo no usarlo: en un CRUD sencillo sin lógica real: añade interfaces y traducciones sin beneficio.

Arquitectura limpia (onion)

Variante concéntrica del mismo principio: la regla de dependencia exige que el código fuente solo apunte hacia el centro.

Las dependencias apuntan siempre hacia el centro.

Flujo de trabajo: se parte de las entidades y los casos de uso; el exterior (web, persistencia, interfaz) se enchufa al final. Los datos que cruzan una frontera lo hacen en estructuras simples, no en objetos del framework.

Cuándo no usarlo: igual que la hexagonal: si el dominio no justifica las capas. Un riesgo frecuente es duplicar clases en cada anillo solo por cumplir el esquema.

Microservicios

Servicios pequeños, desplegables por separado, cada uno dueño de sus datos y alineado con un contexto delimitado.

Servicios pequeños e independientes, cada uno con sus datos, detrás de una puerta de entrada común.

Flujo de trabajo: cada equipo tiene su repositorio o su carpeta, su canal de integración continua y su ritmo de despliegue. Los servicios se hablan por contratos versionados. Requieren, como base, automatización completa de despliegue, observabilidad distribuida (trazas, métricas, registros correlados) y una estrategia para la consistencia entre servicios.

Cuándo no usarlo: con un equipo pequeño, un dominio todavía inestable o sin automatización. El síntoma de haberlo hecho mal es el monolito distribuido: servicios que hay que desplegar juntos y se llaman en cadena síncrona.

Orientada a eventos

Los componentes no se invocan: publican hechos y otros reaccionan a ellos.

Quien produce un evento no sabe quién lo consume: el bus los desacopla.

Flujo de trabajo: el productor publica un evento ya ocurrido («pedido confirmado») sin saber quién lo consume. Añadir una funcionalidad es añadir un consumidor. Hay dos modelos: broker (descentralizado, cada consumidor reacciona) y mediador (un orquestador central coordina el flujo).

Cuándo no usarlo: cuando se necesita una respuesta inmediata y consistente, o cuando el flujo es tan lineal que seguirlo a través de eventos solo lo hace opaco. El coste está en la depuración y en la consistencia eventual.

Event sourcing

En lugar de guardar el estado actual, se guarda la secuencia de eventos que lo produjo. El estado se reconstruye reproduciéndolos.

Se guardan los hechos, no el estado: el estado se reconstruye reproduciéndolos.

Flujo de trabajo: un comando llega a un agregado, que valida las reglas y emite eventos; estos se añaden al registro y las proyecciones los consumen para construir las vistas. Para no reproducir toda la historia se guardan instantáneas periódicas. Los cambios de esquema de eventos se gestionan con versionado de eventos.

Fortalezas: auditoría completa, posibilidad de reconstruir el estado en cualquier instante, nuevas proyecciones sobre datos antiguos.

Cuándo no usarlo: casi siempre que no haya una necesidad clara de historia o auditoría. Es de los estilos más caros de entender, de migrar y de corregir (un error ya registrado se compensa, no se borra).

CQRS

Separa el modelo que escribe del que lee. Suele acompañar a event sourcing, pero no lo exige.

Lectura y escritura con modelos distintos, cada uno optimizado para lo suyo.

Flujo de trabajo: los comandos pasan por el modelo de escritura, que protege las invariantes; sus cambios se propagan a modelos de lectura optimizados para cada consulta. Las lecturas pueden ir a un almacén distinto, con la forma exacta que necesita la pantalla.

Cuándo no usarlo: si lectura y escritura tienen formas parecidas y cargas similares. Sumar dos modelos y la sincronización entre ellos es complejidad sin retorno.

Serverless (funciones como servicio)

Funciones que se ejecutan bajo demanda sobre infraestructura gestionada por el proveedor.

Funciones que se ejecutan solo cuando llega un evento; el proveedor gestiona los servidores.

Flujo de trabajo: cada función se despliega por separado y responde a un disparador (petición, evento, temporizador). No hay servidores que mantener y el coste sigue al uso. La lógica se escribe sin estado; el estado vive en servicios gestionados.

Cuándo no usarlo: procesos largos, latencia muy exigente donde el arranque en frío molesta, cargas constantes y altas donde un servidor propio sale más barato, o cuando el riesgo de dependencia del proveedor no es asumible.

Pipes and filters

Cadena de pasos independientes: cada filtro transforma la entrada y entrega su salida al siguiente.

Pasos independientes encadenados: la salida de uno es la entrada del siguiente.

Flujo de trabajo: se descompone el procesamiento en pasos con una sola responsabilidad y un formato de intercambio común. Cada filtro se prueba aislado y se puede reordenar, sustituir o ejecutar en paralelo. Es la forma natural de las canalizaciones de datos, los compiladores y las tuberías de Unix.

Cuándo no usarlo: cuando los pasos necesitan mucho contexto compartido o interacción entre sí, o cuando el trabajo es interactivo y no por lotes.

Microkernel (plugins)

Un núcleo pequeño y estable con las funciones mínimas, y extensiones que se enchufan a través de un contrato.

Un núcleo mínimo estable y extensiones que se enchufan.

Flujo de trabajo: se define el contrato de los plugins (interfaz, ciclo de vida, descubrimiento) y se mantiene estable; las funcionalidades nuevas se escriben como plugins, a veces por terceros. Los editores de código y los navegadores usan este modelo.

Cuándo no usarlo: si no hay una necesidad real de extensión de terceros o de variantes por cliente. Un contrato de plugins mal pensado es difícil de cambiar sin romper el ecosistema.

Space-based

Pensada para escalar picos extremos: la lógica y los datos viven en memoria distribuida y la base de datos se actualiza de forma asíncrona.

Los datos viven en memoria distribuida para escalar sin cuello de botella en la base de datos.

Flujo de trabajo: las peticiones llegan a unidades de proceso que operan sobre su copia de los datos en la rejilla; la rejilla replica entre unidades y un proceso en segundo plano persiste los cambios. Se añaden o se retiran unidades según la carga.

Cuándo no usarlo: cuando los datos son enormes (no caben en memoria), cuando se exige consistencia fuerte inmediata o cuando la carga es estable y no justifica la complejidad.

SOA (arquitectura orientada a servicios)

Servicios de negocio reutilizables, tradicionalmente coordinados por un bus de servicios empresarial que enruta, transforma y orquesta.

Servicios empresariales reutilizables que se orquestan a través de un bus.

Flujo de trabajo: se identifican servicios de granularidad empresarial, se publican sus contratos y el bus encadena las llamadas entre sistemas heterogéneos. Es el antecesor de los microservicios, con servicios más grandes, esquemas compartidos y lógica en el bus.

Cuándo no usarlo: el bus central tiende a convertirse en un cuello de botella y un punto de acoplamiento organizativo. Hoy se prefieren extremos inteligentes y conductos sencillos.

Peer-to-peer

No hay un servidor central: cada nodo es cliente y servidor a la vez.

Todos los nodos son a la vez clientes y servidores; no hay punto central.

Flujo de trabajo: los nodos se descubren entre sí, intercambian datos directamente y se reparten la carga. Es el modelo de distribución de ficheros, de ciertos sistemas de mensajería y de las redes de cadena de bloques.

Cuándo no usarlo: si se necesita control central, autoridad sobre los datos o garantías de consistencia fuertes. La seguridad y la confianza entre nodos son el gran reto.

Comparativa de estilos

EstiloDespliegueEscalaComplejidad operativaCambio en una parte
MonolitoUnoTodo a la vezBajaRedespliega todo
Monolito modularUnoTodo a la vezBajaRedespliega todo, cambio localizado
CapasNormalmente unoPor capa si se separanBajaSuele cruzar capas
Hexagonal / limpiaUno o variosSegún despliegueBaja a mediaAislado en adaptadores
MicroserviciosMuchosPor servicioAltaUn servicio
EventosVariosPor consumidorMedia a altaUn consumidor
Event sourcing y CQRSVariosLectura y escritura por separadoAltaProyecciones nuevas sin tocar el origen
ServerlessPor funciónAutomáticaMedia (cambia de sitio)Una función
MicrokernelNúcleo más pluginsDel núcleoMediaUn plugin
Space-basedMuchas unidadesMuy alta, elásticaMuy altaCompleja

Patrones de integración y resiliencia

Cuando el sistema se reparte en piezas que se hablan por red, aparecen problemas propios con soluciones conocidas.

API gateway

Un único punto de entrada para los clientes que resuelve lo transversal.

Un único punto de entrada que resuelve lo transversal.

Concentra autenticación, límites de uso, enrutado y, a veces, la agregación de varias respuestas. Evita que cada servicio repita esa lógica. Riesgo: convertirse en un monolito de reglas de negocio; el gateway debe quedarse en lo transversal.

Saga

Una transacción de negocio que abarca varios servicios no puede apoyarse en una transacción de base de datos. La saga la divide en pasos locales, cada uno con una acción compensatoria que lo deshace.

Una transacción larga dividida en pasos locales, cada uno con su deshacer.

Hay dos formas: coreografía (cada servicio reacciona a los eventos del anterior, sin coordinador) y orquestación (un orquestador dice qué paso toca). La coreografía es más desacoplada pero más difícil de seguir; la orquestación es más legible y centraliza el estado. Los pasos y compensaciones deben ser idempotentes.

Outbox transaccional

Resuelve el problema de la doble escritura: guardar en la base de datos y publicar un evento sin que uno se pierda si el otro falla.

El cambio de estado y el evento se guardan en la misma transacción.

El evento se escribe en una tabla de la misma transacción que el cambio de estado; un proceso aparte lo lee y lo publica. La entrega resultante es al menos una vez, de modo que el consumidor debe ser idempotente (por ejemplo, descartando identificadores de evento ya procesados). Es el complemento imprescindible de cualquier arquitectura de eventos seria.

Circuit breaker

Evita que un servicio que falla arrastre a quien lo llama.

Corta las llamadas a una dependencia que falla para no arrastrar al resto.

Si las llamadas fallan por encima de un umbral, el circuito se abre y las siguientes fallan al instante sin esperar. Pasado un tiempo, se dejan pasar unas pocas de prueba. Se combina con timeouts explícitos, reintentos con espera creciente y aleatoria (nunca reintentos inmediatos y masivos), bulkheads (compartimentos de recursos separados) y un camino degradado definido.

Strangler fig

La forma segura de sustituir un sistema antiguo sin una reescritura total.

Sustituir un sistema antiguo pieza a pieza detrás de una fachada.

Una fachada se coloca delante; cada funcionalidad se reimplementa en el sistema nuevo y la fachada empieza a enrutarle esa parte. El sistema viejo se va vaciando hasta poder apagarlo. El valor está en que cada paso es pequeño, desplegable y reversible.

Otros patrones que conviene conocer

PatrónProblema que resuelve
Capa anticorrupciónEvitar que el modelo de un sistema ajeno contamine el propio
Backend for frontendCada tipo de cliente tiene una API adaptada a sus necesidades
SidecarAñadir capacidades transversales (observabilidad, seguridad) junto a cada servicio
Cache-asideAcelerar lecturas sin que la caché sea la fuente de verdad
Idempotent consumerProcesar un mensaje repetido sin efectos duplicados
BulkheadAislar recursos para que un fallo no consuma todos

Datos y consistencia

La decisión más difícil de revertir casi siempre es la de los datos.

  • Un dueño por dato: cada dato tiene un único servicio o módulo responsable de escribirlo. Los demás lo piden o guardan una copia derivada.
  • No compartir tablas entre servicios: una base de datos compartida es una API sin contrato y acopla los despliegues.
  • Consistencia fuerte frente a eventual: la fuerte es más simple de razonar; la eventual escala mejor y exige diseñar la interfaz y las reglas para tolerar el desfase.
  • Transacciones distribuidas: el compromiso en dos fases es frágil y lento; se suele preferir saga más outbox.
  • Migraciones: los cambios de esquema se hacen en pasos compatibles hacia atrás (expandir, migrar, contraer) para poder desplegar sin parar.

Cómo se decide una arquitectura

De los requisitos a una decisión registrada y vigilada.
  1. Entender el contexto: objetivos de negocio, restricciones (presupuesto, plazo, equipo, normativa) y atributos de calidad prioritarios, con escenarios medibles.
  2. Generar alternativas: al menos dos. Una decisión con una sola opción no es una decisión.
  3. Evaluar los compromisos: qué gana y qué paga cada opción frente a los escenarios. Para decisiones de gran riesgo sirve un método estructurado de evaluación por escenarios como ATAM.
  4. Probar lo que más riesgo tiene: una prueba de concepto o un spike sobre la hipótesis más dudosa, no sobre lo fácil.
  5. Registrar la decisión en un ADR.
  6. Vigilar que se cumple con comprobaciones automáticas.
  7. Revisar cuando cambien los requisitos, no por inercia ni por moda.

ADR: registros de decisiones de arquitectura

Un ADR es un documento corto, inmutable una vez aceptado y guardado junto al código. Si una decisión cambia, se escribe un ADR nuevo que sustituye al anterior.

## ADR-007: Separar el módulo de facturación como servicio
 
Estado: aceptada
Contexto: facturación se despliega con un ritmo distinto y tiene
  requisitos normativos propios; hoy bloquea los despliegues del resto.
Decisión: extraer facturación como servicio con su propia base de datos.
Alternativas descartadas:
  - Mantenerla como módulo: no resuelve el bloqueo de despliegues.
  - Reescribirla desde cero: riesgo y plazo desproporcionados.
Consecuencias:
  - Más: despliegue independiente y datos aislados.
  - Menos: consistencia eventual con pedidos, necesidad de saga.

Fitness functions

Una fitness function es una comprobación automática de que una característica de la arquitectura sigue cumpliéndose. Convierte las decisiones en reglas ejecutables:

  • Una regla que falla la compilación si el dominio importa algo de infraestructura.
  • Un test que detecta dependencias cíclicas entre módulos.
  • Una prueba de carga en integración continua que alerta si un tiempo de respuesta se degrada.
  • Un límite al tamaño o a la complejidad de un módulo.

Sin esto, la arquitectura documentada y la real se separan poco a poco.

Cómo se documenta

  • Modelo C4: cuatro niveles de zoom: contexto del sistema, contenedores, componentes y código. Cada diagrama responde a una pregunta y tiene un público.
  • Vistas por interesado: quien opera necesita una vista de despliegue; quien desarrolla, de módulos; quien decide, de contexto.
  • Documentación junto al código, versionada con él, y diagramas generados o fáciles de editar.
  • Qué no documentar: lo que el código ya dice con claridad. Se documentan las razones y las fronteras.

Evolución de una arquitectura

Una arquitectura no se acaba: se hace evolucionar.

  1. Empezar simple. Un monolito modular bien delimitado cubre mucho más tiempo del que se cree.
  2. Medir antes de partir. Se separa una pieza cuando hay una razón observable: ritmo de cambio distinto, escalado distinto, equipo distinto, requisito de aislamiento.
  3. Extraer por el borde. Primero los módulos con menos dependencias; se usa el strangler fig y se mantiene la compatibilidad.
  4. Cambios compatibles en pasos pequeños. Cada paso es desplegable y reversible.
  5. Limpiar lo que queda. Apagar de verdad el código y los datos antiguos; lo que se deja «por si acaso» se convierte en deuda.
  6. Reevaluar las decisiones a la luz de lo aprendido, con nuevos ADR.

Lista de comprobación antes de dar por buena una arquitectura

  • Los atributos de calidad prioritarios están escritos como escenarios medibles.
  • Cada decisión importante tiene su ADR con alternativas descartadas.
  • Las fronteras coinciden con contextos del dominio y con equipos.
  • Cada dato tiene un único dueño.
  • Toda llamada entre piezas tiene tiempo máximo, política de reintentos y comportamiento degradado.
  • Se puede desplegar y volver atrás sin intervención manual.
  • Hay trazas, métricas y registros correlados para seguir una petición de extremo a extremo.
  • Las reglas de dependencia se comprueban en integración continua.
  • Se sabe qué ocurre si cae cada dependencia externa.

Antipatrones habituales

  • Microservicios por moda: adoptar la complejidad de lo distribuido sin tener el problema que resuelve.
  • Monolito distribuido: servicios acoplados que se despliegan juntos y se llaman en cadena síncrona.
  • Base de datos compartida: varios servicios leyendo y escribiendo las mismas tablas.
  • Gran bola de barro: sin estructura reconocible, cualquier cosa depende de cualquier cosa.
  • Arquitectura de ensueño: diseñar para una escala o una variabilidad que nunca llega.
  • Dios servicio o dios módulo: una pieza que lo sabe y lo hace todo.
  • Golden hammer: usar siempre la misma tecnología o estilo, sea cual sea el problema.
  • Resume-driven design: elegir tecnologías por lo que aportan al currículo y no al sistema.
  • Decisiones sin registro: las razones solo viven en la cabeza de quien las tomó.
  • Ignorar la organización: diseñar fronteras que contradicen la estructura de los equipos.