Ir al contenido
English

Modelos y vistas C4

Un modelo de arquitectura declara una sola vez las personas, los sistemas de software, los contenedores, los almacenes de datos y los componentes, con sus relaciones. Las vistas C4 dibujan el modelo en un nivel, cada una con su propia composición: mover una caja cambia una vista; cambiar el nombre de una entidad las cambia todas.

language "0.2"
model commerce {
person customer "Cliente"
system shop "Commerce" {
container web "Web" { technology "React" }
container api "API" { technology "HTTP" }
datastore db "Pedidos" { technology "PostgreSQL" }
}
customer -> shop.web: "Compra" as visit
shop.web -> shop.api: "HTTPS" as request
shop.api -> shop.db: "SQL" as persist
}
diagram containers: c4 using commerce {
level container
scope shop
include customer, shop.web, shop.api, shop.db
direction LR
layout assisted
theme "editorial.light"
}
Commerce [Software System] Cliente [Person] Web [Container: React] API [Container: HTTP] Pedidos [Container: PostgreSQL] Compra HTTPS SQL

Las vistas se compilan en el mismo modelo que los diagramas de flujo (decisión 0020): las entidades se convierten en elementos cuyos ids son sus rutas, las relaciones vienen del modelo, y placement, style, class, rule, animate, los temas, los preajustes, los lienzos y todos los modos de disposición funcionan como en los diagramas de flujo.

Declaración Entidad Dónde
person <id> ["Label"] [{ … }] una persona que usa los sistemas en la raíz del modelo
system <id> ["Label"] [{ … }] un sistema de software en la raíz del modelo
container <id> ["Label"] [{ … }] una aplicación o un servicio de un sistema en un sistema
datastore <id> ["Label"] [{ … }] un contenedor que almacena datos (cilindro) en un sistema
component <id> ["Label"] [{ … }] una parte de un contenedor en un contenedor

Los bloques de entidad admiten description "…", technology "…", external (personas y sistemas ajenos a la organización), url "…" (un enlace en las exportaciones, export.md) y las entidades anidadas en ellos. Cualquier otra ubicación es model.invalid-nesting.

  • Rutas. Una entidad se nombra con los ids desde la raíz: shop.api.orders. Las entidades hermanas tienen ids distintos.
  • Relaciones. a -> b: "Label" as id { technology "…"; description "…" }, en la raíz o en un bloque de entidad. Los extremos se buscan desde la entidad que los contiene hacia fuera y luego desde la raíz, después de leer todo el modelo, así que el orden de declaración nunca importa: dentro de system shop { }, api nombra shop.api. Una relación de una entidad consigo misma o con su propio ancestro es model.invalid-relation; un extremo desconocido es ref.unknown-entity, con rutas parecidas como pistas.
  • Ids. Los ids de los modelos comparten el espacio de nombres del archivo con los diagramas y los temas; los ids de las relaciones son únicos en cada modelo.

diagram <id>: c4 using <model> { … } nombra un modelo del archivo, una importación de miembros (import commerce from "../models/commerce.meltemi") o una con espacio de nombres (using models.commerce).

Nivel scope Dibuja Sin include
context opcional, un sistema personas y sistemas todos; con un ámbito, el ámbito y sus vecinos
container un sistema los contenedores y los almacenes de datos del ámbito, personas, otros sistemas los hijos del ámbito y las entidades con las que se relacionan
component un contenedor los componentes del ámbito, los demás contenedores de su sistema, personas, otros sistemas los hijos del ámbito y las entidades con las que se relacionan
  • include a, b, … lista las entidades que dibujar; exclude a, … quita entidades de la lista o del conjunto predeterminado.
  • El ámbito de una vista de contenedores o de componentes se dibuja como un límite discontinuo alrededor de los hijos que contiene.
  • label shop.api "Orders API" da a una entidad, o a una relación por su id, otro texto solo en esta vista. En placement, label <relation> at 50% sigue moviendo la etiqueta de una relación.
Código Cuándo
c4.invalid-level falta level o no es context, container ni component
c4.scope-required una vista de contenedores o de componentes sin scope
c4.invalid-scope un ámbito del tipo equivocado; los almacenes de datos no tienen componentes
c4.out-of-level una entidad que el nivel no dibuja, o el propio ámbito, en include
c4.unsupported-relation una combinación que no respalda ninguna relación del modelo
ref.unknown-model using no nombra ningún modelo
ref.unknown-entity una ruta desconocida en scope, include o exclude
  • Elevación. Cada extremo de una relación del modelo se dibuja en su ancestro dibujado más cercano: en el nivel de contexto, customer -> shop.web va de customer a shop. Una relación cuyos extremos coinciden, o que tiene un extremo sin nada dibujado por encima, no se dibuja.
  • Trazabilidad. Cada relación dibujada conserva las claves de las relaciones del modelo que representa (sources en el JSON, “Representa” en el inspector) e indica cuándo se elevó un extremo (derived). Las relaciones directas y las elevadas conservan su id del modelo, así que los estilos y las rutas las nombran.
  • Sin fusión predeterminada. Dos relaciones del modelo elevadas al mismo par siguen siendo dos flechas.
  • Combinación explícita. Una instrucción de relación en una vista combina todas las relaciones del modelo cuyos extremos dibujados son su par: customer -> shop: "Usa" as uses dibuja una sola flecha que las representa a todas. Una combinación que no respalda ninguna relación del modelo es c4.unsupported-relation: las vistas nunca dibujan flechas por conveniencia. Las vistas solo aceptan -> y -->; <->, <--> y las líneas -- y --- son prop.invalid-value sobre el símbolo, que nombra esos dos.
  • Formas. Una persona es una cabeza sobre un cuerpo redondeado; los sistemas, los contenedores y los componentes son cajas con su etiqueta, una línea de tipo como [Container: React] y su descripción; un almacén de datos es un cilindro; las personas y los sistemas externos son grises y discontinuos. Con "locale": "es" en project.json, o --lang es al exportar, las líneas de tipo se escriben en español: [Contenedor: React], [Persona externa], [Sistema de software].
  • Colores. Las clases integradas c4_person, c4_system, c4_container, c4_component, c4_external y c4_boundary colorean los tipos con los tokens del tema. Se aplican primero, así que las clases y las reglas del tema, y los rule, class y style de la vista, tienen prioridad.
  • Relaciones. La etiqueta, con la tecnología en una segunda línea: [JSON/HTTPS].

Una vista acepta una declaración propia, note <id> "Text" [on <ruta de la entidad>]: una anotación que pertenece a la vista, nunca al modelo, y que no es una entidad (include, exclude, label y las relaciones no pueden nombrarla). Se dibuja como una nota de flujo, acepta class y url en su bloque, y le valen las instrucciones style, class, rule y animate de la vista. Su posición se escribe en el placement de la vista como la de cualquier elemento.

diagram containers: c4 using commerce {
level container
scope shop
include customer, shop.web, shop.api, shop.db
note cache "Cached 5 min" on shop.api
}

El destino de on es una entidad que la vista dibuja: una ruta que el modelo tiene pero la vista no dibuja es ref.unknown-element, con una pista sobre cómo incluirla, y una guía punteada une la nota con ella. Excluir o quitar la entidad en el editor elimina la cláusula y conserva la nota.

link <model>.<path> en un diagrama de secuencia o una composición libre, también a través de importaciones (link commerce.shop.api, link models.commerce.shop.api), vincula un objeto con una entidad. Un objeto que no escribe ninguna etiqueta muestra la de la entidad; la información al pasar el puntero y el inspector muestran su tipo, su tecnología y su descripción. Un enlace no copia nada más: una relación estructural nunca se convierte en un mensaje.

  • Una vista de un modelo importado se compila en el proyecto contra ese modelo, así que validate, export, layout y el editor ven la misma vista.
  • Cambiar el nombre de una entidad reescribe su declaración, las relaciones del modelo, los scope, include, exclude y label, las combinaciones, la colocación y los estilos de cada vista, y todos los enlaces. En VS Code, Cambiar el nombre del símbolo llega a todos los archivos del proyecto; el lienzo y planEdit (renameEntity) cambian el nombre dentro de un archivo.