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 :
| Niveau | Nom EN | Nom FR | Public visé |
|---|---|---|---|
| 1 | Context | Contexte système | Tout le monde, technique ou non |
| 2 | Container | Conteneurs | Développeurs, ops, architectes |
| 3 | Component | Composants | Développeurs, architectes |
| 4 | Code | Code | Dé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).
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ère | Conteneur | Composant |
|---|---|---|
| Unité déployable ? | Oui | Non |
| Espace processus ? | Le sien | Partage celui du conteneur hôte |
| Parle aux autres via… | Réseau, IPC, fichier | Appel 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
.pumlvit 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.pumlChoisissez 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 :
| Diagramme | Fichier à inclure |
|---|---|
| Contexte / Landscape | C4_Context.puml |
| Conteneurs | C4_Container.puml (inclut le précédent) |
| Composants | C4_Component.puml (inclut les précédents) |
| Dynamic | C4_Dynamic.puml |
| Deployment | C4_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.
À décortiquer :
@startuml/@enduml— délimitent le diagramme PlantUML.!include <C4/C4_Context>— charge la grammaire C4 niveau 1.title— le titre, toujours présent (le checklist y revient au § 17).Person()— un acteur humain.System()— le système modélisé (mis en avant visuellement).System_Ext()— un système externe (suffixé_Extpartout :Person_Ext,Container_Ext,Component_Ext).Rel(source, cible, "label", "techno")— une relation orientée desourceverscible, avec un libellé qui explique l'intention.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
| Suffixe | Sens | Exemple |
|---|---|---|
| (rien) | Élément interne au périmètre | Container(api, ...) |
_Ext | Élément externe au périmètre | Container_Ext(cdn, ...) |
Db | Base de données / stockage | ContainerDb(pg, ...) |
Queue | File / topic / broker | ContainerQueue(orders, ...) |
_Boundary | Cadre de regroupement | Container_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 :
| Macro | Direction | Alias longs |
|---|---|---|
Rel_U | vers le haut | Rel_Up |
Rel_D | vers le bas | Rel_Down |
Rel_L | vers la gauche | Rel_Left |
Rel_R | vers la droite | Rel_Right |
Rel_Back | sens inverse de l'écriture | — |
Rel_Neighbor | rapproche 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_RPour 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ère | Quand 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 utiliseBoundary_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 paysage10.2 Légendes calculées
C4‑PlantUML suit les éléments et tags utilisés et génère automatiquement la légende correspondante.
| Macro | Effet | À 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ègle —
SHOW_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
| Format | Exemple | Usage |
|---|---|---|
| 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.
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.
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).
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.
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
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
Décisions de modélisation à expliquer :
| Choix | Pourquoi |
|---|---|
| SPA et API séparés | Deux 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 composant | Il s'exécute dans son propre processus → c'est une unité déployable → conteneur |
blob reste externe | On 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.
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
ContainerDbou uneContainerQueue; - une
System_Boundaryautour des conteneurs internes ; - une
LAYOUT_WITH_LEGEND()ouSHOW_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
19.2 Tableau des macros à connaître
| Catégorie | Macros |
|---|---|
| Acteurs | Person(), Person_Ext() |
| Systèmes | System(), System_Ext(), SystemDb(), SystemQueue() |
| Conteneurs | Container(), Container_Ext(), ContainerDb(), ContainerQueue() |
| Composants | Component(), Component_Ext(), ComponentDb(), ComponentQueue() |
| Frontières | System_Boundary(), Container_Boundary(), Enterprise_Boundary(), Boundary() |
| Relations | Rel(), BiRel(), Rel_U/D/L/R(), Rel_Back(), Rel_Neighbor() |
| Mise en page | LAYOUT_TOP_DOWN(), LAYOUT_LEFT_RIGHT(), LAYOUT_LANDSCAPE(), Lay_U/D/L/R(), Lay_Distance() |
| Légende | SHOW_LEGEND(), LAYOUT_WITH_LEGEND(), SHOW_FLOATING_LEGEND() |
| Style | LAYOUT_AS_SKETCH(), HIDE_STEREOTYPE(), AddElementTag(), AddRelTag(), AddBoundaryTag() |
| Déploiement | Deployment_Node(), Node(), Node_L(), Node_R() |
| Dynamique | Index(), SetIndex(), LastIndex() |
19.3 Cinq règles à graver
- Un niveau par diagramme. On ne mélange pas systèmes et composants.
- Tout est étiqueté. Éléments, relations, technologies, protocoles.
- Les frontières montrent la propriété.
System_Boundarycerne ce que l'équipe possède. - Le type est toujours explicite. Garder les stéréotypes ou les rendre visibles d'une autre façon (légende, forme).
- 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.
| # | Source | Auteur(s) |
|---|---|---|
| 01 | c4model.com | Simon Brown |
| 02 | C4-PlantUML (GitHub) | Ricardo Niepel et al. |
| 03 | deepwiki — C4 model | — |
| 04 | dev.to — C4 basics | — |
| 05 | docdac — PlantUML C4 | — |
| 06 | Communicating Software Architecture with C4 (ebook) | Luca Mezzalira |
| 07 | Hitchhiker's Guide to PlantUML | — |
| 08 | icepanel.io — What is C4? | — |
| 09 | InfoQ — C4 Architecture Model | — |
| 10 | medium.com — C4 Autoware example | — |
| 11 | medium.com — Understanding C4 with PlantUML | — |
| 12 | PlantUML stdlib (C4 section) | — |
| 13 | Wikipedia — C4 model | — |
| 14 | working-software.com — C4 mistakes | — |