¿Qué es el diagrama del modelo C4?
La Diagrama del modelo C4 es un marco arquitectónico jerárquico de cuatro niveles diseñado para documentar la arquitectura de software con diferentes grados de detalle. Creado por Simon Brown, el C4 evita cuadros y líneas ambiguas al estructurar los mapas del sistema en cuatro lentes de abstracción explícitas: Contexto (alcance a nivel de sistema), Contenedor (aplicaciones y almacenes de datos), Componente (módulos internos), y Código (implementaciones a nivel de clase).
Para implementar este modelo de forma eficaz en texto, los ingenieros utilizan la extensión oficial C4-PlantUML biblioteca estándar de extensiones. Esta biblioteca reemplaza las formas UML crudas con macros especializadas que inyectan automáticamente colores distintos, formas y campos de metadatos para usuarios, sistemas y bases de datos. Con VPasCode, puedes definir estos entornos anidados de forma limpia en código. El motor de diseño enruta dinámicamente los vectores de conexión y escala los campos de texto sin arruinar la geometría de tu diseño.
Guía de sintaxis principal: elementos y construcciones
Construir un modelo C4 válido usando PlantUML depende de importar los archivos de biblioteca correctos, seleccionar macros estructurales, establecer límites y utilizar enlaces de relaciones especializados.
1. Importación de los archivos de la biblioteca estándar C4
La C4-PlantUMLextensión se divide en archivos individuales que se corresponden directamente con los niveles distintos del modelo de abstracción. Para evitar retrasos en el rendimiento o errores del compilador, solo debes importar la capa de archivo específica que tu diagrama requiere:
@startuml
' Incluir el archivo de capa C4 específico requerido
!include <C4/C4_Context>
' Usa C4_Container o C4_Component para mapas arquitectónicos más profundos
2. Declaración de actores y sistemas principales (nivel de contexto)
En el nivel de contexto del sistema a alto nivel, modelas componentes internos, dependencias externas y usuarios humanos. La biblioteca estándar proporciona macros específicas que aceptan un ID, una etiqueta visual y una etiqueta descriptiva opcional:
Person(id, "Etiqueta", "Descripción")— Representa un perfil de usuario humano o un actor del sistema.System(id, "Etiqueta", "Descripción")— Representa una aplicación de software interna principal o ecosistema de servicios.System_Ext(id, "Etiqueta", "Descripción")— Representa un sistema externo o dependencia de una API de terceros (se representa con una paleta de colores grises explícita).
@startuml C4_Elements
!include <C4/C4_Context>
Person(customer, "Cliente de Banca", "Un cliente con una cuenta bancaria personal")
System(banking_sys, "Sistema Bancario Central", "Gestiona transacciones financieras")
System_Ext(mail_sys, "Servicio de Correo Electrónico", "Pasarela de notificaciones SMTP interna") 
3. Límites explotados (niveles de contenedor y componente)
Cuando profundizas más en la capa de contenedor, modelas aplicaciones web, microservicios y bases de datos. Puedes aislar estos elementos internos dentro de una caja de límite lógico explícito usando elSystem_Boundary()envoltura de macro:
!include <C4/C4_Container>
System_Boundary(c1, "Ecosistema del Sistema de Comercio Electrónico") {
Container(web_app, "Aplicación de página única", "React & TypeScript", "Proporciona funciones de usuario mediante vista web")
ContainerDb(database, "Base de datos relacional", "PostgreSQL", "Almacena perfiles de usuario e historiales de registros")
} 
4. Mapeo de relaciones técnicas
En lugar de depender de líneas punteadas básicas, C4 utiliza un formato de macros de comunicación explícito comoRel(From_ID, To_ID, "Etiqueta", "Tecnología"). Esto mantiene tus mapas de arquitectura altamente legibles al exigir que cada conexión indique su propósito y el protocolo de transporte subyacente (por ejemplo, HTTPS, gRPC o AMQP):
!include <C4/C4_Container>
Person(customer, "Cliente de Banca", "Un cliente con una cuenta bancaria personal")
System(banking_sys, "Sistema Bancario Central", "Gestiona transacciones financieras")
System_Ext(mail_sys, "Servicio de Correo Electrónico", "Pasarela de notificaciones SMTP interna")
System_Boundary(c1, "Ecosistema del Sistema de Comercio Electrónico") {
Container(web_app, "Aplicación de página única", "React & TypeScript", "Proporciona funciones de usuario mediante vista web")
ContainerDb(database, "Base de datos relacional", "PostgreSQL", "Almacena perfiles de usuario e historiales de registros")
}
Rel(customer, web_app, "Utiliza funciones de tienda mediante", "HTTPS")
Rel(web_app, database, "Lee y escribe datos transaccionales mediante", "SQL/TCP") 
Mejores prácticas para arquitecturas C4 legibles
- Nunca mezcles niveles de abstracción:Mantén tus diagramas enfocados en una sola capa. No mezcles componentes de software internos de gran detalle en un mapa de contexto de sistema de alto nivel. Si un sistema se vuelve demasiado complejo, divídelo en un diagrama independiente y dedicado a nivel de contenedor.
- Define explícitamente las tecnologías:Siempre utiliza el cuarto parámetro en tus
Rel()macros para indicar la tecnología o protocolo exacto que se está utilizando (por ejemplo,"JSON/HTTPS"o"JDBC"). Esto proporciona a tu equipo un contexto de implementación crucial a simple vista. - Aprovecha las invalidaciones de diseño direccionales: Si tus componentes comienzan a apilarse de forma incómoda, utiliza macros de relación direccionales (como
Rel_D()para abajo,Rel_R()para la derecha, oRel_L()para la izquierda) para limpiar manualmente tu flujo arquitectónico.
Ejemplos reales de PlantUML C4
Ejemplo 1: Diseño de contexto de sistema de alto nivel (Nivel 1)
Este plano funcional modela un diagrama estándar de contexto de sistema de nivel 1, detallando cómo un cliente interactúa con una aplicación de banca en línea y sus dependencias externas.
@startuml
!include <C4/C4_Context>
title Diagrama de contexto de sistema para el sistema de banca en línea
Person(customer, "Cliente de banca personal", "Un cliente del banco con cuentas personales.")
System(banking_system, "Sistema de banca en línea", "Permite a los clientes ver información financiera y realizar transferencias.")
System_Ext(mail_system, "Subsistema de correo electrónico", "El clúster de servidores corporativos internos de correo electrónico SendGrid de la empresa.")
Rel(customer, banking_system, "Utiliza el panel en línea mediante")
Rel_R(banking_system, mail_system, "Envía alertas y códigos de verificación usando", "SMTP")
@enduml 
Desglose de sintaxis: Este diagrama se centra únicamente en el alcance de alto nivel. La System_Ext macro aplica automáticamente un perfil de color gris al servicio de correo electrónico, separándolo visualmente del sistema principal y sus dependencias externas. La Rel_R macro obliga al motor de diseño a colocar el nodo de correo directamente a la derecha del bloque del sistema bancario.
Ejemplo 2: Topología de contenedores de microservicios con profundidad (Nivel 2)
Este plano avanzado de la empresa descompone un sistema en sus aplicaciones contenedoras constituyentes y almacenes de datos aislados, mostrando cómo el tráfico web fluye a través de una puerta de enlace de API hasta los microservicios del backend.
@startuml
!include <C4/C4_Container>
title Diagrama de contenedores para la puerta de enlace del portal de pagos
Person(merchant, "Socio comercial web", "Integra los puntos finales de pago de la plataforma en sus sitios web.")
System_Boundary(portal_scope, "Ecosistema de puerta de enlace de pagos") {
Container(api_gateway, "Proxy de enrutamiento de API", "Nginx", "Intercepta llamadas entrantes, maneja límites de tasa y equilibra nodos.")
Container(auth_service, "Microservicio de identidad", "Go & OAuth2", "Valida los tokens y ámbitos de API de desarrolladores.")
Container(txn_service, "Libro de transacciones", "Java Spring Boot", "Procesa pagos y gestiona cuentas de libro.")
ContainerDb(ledger_db, "Almacén de datos del libro", "CockroachDB", "Implementa esquemas de tablas distribuidas compatibles con ACID.")
}
' Ruta los flujos de tráfico de forma limpia a través de los objetivos internos de contenedores
Rel(merchant, api_gateway, "Envía cargas útiles de pago mediante", "HTTPS/JSON")
Rel_D(api_gateway, auth_service, "Valida los tokens entrantes mediante", "gRPC")
Rel_D(api_gateway, txn_service, "Reenvía acciones de compra a", "gRPC")
Rel_R(txn_service, ledger_db, "Almacena entradas del libro mediante", "SQL/TLS")
@enduml 
Desglose de sintaxis: Al utilizar el System_Boundary envoltura de macro, los componentes internos se agrupan limpiamente juntos dentro de una caja de perímetro clara. La macro especializada ContainerDb macro representa el almacén de datos con un icono explícito de cilindro de base de datos, haciendo que la división entre las capas de tiempo de ejecución de cálculo y almacenamiento permanente sea clara a simple vista.