Read in English · Lire en français · Auf Deutsch lesen
Sección 4.3 de 4.8 · Intermedio · 20 min de lectura
El modelo C4: contexto, contenedores, componentes y código
Videolección
5 min · narrado en inglés, con subtítulosSolo escuchar (audio)
Leer la transcripción
Pide a un equipo que dibuje su arquitectura y a menudo obtendrás formas sin explicar, líneas sin etiqueta y niveles de detalle mezclados. En esta lección aprenderás la respuesta de Simon Brown: el modelo C4.
Piensa en un mapa en línea. Con la vista alejada, ves un país entero y las autopistas entre ciudades. Acerca la vista y ves los distritos de una ciudad, luego las calles de un distrito y después un solo edificio. Cada nivel de zoom es útil para personas distintas. Y siempre sabes en qué nivel estás mirando. C4 hace lo mismo con el software. No es una notación nueva, sino un pequeño conjunto de abstracciones y una jerarquía de diagramas.
El nivel uno, el diagrama de contexto del sistema, muestra tu sistema como una sola caja, con las personas que lo usan y los demás sistemas de software con los que se conecta. Es para todo el mundo, sea técnico o no. El nivel dos, el diagrama de contenedores, muestra las aplicaciones y los almacenes de datos que hay dentro del sistema. C4 recomienda estos dos primeros niveles para todos los equipos. El nivel tres, el diagrama de componentes, se acerca a un contenedor. Dibújalo solo donde aporte valor, en las partes complejas o arriesgadas. El nivel cuatro muestra el propio código. Rara vez vale la pena dibujarlo a mano, porque la mayoría de las herramientas pueden generarlo bajo demanda.
La palabra contenedor requiere cuidado. En C4, un contenedor es una unidad que se ejecuta o se despliega por separado y que ejecuta código o almacena datos: una aplicación web, una app móvil, un servicio, un esquema de base de datos o un topic de mensajes. No es lo mismo que un contenedor Docker. Una app móvil en un teléfono es un contenedor C4 y, sin embargo, no se ejecuta en Docker. Cuántas copias de un contenedor se ejecutan, y dónde, corresponde a un diagrama de despliegue.
Este es el nivel uno de la plataforma de reparto de comida. Los clientes, el personal de los restaurantes y los repartidores tienen cada uno una flecha etiquetada que dice qué hacen con la plataforma, que se muestra como una sola caja. Debajo están los sistemas externos de los que depende: un proveedor de pagos, un servicio de mapas y los servicios push. Ver de un vistazo que estos servicios se contratan fuera es arquitectónicamente significativo.
Ahora acerquémonos al nivel dos. Para la mayoría de los equipos, este diagrama de contenedores es el diagrama más valioso que tienen. Arriba, cada tipo de usuario tiene una app, y cada app indica su tecnología. Cada app llama a la interfaz de programación de aplicaciones, o API, de la plataforma a través de un API gateway, que autentica a los usuarios y enruta las solicitudes. Fíjate en el protocolo de cada flecha. El servicio de pedidos registra los pedidos y cobra. Lee y escribe en la base de datos de pedidos. También publica eventos de pedidos en un topic de Kafka, dibujado como un contenedor por derecho propio. Los servicios de despacho y de notificaciones consumen de él. Esas flechas son discontinuas porque son asíncronas, y la leyenda lo indica. Fuera del límite están los tres sistemas externos, y abajo está la leyenda. Cuántas copias de cada servicio se ejecutan se deja para un diagrama de despliegue.
C4 no prescribe formas ni colores, pero sí prescribe lo que debe decir todo diagrama. Cada uno necesita un título que indique su tipo y su alcance, y una leyenda que explique cada forma y cada estilo de línea. Cada elemento tiene un nombre, un tipo, una descripción de una frase y, en los contenedores y componentes, su tecnología. Cada relación es una flecha, en una sola dirección, etiquetada con lo que hace. Nunca solo "usa". Entre contenedores, añade el protocolo e indica si es síncrono o asíncrono. Mantén un solo nivel de abstracción: nada de clases en un diagrama de contenedores. Y usa el color solo como complemento, porque los diagramas se imprimen en blanco y negro y los leen personas daltónicas.
Apliquemos las reglas. Un equipo comparte un diagrama de pizarra: cinco cajas, entre ellas App, Backend y DB, líneas sin puntas de flecha, una caja verde y ni título ni leyenda. Primero, decide qué es. Mezcla una app, un servicio y una base de datos, así que es un diagrama de contenedores, y recibe un título que lo dice. Cada caja recibe un nombre, un tipo y una tecnología. App pasa a ser la app del cliente, y DB pasa a ser la base de datos de pedidos. Cada línea simple se convierte en una flecha etiquetada con un protocolo. El equipo descubre que una línea significaba dos cosas distintas, una llamada en un sentido y un webhook en el otro, así que se convierte en dos flechas. Etiquetar las flechas también revela un topic de Kafka que nadie había dibujado. Y la caja verde resulta significar "es de nuestro equipo", algo que va en la leyenda. El resultado tiene más cosas y, sin embargo, necesita menos explicación, porque responde a todas las preguntas que haría un lector. La mayor parte del valor vino de etiquetar las flechas.
La sección completa añade el diagrama de componentes, los diagramas complementarios y las herramientas de modelado. A continuación, en la Sección cuatro punto cuatro, veremos las partes del Lenguaje Unificado de Modelado, o UML, que los arquitectos todavía usan. Nos vemos allí.
Lo que necesitas saber
- El modelo C4, creado por Simon Brown, describe el software con una jerarquía de cuatro diagramas (contexto del sistema, contenedores, componentes y código) construida sobre las abstracciones persona, sistema de software, contenedor y componente.
- Un contenedor C4 es una unidad que se ejecuta o se despliega por separado y que ejecuta código o almacena datos, como una aplicación web, una app móvil, un servicio, un esquema de base de datos o un topic de mensajes; no es lo mismo que un contenedor Docker.
- Los diagramas de contexto del sistema y de contenedores se recomiendan para todos los equipos; los de componentes, solo donde aporten valor, y los de código, rara vez y, preferiblemente, generados a partir del código.
- Los diagramas complementarios son el panorama de sistemas (todos los sistemas de una organización), el dinámico (la colaboración en tiempo de ejecución para un escenario) y el de despliegue (los contenedores asignados a la infraestructura, uno por entorno).
- Todo diagrama necesita un título con su tipo y su alcance, y una leyenda; todo elemento, un nombre, un tipo, una descripción y (en contenedores y componentes) una tecnología; toda relación, una única dirección, una etiqueta concreta y, entre contenedores, un protocolo.
- Las herramientas de modelado como Structurizr generan muchos diagramas coherentes a partir de un solo modelo, mientras que las herramientas de dibujo producen imágenes independientes que se van distanciando entre sí.
Mapas de tu código
El modelo C4 es un enfoque para diagramar la arquitectura de software creado por Simon Brown. Surgió de la formación en arquitectura de software que impartía desde aproximadamente 2006: según el sitio de C4, sus raíces se remontan a algún momento entre 2006 y 2009, los tipos de diagrama recibieron nombre a principios de 2010 y el nombre "C4" se usó por primera vez a principios de 2011. Brown había observado que los equipos a los que se pedía dibujar su arquitectura producían diagramas difíciles de entender: formas y colores sin explicar, cajas que podían ser cualquier cosa, desde una clase hasta un centro de datos, líneas sin etiqueta y varios niveles de detalle mezclados en una misma página. UML, que podría haber resuelto el problema, había caído en gran medida en desuso en el trabajo diario.
Su respuesta no fue una notación nueva, sino un pequeño conjunto de abstracciones y una jerarquía de diagramas construida sobre ellas, que él compara con los niveles de zoom de un mapa en línea. Empiezas con el país entero, te acercas a una ciudad, luego a un distrito y después a una calle. Cada nivel muestra una cantidad distinta de detalle con un propósito distinto, y siempre sabes en qué nivel estás mirando. C4 es deliberadamente independiente de la notación y de la herramienta: puedes dibujarlo en una pizarra, en una herramienta de dibujo o con una herramienta de modelado, siempre que sigas unas pocas reglas.
C4 se ha convertido en uno de los enfoques más usados para los diagramas de arquitectura porque es fácil de aprender, encaja de forma natural con el pensamiento de múltiples vistas de la Sección 4.2 y produce diagramas que pueden seguir tanto los desarrolladores como los lectores no técnicos. En términos de 42010, cada tipo de diagrama C4 es un punto de vista con su propio tipo de modelo; C4 simplemente mantiene pequeño el conjunto.
Las abstracciones: personas, sistemas de software, contenedores, componentes
C4 se basa en cuatro abstracciones, más el código. Una persona es un usuario humano del sistema: un cliente, un repartidor, un agente de soporte. Un sistema de software es el nivel más alto de abstracción, algo que aporta valor a sus usuarios y que normalmente pertenece a un equipo u organización, que lo construye; la plataforma de reparto de comida es uno, y también lo son el proveedor de pagos y el servicio de mapas de los que depende.
Un contenedor es algo que tiene que estar en ejecución para que el sistema funcione: en palabras de Brown, esencialmente un límite de ejecución alrededor de un código que se ejecuta o de unos datos que se almacenan. Son ejemplos una aplicación web del lado del servidor, una aplicación de una sola página que se ejecuta en un navegador, una app móvil, una aplicación de escritorio, una función serverless, un esquema de base de datos, un almacén de archivos o un topic de mensajes. Cada uno se puede desplegar o ejecutar por separado, y los contenedores se comunican entre sí a través de los límites de proceso, normalmente por una red.
Un componente es una agrupación de funcionalidad relacionada detrás de una interfaz bien definida, que vive dentro de un contenedor y se ejecuta en el mismo proceso que los demás componentes de ese contenedor. En un servicio Java puede ser un conjunto de clases detrás de una interfaz; en un servicio Node.js, un módulo. Los componentes no se pueden desplegar por separado; la unidad de despliegue es el contenedor. Por último, el código son las clases, funciones y tablas que implementan un componente.
Los cuatro diagramas principales
| Nivel | Alcance | Muestra | Público principal | ¿Recomendado? |
|---|---|---|---|---|
| 1. Contexto del sistema | Un sistema de software | El sistema como una sola caja, las personas que lo usan y los demás sistemas de software con los que interactúa | Todo el mundo, técnicos y no técnicos, dentro y fuera del equipo | Sí, para todos los equipos |
| 2. Contenedores | Un sistema de software | Los contenedores (apps, servicios, almacenes de datos, topics) que contiene, sus responsabilidades, sus tecnologías y cómo se comunican | Arquitectos, desarrolladores y personal de operaciones y soporte | Sí, para todos los equipos |
| 3. Componentes | Un contenedor | Los componentes que contiene, sus responsabilidades y tecnologías, y sus relaciones | Arquitectos y desarrolladores | Solo donde aporte valor; genéralo si hay que mantenerlo a largo plazo |
| 4. Código | Un componente | Clases, interfaces, funciones o tablas, normalmente como diagrama de clases UML o diagrama entidad-relación | Desarrolladores | Rara vez; generarlo bajo demanda a partir del código para las partes más complejas |
Nivel 1: el diagrama de contexto del sistema
El diagrama de contexto del sistema es el punto de partida. Coloca el sistema que estás describiendo en el centro, como una sola caja, y lo rodea de las personas que lo usan y de los sistemas de software de los que depende o que dependen de él. Oculta deliberadamente todo el detalle interno, incluidas las tecnologías, los protocolos y los servicios internos. Responde a las preguntas que cualquier recién llegado, responsable de producto o revisor de seguridad hace primero: ¿qué es este sistema, quién lo usa y con qué se conecta?
Como oculta lo interno, el diagrama de contexto es también el diagrama adecuado para las conversaciones con partes interesadas no técnicas y para delimitar el alcance: ¿dónde termina nuestra responsabilidad? En el ejemplo de reparto de comida de abajo muestra de inmediato que los pagos con tarjeta, el cálculo de rutas y el envío de notificaciones push se contratan fuera, lo cual es arquitectónicamente significativo (cada uno es una dependencia externa con su propia disponibilidad, su costo y su contrato) e invisible en la mayoría de las vistas a nivel de código.
Plataforma de reparto de comida: contexto del sistema
Nivel 2: el diagrama de contenedores
El diagrama de contenedores se acerca a la caja del sistema y muestra los contenedores que hay dentro: las aplicaciones y los almacenes de datos que forman el sistema, de qué es responsable cada uno, qué tecnología usa cada uno y cómo se comunican. Para la mayoría de los equipos es el diagrama más valioso que tienen. Muestra las principales decisiones estructurales (cuántas unidades desplegables hay, cuáles se comunican de forma síncrona y cuáles mediante mensajería, cuáles son dueñas de datos) y es lo bastante concreto para los desarrolladores y el personal de operaciones, sin dejar de caber en una página.
Fíjate en dos decisiones en el diagrama de abajo. El topic de mensajes de los eventos de pedidos se dibuja como un contenedor por derecho propio, porque es un almacén en el que los productores escriben y del que los consumidores leen; la guía de C4 ofrece este estilo explícito o, como alternativa, omitir el topic y escribir "a través del topic de eventos de pedidos" en las flechas. Dibujarlo muestra con claridad el acoplamiento a través del topic. Y las relaciones asíncronas usan una línea discontinua, que explica la leyenda. El diagrama de contenedores no dice nada sobre cuántas copias de cada servicio se ejecutan, en qué región o detrás de qué balanceador de carga; eso corresponde a un diagrama de despliegue.
Plataforma de reparto de comida: contenedores
Nivel 3: el diagrama de componentes
El diagrama de componentes se acerca a un contenedor y muestra los componentes que hay dentro. Está dirigido a los arquitectos y desarrolladores que trabajan en ese contenedor, y es donde se hace visible la estructura interna de un servicio: qué parte atiende las solicitudes entrantes, dónde viven las reglas de negocio, qué parte habla con la base de datos y cómo salen los eventos del servicio.
La guía de C4 es dibujar diagramas de componentes solo donde aporten valor, normalmente para contenedores complejos, arriesgados o que modifican muchas personas, y generarlos automáticamente si se van a mantener durante mucho tiempo, porque la estructura de componentes cambia tan a menudo como el código. En la plataforma de reparto de comida, el servicio de pedidos cumple esos requisitos: maneja dinero, habla con un proveedor externo y debe publicar eventos de forma fiable. El diagrama de abajo muestra una estructura típica, que incluye un componente de bandeja de salida (outbox) que escribe los eventos en la base de datos en la misma transacción que el pedido y después los retransmite a Kafka (el patrón de bandeja de salida se trata en el Capítulo 6).
Servicio de pedidos: componentes
Nivel 4: el código y los diagramas complementarios
El nivel de código se acerca a un componente y muestra sus clases, interfaces o tablas, normalmente como diagrama de clases UML o diagrama entidad-relación. La guía de C4 lo considera opcional y, en general, no vale la pena dibujarlo a mano: la mayoría de los entornos de desarrollo pueden generarlo bajo demanda, y una copia dibujada a mano queda desactualizada en cuanto alguien refactoriza. Dibújalo solo para las partes más importantes o intrincadas, como un modelo de dominio en el corazón del negocio (la Sección 4.4 muestra un diagrama de clases así).
Tres diagramas complementarios cubren los huecos que deja la jerarquía. Un diagrama de panorama de sistemas (system landscape) es un diagrama de contexto sin un único sistema en el foco: muestra todos los sistemas de software y personas de una organización o dominio, lo que resulta útil para los arquitectos empresariales y de plataforma. Un diagrama dinámico muestra cómo colaboran los elementos en tiempo de ejecución en un escenario, como interacciones numeradas sobre un diagrama de contenedores o de componentes (o como un diagrama de secuencia UML); es el equivalente en C4 de los escenarios de 4+1. Un diagrama de despliegue muestra cómo se asignan los contenedores a la infraestructura en un entorno: nodos de despliegue como regiones de la nube, clústeres de Kubernetes, máquinas virtuales, servicios de bases de datos gestionados y dispositivos, con el número de instancias. C4 recomienda un diagrama de despliegue por cada entorno que importe, normalmente producción y quizá preproducción (staging).
Reglas de notación que hacen legibles los diagramas
C4 no prescribe formas ni colores, pero sí prescribe lo que debe decir todo diagrama. Estas reglas, resumidas de la guía de notación de C4, son las que hacen que los diagramas anteriores se puedan leer sin una reunión para explicarlos.
Lista de comprobación: un diagrama C4 que se explica solo
- Un título que indique el tipo y el alcancePor ejemplo, "Diagrama de contenedores de la plataforma de reparto de comida", para que los lectores sepan de inmediato el nivel de zoom.
- Una leyenda (clave)Explica cada forma, color, estilo de borde, estilo de línea y punta de flecha que uses, aunque la notación parezca obvia. Los lectores de otros equipos no compartirán tus convenciones.
- Cada elemento tiene un nombre, un tipo y una descripciónEl tipo entre corchetes (Persona, Sistema de software, Contenedor, Componente) elimina la ambigüedad; una frase breve sobre su responsabilidad dice para qué sirve el elemento.
- Tecnología en cada contenedor y componente"Contenedor: Java", "Contenedor: PostgreSQL". Las elecciones tecnológicas son arquitectura y los lectores las necesitan.
- Cada relación tiene una sola dirección y una etiquetaUsa una flecha por relación, etiquetada con lo que hace en la dirección de la flecha ("Publica eventos de pedidos en"), nunca solo "usa" ni una flecha de doble punta.
- Protocolos en las relaciones entre contenedoresJSON/HTTPS, SQL/TCP, Kafka. Que una relación sea síncrona o asíncrona es uno de los datos más importantes del diagrama.
- Acrónimos explicadosEscríbelos completos o defínelos en la leyenda o en el glosario.
- Un nivel de abstracción por diagramaNada de clases en un diagrama de contenedores, nada de servidores en un diagrama de componentes.
- El color como complemento, no como única señalLos diagramas se imprimen en blanco y negro y los leen personas daltónicas; usa también el estilo de línea y las etiquetas, y mantén el significado de los colores coherente entre diagramas.
Ejemplo práctico
Ejemplo práctico: mejorar un diagrama típico de un equipo
Un equipo de la empresa de reparto de comida comparte esta descripción del diagrama de su pizarra: cinco cajas con las etiquetas "App", "Backend", "Orders", "DB" y "Stripe"; líneas entre ellas sin puntas de flecha; la caja Orders es verde y las demás azules; no hay título ni leyenda. Aplicando las reglas de C4 paso a paso:
| Título y nivel | Decide qué es el diagrama. Mezcla una app móvil, un servicio y una base de datos, así que es un diagrama de contenedores. Ponle el título "Diagrama de contenedores de la plataforma de reparto de comida". |
|---|---|
| Nombre, tipo, descripción | "App" pasa a ser "App del cliente [Contenedor: Kotlin, Swift] App de iOS y Android para pedir comida". "Backend" resulta ser el API gateway; "DB" pasa a ser "Base de datos de pedidos [Contenedor: PostgreSQL]". |
| Sistemas externos | "Stripe" es el nombre de un producto de un sistema externo. Muéstralo como "Proveedor de pagos [Sistema de software]" fuera del límite del sistema, con el nombre del proveedor en la descripción si eso importa a los lectores. |
| Relaciones | Sustituye cada línea simple por una flecha etiquetada: "Llama a [JSON/HTTPS]", "Lee y escribe en [SQL/TCP]", "Autoriza pagos con tarjeta usando [HTTPS]". El equipo descubre que una línea significaba dos cosas distintas (una llamada en una dirección y un webhook en la otra), así que se convierte en dos flechas. |
| Elementos que faltan | Al etiquetar las flechas se descubre que los eventos de pedidos llegan al servicio de despacho a través de un topic de Kafka que no estaba dibujado. Añade el topic como contenedor, con flechas asíncronas discontinuas. |
| Leyenda y color | La caja verde resulta significar "es de nuestro equipo". Añádelo a una leyenda, o sustituye el color por un límite discontinuo con el nombre del equipo. |
| Resultado | El diagrama ha ganado un título, una leyenda, tres elementos y el doble de flechas, y aun así necesita menos explicación, porque cada pregunta que haría un lector tiene respuesta en la página. |
La mayor parte del valor vino de etiquetar las flechas: las líneas sin etiqueta ocultan los datos arquitectónicos más importantes (dirección, protocolo, síncrono o asíncrono).
El diagrama mejorado reveló una dependencia (el topic) que el propio equipo había olvidado, un efecto secundario típico de aplicar las reglas.
Herramientas: dibujo frente a modelado
Los diagramas C4 pueden hacerse con cualquier herramienta de dibujo, y muchos equipos empiezan con una pizarra o una aplicación general de diagramas. El sitio de C4 distingue dos familias de herramientas. Las herramientas de diagramación dibujan cajas y líneas; son flexibles y conocidas, pero los diagramas son imágenes independientes, así que cambiar el nombre de un elemento obliga a editar todos los diagramas que lo muestran, y nada comprueba que los diagramas coincidan. Las herramientas de modelado mantienen un único modelo de personas, sistemas, contenedores, componentes y relaciones, y generan cada diagrama como una vista de ese modelo; el cambio de nombre se hace una sola vez, los diagramas siguen siendo coherentes y el modelo se puede consultar y validar.
Structurizr, creada por Simon Brown, es la herramienta de modelado de referencia para C4. Su Structurizr DSL, basado en texto, describe el modelo y las vistas en un archivo que vive en el control de versiones junto al código. Otras opciones son C4-PlantUML (formas C4 para PlantUML), el soporte de diagramas C4 de Mermaid y diversas herramientas de modelado comerciales; la Sección 4.7, Diagramas como código, muestra ejemplos. La elección importa menos que el hábito: guarda la fuente de los diagramas donde trabaja el equipo y actualízala en el mismo pull request que el cambio que describe.
Preguntas frecuentes
¿Sustituye C4 a UML?
No exactamente. C4 define abstracciones y tipos de diagrama, no una notación, y no dice nada sobre muchas cosas que UML puede expresar con precisión, como las máquinas de estados o las secuencias detalladas de mensajes. Muchos equipos usan C4 para la estructura y toman prestados de UML los diagramas de secuencia, de estados y de despliegue donde hace falta precisión (Sección 4.4).
¿Cómo encajan las funciones serverless en C4?
Cada función, o cada grupo de funciones que se despliegan juntas, es un contenedor: una unidad desplegable por separado que ejecuta código. Los almacenes de datos y las colas compartidos que usan también son contenedores.
Nuestro sistema es un único monolito desplegable. ¿El diagrama de contenedores no sirve para nada?
No. Un monolito normalmente sigue teniendo un cliente web o móvil, la aplicación de servidor, una base de datos y quizá un almacén de archivos y una tarea programada, y cada uno es un contenedor. El diagrama de componentes del monolito pasa entonces a ser la vista más interesante de sus módulos internos.
Comprueba lo que has entendido
¿Qué es un contenedor en el modelo C4? Da dos ejemplos que no tengan que ver con Docker.
Una unidad que se ejecuta o se despliega por separado y que ejecuta código o almacena datos. Ejemplos: una app móvil en un teléfono, una aplicación de una sola página en un navegador, un esquema de base de datos, una función serverless.
¿Qué dos diagramas C4 recomienda la guía de C4 para todos los equipos?
El diagrama de contexto del sistema y el diagrama de contenedores.
¿Dónde deben mostrarse el número de réplicas, las regiones y los balanceadores de carga?
En un diagrama de despliegue, uno por entorno, no en el diagrama de contenedores.
¿Por qué insiste C4 en flechas de una sola dirección y con etiqueta?
Las líneas sin etiqueta o de doble sentido ocultan qué es la relación (llamada, flujo de datos, evento), en qué dirección va y qué protocolo usa, que están entre los datos arquitectónicos más importantes del diagrama.
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: “¿Cada uno de nuestros microservicios debería ser un contenedor o un sistema de software aparte en nuestros diagramas C4?”