C4 avec PlantUML — Les bases

Version 1.0 — 2026-05-08

Document pédagogique : comprendre le modèle C4 et savoir le mettre en pratique avec C4‑PlantUML pour produire des diagrammes d'architecture lisibles, précis et versionnables.


1. Pourquoi C4 ?

Demandez à un urbaniste de décrire un bâtiment : il vous fournira un plan de masse, des plans d'étage, des coupes, des élévations, et des détails. Demandez à un développeur de décrire l'architecture d'un logiciel, et vous risquez de recevoir un assemblage hétéroclite de boîtes et de flèches dont la signification varie d'un schéma à l'autre.

Les défauts récurrents d'un tel schéma ad hoc sont connus :

  • la sémantique des couleurs, formes et flèches n'est pas définie ;
  • des termes vagues comme « business logic » servent d'étiquette ;
  • les choix technologiques manquent ;
  • les niveaux d'abstraction sont mélangés sur un même diagramme ;
  • les flèches ne sont pas étiquetées, ou les étiquettes ne reflètent pas le sens.

Le modèle C4, créé par Simon Brown, est une réponse pragmatique à ce désordre. Il propose un petit jeu d'abstractions et une famille de diagrammes hiérarchisés qui se zooment comme une carte routière : on commence vue d'avion, puis on plonge progressivement vers les détails.

Idée centrale — Une architecture se documente comme une carte : différents niveaux de zoom pour différents publics et différentes décisions.

C4 ne remplace pas UML, ArchiMate ou SysML. Il s'inscrit dans la lignée des schémas « boîtes et flèches », mais avec une grammaire stable et une hiérarchisation explicite.


2. Le modèle C4 en une page

Le nom C4 vient des quatre niveaux historiques :

NiveauNom ENNom FRPublic visé
1ContextContexte systèmeTout le monde, technique ou non
2ContainerConteneursDéveloppeurs, ops, architectes
3ComponentComposantsDéveloppeurs, architectes
4CodeCodeDéveloppeurs (souvent généré)

À ces quatre niveaux statiques s'ajoutent trois diagrammes complémentaires :

  • System Landscape — la carte des systèmes d'une organisation ou d'un domaine (un cran au-dessus du contexte) ;
  • Dynamic — un scénario d'exécution numéroté (qui appelle qui, dans quel ordre) ;
  • Deployment — la projection des conteneurs sur l'infrastructure (serveurs, machines, cloud, clusters).
projette surscénariseSystem Landscape1. Context2. Container3. Component4. CodeDeploymentDynamic

Une bonne pratique : produire systématiquement les niveaux 1 et 2 ; ne descendre au niveau 3 que là où la clarification architecturale le justifie ; déléguer le niveau 4 à la génération automatique depuis le code.


3. Les quatre abstractions

Le cœur de C4 tient en une définition récursive :

Un système logiciel est composé d'un ou plusieurs conteneurs, eux-mêmes composés d'un ou plusieurs composants, eux-mêmes implémentés par du code. Les personnes utilisent des systèmes logiciels.

3.1 Personne (Person)

Un acteur humain : utilisateur final, administrateur, opérateur de support, persona… Ce peut aussi être un acteur non humain (un système amont qui agit comme déclencheur), mais en pratique on réserve « Person » aux humains.

3.2 Système logiciel (Software System)

Le plus haut niveau d'abstraction et — paradoxalement — le plus difficile à définir. Une heuristique utile :

Un système logiciel est ce qu'une équipe construit, possède, et dont elle peut voir tous les détails internes. Souvent, sa frontière coïncide avec celle d'un dépôt de code, et tout son contenu est déployé en même temps.

À noter, ce n'est pas : un bounded context DDD, un domaine produit, une capacité métier, ni une équipe. Ce sont des choses utiles, mais distinctes.

3.3 Conteneur (Container)

⚠️ Pas Docker. Le mot a été choisi avant la mode des conteneurs OS.

Un conteneur C4 est un élément runtime qu'il faut faire tourner pour que le système fonctionne. C'est une unité déployable. Exemples :

  • une application web côté serveur (Tomcat, Rails, Node.js, ASP.NET…) ;
  • une SPA côté client (Angular, React, Vue…) ;
  • une application mobile, une application desktop ;
  • une fonction serverless (Lambda, Cloud Function) ;
  • un schéma de base de données ;
  • un bucket S3, un CDN, un système de fichiers ;
  • une file ou un topic d'un broker (cf. § 15.2).

La règle qui sépare conteneur de composant est limpide :

CritèreConteneurComposant
Unité déployable ?OuiNon
Espace processus ?Le sienPartage celui du conteneur hôte
Parle aux autres via…Réseau, IPC, fichierAppel de fonction / méthode

3.4 Composant (Component)

Un regroupement cohérent de fonctionnalités, exposé derrière une interface bien définie, exécuté dans le processus d'un conteneur.

Selon le langage :

  • en POO (Java, C#, Kotlin, TypeScript de classes) : un ensemble de classes et d'interfaces qui forme une unité fonctionnelle ;
  • en JavaScript : un module qui regroupe fonctions et objets ;
  • en fonctionnel (F#, Haskell, OCaml) : un module au sens du langage.

Un composant n'est pas un fichier JAR, une DLL, un package, un namespace ni un dossier. La correspondance peut exister, mais ce sont des outils d'organisation du code, pas une abstraction d'architecture.

3.5 Code

Les briques du langage : classes, fonctions, objets, traits, types. Ce niveau n'a pas de macros C4‑PlantUML dédiées — on utilise le diagramme de classes UML natif de PlantUML, ou de la génération automatique.


4. Les diagrammes : un par niveau de zoom

Chaque diagramme répond à une question, pour un public, à un niveau.

4.1 Diagramme de contexte (Niveau 1)

Question : qui utilise le système, et à quels autres systèmes parle-t-il ?

  • Périmètre : un système logiciel.
  • Boîte centrale : le système modélisé.
  • Autour : les personnes et systèmes externes connectés.
  • À cacher : les technologies, protocoles, détails internes.

C'est le diagramme à montrer aux non-techniques. Recommandé pour tout projet.

4.2 Diagramme de conteneurs (Niveau 2)

Question : de quelles applications et stockages le système est-il composé, et comment communiquent-ils ?

  • Périmètre : un système logiciel (le même qu'au niveau 1).
  • Contenu : les conteneurs internes au système, les personnes et systèmes externes qui leur sont directement reliés.
  • À montrer : les choix technologiques majeurs et les protocoles entre conteneurs (HTTPS, JDBC, gRPC, AMQP…).
  • À cacher : le déploiement (serveurs, load balancers, réplication — cf. § 4.5).

Recommandé pour tout projet : c'est le diagramme le plus utile au quotidien.

4.3 Diagramme de composants (Niveau 3)

Question : comment un conteneur est-il structuré à l'intérieur ?

  • Périmètre : un conteneur.
  • Contenu : ses composants, plus les conteneurs/personnes/systèmes directement connectés.
  • À ne produire que si la valeur le justifie. Préférer la génération automatique pour de la documentation pérenne — sinon le diagramme diverge du code et devient obsolète sans que personne ne s'en aperçoive.

4.4 Diagramme de code (Niveau 4)

Optionnel, généré la plupart du temps par l'IDE ou un outil dédié. Hors champ direct de C4‑PlantUML.

4.5 Diagrammes complémentaires

  • System Landscape — au-dessus du contexte : tous les systèmes pertinents d'une organisation, avec leurs personnes. Utile pour cartographier un SI.
  • Dynamic — un cas d'usage exécuté pas à pas. Utilise les mêmes éléments qu'un container/component diagram, mais les flèches sont numérotées.
  • Deployment — projette les conteneurs sur les nœuds d'infrastructure (machines virtuelles, pods, datacenter, device mobile). Un diagramme par environnement (dev, staging, prod).

Règle pratique — Niveau ≠ profondeur de détail à l'intérieur d'un élément. Niveau = à quel niveau d'abstraction on regarde. Ne dessinez jamais un système contenant des composants sans passer par les conteneurs.


5. Pourquoi PlantUML pour C4

C4 est indépendant de la notation et indépendant de l'outil : on peut le dessiner sur un tableau blanc, dans Draw.io, dans Structurizr, ou avec PlantUML. Pourquoi alors PlantUML ?

  • Diagrams as code : le .puml vit dans le dépôt, suit la pull request, est revu, diffé, versionné, et peut être généré en CI.
  • Open source et largement supporté (CLI, IDE, GitLab, GitHub, Confluence, Azure DevOps…).
  • C4‑PlantUML : une bibliothèque de macros qui rajoute la grammaire C4 par dessus PlantUML, avec une notation cohérente, des tags, des légendes calculées, et plein de petites commodités.

À retenir — PlantUML c'est la base, C4‑PlantUML c'est la surcouche qui apporte les macros Person(), Container(), Rel(), etc.

5.1 Comment inclure C4‑PlantUML

Trois méthodes, par ordre de préférence selon le contexte :

' (a) Standard library bundled avec PlantUML — pas besoin d'Internet.
!include <C4/C4_Container>

' (b) Version toujours à jour depuis GitHub — nécessite le réseau au rendu.
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

' (c) Copie locale des fichiers .puml — reproductibilité maximale.
!include C4_Container.puml

Choisissez selon vos contraintes : (a) en local sans réseau, (b) pour les exemples publics, (c) pour la production stable.

5.2 Quel fichier inclure ?

Chaque niveau étend le précédent. On inclut le plus profond dont on a besoin :

DiagrammeFichier à inclure
Contexte / LandscapeC4_Context.puml
ConteneursC4_Container.puml (inclut le précédent)
ComposantsC4_Component.puml (inclut les précédents)
DynamicC4_Dynamic.puml
DeploymentC4_Deployment.puml
Sequence (style C4)C4_Sequence.puml

Astuce — Pour un diagramme de conteneurs, n'incluez que C4_Container.puml : il vous donne déjà Person(), System(), Container(), et leurs variantes.


6. Premier diagramme : un Hello World C4‑PlantUML

Voici un diagramme de contexte minimal pour une application bancaire en ligne.

Diagramme de contexte — Banque en ligneClient Personne qui consulte sescomptes et fait desvirementsBanque en ligne Permet aux clients de gérerleurs comptesSystème central Stocke les comptes etexécute les transactionsService e-mail Envoie les notificationstransactionnellesConsulte ses comptes etordonne des virements via[HTTPS]Lit / écrit comptes[XML/HTTPS]Envoie e-mails via[SMTP]Legend  person  system  external system 

À décortiquer :

  1. @startuml / @enduml — délimitent le diagramme PlantUML.
  2. !include <C4/C4_Context> — charge la grammaire C4 niveau 1.
  3. title — le titre, toujours présent (le checklist y revient au § 17).
  4. Person() — un acteur humain.
  5. System() — le système modélisé (mis en avant visuellement).
  6. System_Ext() — un système externe (suffixé _Ext partout : Person_Ext, Container_Ext, Component_Ext).
  7. Rel(source, cible, "label", "techno") — une relation orientée de source vers cible, avec un libellé qui explique l'intention.
  8. SHOW_LEGEND() — génère une légende automatique sous le diagramme.

Règle d'or — Un libellé de relation comme "Utilise" est trop vague. Préférez "Consulte les comptes via", "Pousse les paiements vers", etc.


7. Vocabulaire de C4‑PlantUML

C4‑PlantUML expose une grammaire régulière. Une fois trois ou quatre macros acquises, le reste se déduit par suffixage.

7.1 Les macros par niveau

Niveau 1 — Context
    Person(alias, label, ?descr, ?sprite, ?tags, ?link)
    Person_Ext(...)
    System(alias, label, ?descr, ?sprite, ?tags, ?link, ?type)
    System_Ext(...)
    SystemDb(...)        ' base de données externe
    SystemQueue(...)     ' broker / queue externe
    Boundary(alias, label, ?type)
    Enterprise_Boundary(alias, label)
    System_Boundary(alias, label)

Niveau 2 — Container  (toutes les macros de Context +)
    Container(alias, label, ?techn, ?descr, ?sprite, ?tags, ?link)
    ContainerDb(...)
    ContainerQueue(...)
    Container_Ext(...)
    Container_Boundary(alias, label)

Niveau 3 — Component  (toutes les précédentes +)
    Component(alias, label, ?techn, ?descr, ?sprite, ?tags, ?link)
    ComponentDb(...)
    ComponentQueue(...)
    Component_Ext(...)

Deployment           (toutes les précédentes +)
    Deployment_Node(alias, label, ?type, ?descr)
    Node(...)            ' alias court
    Node_L(...) / Node_R(...)

Dynamic              (numérotation des relations)
    Index($offset=1)
    SetIndex($new_index)
    LastIndex()

7.2 La grammaire de suffixage à mémoriser

SuffixeSensExemple
(rien)Élément interne au périmètreContainer(api, ...)
_ExtÉlément externe au périmètreContainer_Ext(cdn, ...)
DbBase de données / stockageContainerDb(pg, ...)
QueueFile / topic / brokerContainerQueue(orders, ...)
_BoundaryCadre de regroupementContainer_Boundary(api, ...)

À retenir — On peut bien sûr combiner les suffixes :

ContainerDb_Ext(legacy, "Base héritée", "Oracle", "Données RH")
ComponentQueue_Ext(q, "File externe", "MSK", "Événements partenaires")

7.3 Argumentation des macros

Tous les arguments précédés de ? sont optionnels et peuvent être passés nommés avec $nom="valeur" pour sauter les optionnels antérieurs :

' Positionnel — ordre strict
Container(api, "API", "Java", "Expose l'API REST")

' Nommé — saute le sprite et les tags
Container(api, "API", "Java", "Expose l'API REST", $link="https://wiki/api")

8. Relations et orientations

8.1 La relation de base

Rel(source, cible, "label décrivant l'intention", "?techno")

Bonnes pratiques :

  • toujours orienter : la flèche va de l'appelant vers l'appelé, ou du producteur vers le consommateur ;
  • toujours étiqueter avec un verbe précis ("Pousse les commandes vers"), pas un verbe générique ("Utilise") ;
  • pour les relations inter-conteneurs, toujours indiquer le protocole : "HTTPS/JSON", "AMQP", "JDBC", "gRPC", "WebSocket"

8.2 Forcer la direction visuelle

PlantUML est libre de placer les éléments. Vous pouvez suggérer une direction :

MacroDirectionAlias longs
Rel_Uvers le hautRel_Up
Rel_Dvers le basRel_Down
Rel_Lvers la gaucheRel_Left
Rel_Rvers la droiteRel_Right
Rel_Backsens inverse de l'écriture
Rel_Neighborrapproche les éléments

8.3 Bidirectionnel

BiRel(api, db, "Lit / écrit", "JDBC")
BiRel_R(serviceA, serviceB, "Synchronise", "gRPC")

À utiliser avec parcimonie : une vraie bidirectionnalité est rare. Souvent deux flèches orientées sont plus parlantes.

8.4 Forcer la mise en page sans relation

Il arrive qu'on veuille positionner un élément sans introduire de fausse relation. Les macros Lay_* n'affichent rien mais influencent le placement :

Lay_U(a, b)   ' b est positionné au-dessus de a
Lay_D / Lay_L / Lay_R

Pour les légendes flottantes : Lay_Distance(from, to, ?distance) règle finement l'espacement.


9. Frontières (Boundaries)

Les frontières regroupent visuellement des éléments et matérialisent un périmètre logique.

FrontièreQuand l'utiliser
System_Boundary(c1, "Banque en ligne") { ... }Délimiter le système modélisé sur un diagramme de conteneurs
Container_Boundary(api, "API") { ... }Délimiter un conteneur sur un diagramme de composants
Enterprise_Boundary(org, "Banque SA") { ... }Délimiter une organisation sur un System Landscape
Boundary(g, "Microservice X") { ... }Frontière générique, libellable (?type)

Syntaxe :

System_Boundary(banque, "Banque en ligne") {
    Container(spa, "SPA", "Angular", "UI client")
    Container(api, "API", "Java/Spring", "Logique métier")
    ContainerDb(db, "Base", "PostgreSQL", "Données utilisateurs")
}

Important — Sur les diagrammes séquence (C4_Sequence.puml), la syntaxe est différente : pas d'accolades, on utilise Boundary_End() pour clore.


10. Mise en page et légende

10.1 Direction globale

LAYOUT_TOP_DOWN()      ' par défaut
LAYOUT_LEFT_RIGHT()    ' lecture horizontale
LAYOUT_LANDSCAPE()     ' format paysage

10.2 Légendes calculées

C4‑PlantUML suit les éléments et tags utilisés et génère automatiquement la légende correspondante.

MacroEffetÀ utiliser quand
SHOW_LEGEND()Légende sous le diagramme. Supporte les tags personnalisés.Cas par défaut
LAYOUT_WITH_LEGEND()Combinaison rapide : LAYOUT_TOP_DOWN() + légende à droite.Diagrammes simples sans tags personnalisés
SHOW_FLOATING_LEGEND()Légende repositionnable via Lay_Distance().Légende à placer manuellement

RègleSHOW_LEGEND() doit être l'avant-dernière ligne du diagramme : elle ne peut afficher que les tags déjà rencontrés.

10.3 Style « croquis »

Pour un rendu volontairement esquissé (utile en phase d'idéation pour signaler que rien n'est figé) :

LAYOUT_AS_SKETCH()

10.4 Cacher les stéréotypes

Par défaut, chaque élément affiche son type entre «» (ex. «container»). Pour le masquer :

HIDE_STEREOTYPE()
' ou en argument de SHOW_LEGEND :
SHOW_LEGEND(true)

11. Sprites, icônes et thèmes (vue d'ensemble)

11.1 Sprites pré-définis

C4‑PlantUML fournit person, person2, robot, robot2 :

Person(alice, "Alice", $sprite="person2")
System_Ext(bot, "Robot d'indexation", $sprite="robot")

11.2 Bibliothèques d'icônes

Les icônes des SI réels (langages, clouds, bases de données) sont fournies par des dépôts tiers, par exemple plantuml-icon-font-sprites :

!define DEVICONS https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/master/devicons
!define FONTAWESOME https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/master/font-awesome-5
!include DEVICONS/angular.puml
!include DEVICONS/java.puml
!include DEVICONS/postgresql.puml
!include FONTAWESOME/users.puml

Person(user, "Utilisateur", $sprite="users")
Container(spa, "SPA", "Angular", $sprite="angular")
Container(api, "API", "Java", $sprite="java")
ContainerDb(db, "Base", "PostgreSQL", $sprite="postgresql")

11.3 Trois sources possibles d'images

FormatExempleUsage
Sprite PlantUML$sprite="angular"Icônes vectorielles incluses
URL d'image$sprite="img:https://.../logo.png"Logos PNG/SVG ad hoc
OpenIconic$sprite="&envelope-closed"Glyphes intégrés à PlantUML

Bon réflexe — Les icônes parlent vite mais ne remplacent pas les libellés. C4 reste un outil de communication écrite ; les icônes y sont une aide visuelle, pas une grammaire.

11.4 Thèmes

Plusieurs thèmes prêts à l'emploi sont distribués (C4_blue, C4_green, C4_united, etc.). On les active comme un !theme PlantUML standard.


12. Tags et styles personnalisés (vue d'ensemble)

Les tags permettent de marquer des éléments ou des relations pour leur appliquer un style (couleur, forme, ligne) et apparaître dans la légende.

12.1 Tag d'élément

AddElementTag("legacy", $bgColor="#9E9E9E", $borderColor="#616161",
              $legendText="Système hérité")

Container(monolith, "Monolithe", "Java 7", "À démanteler", $tags="legacy")

12.2 Tag de relation

AddRelTag("async", $textColor="#1565C0", $lineColor="#1565C0",
          $lineStyle=DashedLine())

Rel(api, queue, "Pousse les événements", "AMQP", $tags="async")

12.3 Combinaison de tags

Plusieurs tags se combinent par + :

Container(api, "API", $tags="v1.0+critique")

12.4 Constantes utiles

  • Formes : SharpCornerShape() (par défaut), RoundedBoxShape(), EightSidedShape().
  • Lignes : SolidLine() (par défaut), DashedLine(), DottedLine(), BoldLine().

Garde-fou — Si vous codez par couleur, soyez cohérent entre tous vos diagrammes (la même couleur doit signifier la même chose). Et pensez aux daltoniens et à l'impression noir et blanc.


13. Notation, lisibilité et règles d'or

C4 est indépendant de la notation. Cela libère, mais oblige à la rigueur. Les règles ci-dessous sont distillées du checklist de Simon Brown et de la pratique.

13.1 Le diagramme

  • Titre explicite : type + portée. Ex. "Diagramme de conteneurs — Banque en ligne".
  • Légende présente et utile. Toute couleur, forme, style de bordure ou de ligne y est expliquée.
  • Périmètre clair : on doit voir où s'arrête le système modélisé.

13.2 Les éléments

  • Chaque élément a un nom, un type explicite (Person, Container…) et une description courte.
  • Chaque conteneur et composant porte sa technologie (Java 21, Postgres 15, Kafka 3.x…).
  • Acronymes et abréviations sont explicités dans la légende ou dans la description.

13.3 Les relations

  • Une flèche = une intention unidirectionnelle.
  • Étiquette précise alignée avec la direction : "Pousse les paiements vers" plutôt que "Utilise".
  • Pour toute communication inter-processus, le protocole est sur la flèche.

13.4 La hiérarchie

  • Un seul niveau d'abstraction par diagramme.
  • On ne mélange jamais un système avec ses composants : il manquerait l'étape conteneur.
  • Les éléments sont cohérents entre niveaux (un conteneur du niveau 2 est le conteneur dont on déroule les composants au niveau 3).

14. Erreurs fréquentes à éviter

D'après la conférence C4 Misconceptions, Misuses & Mistakes de Simon Brown (GOTO 2024) et les retours de terrain.

14.1 Sur les abstractions

  • Confondre conteneur et composant. Test à appliquer : « Est-ce déployable séparément ? » Si oui → conteneur. Sinon → composant.
  • Inventer des « sous-composants » ou des « sous-systèmes ». On retombe dans le chaos initial. C4 propose 4 niveaux ; restez-y.
  • Modéliser une bibliothèque partagée comme un conteneur. Une lib n'est pas une unité déployable — c'est du code partagé, à représenter au mieux comme un composant figurant dans plusieurs conteneurs.

14.2 Sur le contenu

  • Pas de métadonnées. Sans le type explicite (Container, Component…), le diagramme redevient ambigu.
  • Pas assez de texte. Ajouter une description courte par élément clarifie le diagramme et économise un fichier de notes parallèle.
  • Décisions sur le diagramme. Un diagramme C4 montre le résultat des décisions, pas le processus de décision. Les décisions vont dans des ADR.

14.3 Sur l'externe

  • Détailler l'intérieur des systèmes externes. On ne contrôle pas leur évolution ; on s'en tient à la frontière et aux interactions.

14.4 Sur les brokers

  • Modéliser le broker comme un seul conteneur. Le couplage réel est par queue / topic. Représentez chaque queue/topic comme un conteneur (ContainerQueue), ou matérialisez-les comme étiquette sur la flèche (cf. § 15.2).

14.5 Sur la couleur

  • Penser que bleu/gris est obligatoire. C4 est notation independent. Vous pouvez choisir n'importe quelle palette tant qu'elle est cohérente et expliquée.

15. Cas particuliers utiles

15.1 Microservices

Le bon niveau de modélisation dépend de la propriété :

  • Une équipe possède l'ensemble → chaque microservice est un groupe de conteneurs (souvent : conteneur API + conteneur base de données) à l'intérieur d'un seul système logiciel.
  • Plusieurs équipes, un service par équipe → chaque microservice devient un système logiciel à part entière, avec son propre diagramme de contexte.
Container — plateforme commerce (équipe unique)Plateforme[system]«container»UI[React] Façade utilisateur«container»Service catalogue[Go] Recherche produits«container»Base catalogue[Postgres]«container»Service commande[Java] Gestion commandes«container»Base commandes[Postgres]«person»ClientUtilise[HTTPS]Recherche[JSON/HTTPS]Commande[JSON/HTTPS]Lit / écrit[SQL]Lit / écrit[SQL]

15.2 Files et topics

Trois représentations possibles, classées par justesse :

  • Modéliser le broker entier comme un conteneur → ❌ masque le couplage réel.
  • Chaque file/topic comme un conteneur (ContainerQueue) → ✅ explicite.
  • Implicite via la flèche (« envoie via la file orders.created ») → ✅ équivalent, plus visuel pour le pur point-à-point.
«container»Service A[Go] Producteur«container»Service C[Java] Consommateur«container»orders.created[Kafka topic] Événements de création decommandesPublie[Kafka]Délivre[Kafka]

15.3 Diagramme dynamique

Mêmes éléments, flèches numérotées ; à utiliser pour scénariser un cas d'utilisation précis (ex. connexion d'un utilisateur).

API[container]«component»SignInController[Spring MVC] Reçoit la requête«component»SecurityComponent[Spring Bean] Vérifie les identifiants«container»Base[Postgres] Identifiants hashés«container»SPA[Angular] UI utilisateur1: Soumet les identifiants[JSON/HTTPS]2: Vérifie viaisAuthenticated()3: SELECT * FROM usersWHERE [JDBC]

Les flèches sont automatiquement numérotées 1, 2, 3.

15.4 Diagramme de déploiement

Les conteneurs vivent dans des nœuds (Deployment_Node) que l'on imbrique pour refléter l'infrastructure : datacenter → serveur → JVM, par exemple.

Déploiement — production«node»Datacenter Paris[OVHcloud]«node»vm-api-01[Ubuntu 22.04]«node»JVM[OpenJDK 21]«node»vm-db-01[Ubuntu 22.04]«node»Poste client[Windows / macOS]«node»Navigateur[Chrome / Firefox]«container»API[Spring Boot] Logique métier«container»Base[Postgres 15]«container»SPA[Angular]Appelle[JSON/HTTPS]Lit / écrit[JDBC]

15.5 Liens cliquables

Tout élément ou relation accepte un argument $link, qui rend la zone correspondante cliquable dans le SVG produit. Idéal pour pointer vers la doc, un runbook, un dashboard.

Container(api, "API", "Java", "Logique métier",
         $link="https://wiki.example.com/api")

16. Atelier guidé : un système de bout en bout

Construisons les deux niveaux essentiels (contexte + conteneurs) pour un même système : une plateforme de partage de notes.

16.1 Cahier des charges, version courte

Une équipe construit NotesShare, une application web qui permet à des utilisateurs d'écrire des notes en markdown et de les partager. Les notes sont chiffrées au repos. La plateforme envoie un e-mail à chaque partage et repose sur un service tiers de stockage objet pour les pièces jointes.

16.2 Niveau 1 — Contexte

Contexte — NotesShareAuteur Rédige et partage des notesLecteur Consulte des notespartagéesNotesShare Plateforme de notesmarkdown chiffréesStockage objet Service tiers pour piècesjointesService e-mail Envoie les notifications departageRédige et partage[HTTPS]Consulte[HTTPS]Stocke / lit pièces jointes[S3 API]Envoie notifications[SMTP]Legend  person  system  external system 

Remarques pédagogiques :

  • Auteur et Lecteur sont deux personas distincts : on les sépare car ils ont des intentions différentes.
  • Stockage objet est externe : on ne sait pas comment il est implémenté, et on ne s'en préoccupe pas.
  • Les libellés des flèches sont des verbes précis, pas des « utilise ».

16.3 Niveau 2 — Conteneurs

Conteneurs — NotesShareNotesShare[system]SPA[TypeScript, React] Interface utilisateurAPI[Go] Logique métier, partage,chiffrementBase de données[PostgreSQL] Notes, droits, métanotifications[RabbitMQ] Événements de partageNotifier[Go] Consomme la queue etdéclenche les e-mailsAuteurLecteurStockage objet Service tiersService e-mail Service tiersRédige et partage[HTTPS]Consulte[HTTPS]Appelle[JSON/HTTPS]Lit / écrit[SQL/TLS]Stocke / lit pièces jointes[S3 API]Publie événements[AMQP]Délivre[AMQP]Envoie[SMTP]Legend  person  container  external system  system boundary 

Décisions de modélisation à expliquer :

ChoixPourquoi
SPA et API séparésDeux processus distincts, deux choix techno explicites, deux possibilités de zoom au niveau 3
ContainerQueue plutôt qu'un « broker RabbitMQ »Le couplage réel est porté par la queue, pas par RabbitMQ
Le worker n'est pas un composantIl s'exécute dans son propre processus → c'est une unité déployable → conteneur
blob reste externeOn n'opère pas le service S3 ; on s'en sert

16.4 Quand passer au niveau 3 ?

Lorsque l'on souhaite documenter (par exemple) comment l'API gère le chiffrement : on dessine un diagramme de composants centré sur le conteneur api.


17. Checklist de revue

À passer avant de partager un diagramme. Inspirée du checklist officiel de Simon Brown.

Le diagramme

  • Titre présent, indiquant le type + le périmètre ?
  • Légende présente et complète ?
  • Acronymes et abréviations explicites ou expliqués ?
  • Niveau d'abstraction unique sur tout le diagramme ?

Les éléments

  • Chaque élément a un nom ?
  • Le type de chaque élément est-il explicite (Person, Container…) ?
  • Chaque élément a une description courte ?
  • Chaque conteneur / composant porte sa technologie ?
  • La signification des couleurs, formes, bordures est-elle expliquée ?

Les relations

  • Chaque flèche a une étiquette qui décrit l'intention ?
  • L'étiquette correspond à la direction dessinée ?
  • Le protocole est-il sur les flèches inter-conteneurs ?
  • La signification des têtes de flèche, styles de ligne est-elle expliquée ?

Test ultime — Le diagramme se comprend-il sans narration ? Si une personne extérieure à l'équipe peut l'expliquer en regardant uniquement le dessin et la légende, c'est gagné.


18. Exercices

Les corrections sont à débattre en revue d'équipe — il n'y a souvent pas une seule réponse juste, mais des compromis cohérents.

Exercice 1 — Lire avant d'écrire

Ouvrez le diagramme suivant à la lumière du checklist du § 17 et listez trois défauts.

S[system]«container»App[tech]«container»DB«person»Userusesuses

Pistes : libellés vagues, technologie manquante sur la base, pas de description, pas de titre, pas de légende, type de la base non explicite (ContainerDb aurait été plus juste)…

Exercice 2 — De zéro à un contexte

Modélisez le diagramme de contexte d'un système que vous connaissez (ex. : votre boîte mail). Contraintes :

  • au moins 1 Person, 1 System, 2 System_Ext ;
  • toutes les flèches sont étiquetées avec un verbe précis ;
  • le protocole figure quand la cible est un système externe.

Exercice 3 — Du contexte aux conteneurs

À partir de votre diagramme de l'exercice 2, produisez un diagramme de conteneurs. Pensez à :

  • au moins une ContainerDb ou une ContainerQueue ;
  • une System_Boundary autour des conteneurs internes ;
  • une LAYOUT_WITH_LEGEND() ou SHOW_LEGEND().

Exercice 4 — Microservices

Reprenez l'exemple NotesShare (§ 16) et imaginez que Notifier est désormais géré par une autre équipe. Reproduisez :

  • un diagramme de contexte du point de vue de l'équipe NotesShare ;
  • un diagramme de contexte du point de vue de l'équipe Notifier.

Exercice 5 — Tags et lecture

Ajoutez à NotesShare un tag "critique" (couleur rouge) sur les conteneurs sur le chemin critique de la fonctionnalité de partage, et un tag "async" (ligne pointillée) sur les communications asynchrones. Passez le checklist : qu'est-ce qui change pour le lecteur ?


19. Aide-mémoire

19.1 Squelette d'un diagramme C4‑PlantUML

Conteneurs — Mon SystèmeMon Système[system]App[Tech] DescriptionBase[PostgreSQL] DescriptionAlice Persona principalService tiers DescriptionVerbe précis[Protocole]Lit / écrit[JDBC]Appelle[JSON/HTTPS]Legend  person  container  external system  system boundary 

19.2 Tableau des macros à connaître

CatégorieMacros
ActeursPerson(), Person_Ext()
SystèmesSystem(), System_Ext(), SystemDb(), SystemQueue()
ConteneursContainer(), Container_Ext(), ContainerDb(), ContainerQueue()
ComposantsComponent(), Component_Ext(), ComponentDb(), ComponentQueue()
FrontièresSystem_Boundary(), Container_Boundary(), Enterprise_Boundary(), Boundary()
RelationsRel(), BiRel(), Rel_U/D/L/R(), Rel_Back(), Rel_Neighbor()
Mise en pageLAYOUT_TOP_DOWN(), LAYOUT_LEFT_RIGHT(), LAYOUT_LANDSCAPE(), Lay_U/D/L/R(), Lay_Distance()
LégendeSHOW_LEGEND(), LAYOUT_WITH_LEGEND(), SHOW_FLOATING_LEGEND()
StyleLAYOUT_AS_SKETCH(), HIDE_STEREOTYPE(), AddElementTag(), AddRelTag(), AddBoundaryTag()
DéploiementDeployment_Node(), Node(), Node_L(), Node_R()
DynamiqueIndex(), SetIndex(), LastIndex()

19.3 Cinq règles à graver

  1. Un niveau par diagramme. On ne mélange pas systèmes et composants.
  2. Tout est étiqueté. Éléments, relations, technologies, protocoles.
  3. Les frontières montrent la propriété. System_Boundary cerne ce que l'équipe possède.
  4. Le type est toujours explicite. Garder les stéréotypes ou les rendre visibles d'une autre façon (légende, forme).
  5. C4 est indépendant de la notation, pas de la rigueur. Choix de couleurs libre, mais cohérence et explicitation obligatoires.

Suite naturelle. Une fois ces bases acquises, les sujets à creuser : sprites avancés et icônes par technologie, système de tags pour évolution (v1.0 / v1.1), génération à partir du code (Structurizr DSL, archtools…), intégration CI/Confluence/GitLab, et la version as code portable Structurizr DSL → PlantUML.


Disclaimer — Ce document condense 14 sources collectées le 2026-05-08.

#SourceAuteur(s)
01c4model.comSimon Brown
02C4-PlantUML (GitHub)Ricardo Niepel et al.
03deepwiki — C4 model
04dev.to — C4 basics
05docdac — PlantUML C4
06Communicating Software Architecture with C4 (ebook)Luca Mezzalira
07Hitchhiker's Guide to PlantUML
08icepanel.io — What is C4?
09InfoQ — C4 Architecture Model
10medium.com — C4 Autoware example
11medium.com — Understanding C4 with PlantUML
12PlantUML stdlib (C4 section)
13Wikipedia — C4 model
14working-software.com — C4 mistakes