Chaque diagramme d’architecture que j’ai vu dans un wiki était faux. Pas dramatiquement faux. Juste calmement, progressivement faux. Le service nommé « Auth » a été divisé en trois microservices il y a six mois. La flèche marquée « sync call » est maintenant async via une queue. La base de données nommée « PostgreSQL » a été migrée vers autre chose lors d’un drill et personne n’a mis à jour la case.
Ce n’est pas de la négligence. C’est de la physique. Le code change des centaines de fois par semaine. La documentation change quand quelqu’un s’en souvient. La demi-vie d’un diagramme d’architecture est d’environ un sprint. Après ça, il devient de la fiction.
Le but n’est pas d’écrire des docs qui ne dérivent jamais. Le but est de détecter la dérive avant qu’elle ne mène le prochain ingénieur en erreur.
Pourquoi les docs pourrissent plus vite que le code
Le code possède un mécanisme de correction intégré : il compile et passe les tests, ou non. La documentation n’a pas de compiler, de suite de tests, de porte CI. Un mauvais diagramme s’affiche parfaitement. Un ADR périmé se lit avec autant de conviction qu’un ADR récent.
La divergence est aussi sociale. Les ingénieurs mettent le code à jour parce que le build casse. Ils mettent la documentation à jour parce qu’ils se sentent coupables. La culpabilité est un planificateur peu fiable.
Quand un nouvel ingénieur arrive et lit le wiki, il construit un modèle mental du système. Si ce modèle a six mois de retard, il prendra des décisions qui aggravent le désordre existant. La documentation qui était censée réduire la friction d’onboarding devient une source d’égarement subtil et coûteux.
Les trois pièges de la fiction
Il existe trois endroits où la documentation d’architecture devient de la fiction le plus rapidement.
Le cimetière du wiki. Les docs d’architecture dans Confluence, Notion ou SharePoint vivent en dehors du repo. Elles n’ont pas d’historique de commits corrélé aux changements de code. Quand un refactor supprime un service, la page du wiki survit comme une ville fantôme numérique. Aucun build ne casse. Aucune alerte ne se déclenche.
La fiction du diagramme. Un beau diagramme exporté depuis Lucidchart ou draw.io et collé dans un README paraît faire autorité. C’est aussi une image statique. Le prochain développeur qui change l’architecture doit ouvrir un outil de design, trouver le fichier source, le mettre à jour, le réexporter et le recoller. Ce workflow a un taux de survie de 5 %.
Le README omniscient. Le README de premier niveau qui tente de documenter chaque service, chaque dépendance et chaque flux de données dans un seul fichier. Il devient un méga-document que tout le monde craint de toucher. Finalement, une âme courageuse ajoute une note : « This section may be outdated. » Puis une autre. Puis l’ensemble du document est entouré de guillemets ironiques et abandonné.
Une documentation vivante qui reste honnête
La solution n’est pas d’écrire plus de docs. C’est de rendre les docs incontournables.
Déplacez les docs dans le repository. Si la documentation n’est pas dans la même pull request que le changement de code, elle ne sera pas mise à jour. Les ADR, les runbooks et les journaux de décision devraient vivre dans docs/architecture/ ou docs/adr/ à côté du code qu’ils décrivent. Quand un reviewer voit un refactor sans mise à jour de la doc, il peut bloquer le merge.
Générez les diagrammes depuis le code. Mermaid, PlantUML et Structurizr vous permettent de définir des diagrammes dans des fichiers texte qui vivent dans le repo. Un job CI les rend à chaque commit. Quand l’architecture change, la source du diagramme change avec elle. Aucun outil de design nécessaire.
<!-- docs/architecture/data-flow.md -->
## Ingestion Pipeline
```mermaid
graph LR
A[Client SDK] -->|HTTP POST| B[Ingest API]
B -->|Pub/Sub| C[Event Consumer]
C -->|Write| D[(ClickHouse)]
Ce diagramme peut être relu dans un diff. Quand le pipeline gagne un nouveau topic Kafka, le changement apparaît dans la même PR qui ajoute le consumer.
**Séparez le « quoi » du « pourquoi ».** La codebase décrit déjà ce que le système fait. Les commentaires, les noms de fonctions et les types encodent la structure actuelle. La documentation devrait se concentrer sur pourquoi le système a cette forme. C'est ce qui dérive silencieusement : le raisonnement derrière une décision, pas la décision elle-même.
Les Architecture Decision Records capturent cela. Un ADR n'est pas une spec. C'est une note datée qui dit : « À cette date, pour ces raisons, nous avons choisi ceci. Voici les contraintes que nous avons acceptées. » Quand les contraintes changent, l'ADR est remplacé par un nouveau. L'ancien enregistrement reste comme historique.
## Automatisez le « quoi », écrivez le « pourquoi »
Les docs d'architecture les plus honnêtes sont celles que vous n'écrivez pas à la main.
Les specs OpenAPI générées depuis le code du controller décrivent votre surface d'API avec précision. TypeDoc, RustDoc ou Javadoc décrivent vos types internes. Les graphes de dépendances générés par `cargo tree`, `go mod graph` ou `webpack-bundle-analyzer` montrent la structure réelle des modules.
Pour les contraintes d'architecture de plus haut niveau, les tests d'architecture automatisés servent de filet de sécurité. En Java, ArchUnit peut imposer des règles comme « aucun package dans `domain` ne doit dépendre de `infrastructure`. » En Python, `import-linter` fait la même chose. En Go, vous pouvez écrire un petit test qui parcourt l'AST et fait échouer le build si un import interdit apparaît.
```java
// This test fails the build if architecture rules break.
@ArchTest
static final ArchRule domain_independence =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAPackage("..infrastructure..");
Quand un développeur importe accidentellement le mauvais package, le build casse immédiatement. La doc d’architecture n’a pas besoin de l’avertir. Le compiler le fait.
Les compromis que personne n’avoue
La documentation vivante n’est pas gratuite. Elle coûte du temps de review, des minutes de CI, et l’occasionnel débat sur le fait qu’un changement justifie un nouvel ADR.
Tous les systèmes n’ont pas besoin d’un diagramme. Un monolithe unique avec trois couches n’a pas besoin d’un modèle C4. L’effort pour maintenir des docs générées devrait être proportionnel à la douleur de mal comprendre le système. Si le mauvais modèle mental vous coûte une journée de debugging, investissez une heure dans un diagramme. Si cela vous coûte cinq minutes, écrivez un commentaire.
Les docs générées peuvent aussi mentir. Une spec OpenAPI générée depuis le code décrit chaque endpoint, y compris ceux internes que vous avez oublié de documenter. Un graphe de dépendances montre chaque import, y compris ceux qui violent votre architecture. La vérité générée est exacte mais pas toujours utile. Vous avez toujours besoin d’une curation humaine pour mettre en évidence ce qui compte.
Les ADR s’accumulent. Au bout de deux ans, vous pouvez avoir trente ADR dans docs/adr/. La plupart seront obsolètes. La solution n’est pas de les supprimer. C’est de les marquer clairement : status: superseded avec un lien vers le remplacement. L’historique a de la valeur. La confusion non.
Une configuration minimale qui fonctionne
Vous n’avez pas besoin d’une plateforme de documentation. Vous avez besoin de trois choses dans votre repo.
docs/adr/YYYY-MM-DD-title.mdpour les décisions. Utilisez un template léger :
# ADR 012: Event Storage Backend
- Status: accepted
- Date: 2026-03-15
## Context
We need durable storage for ingestion events with sub-second query latency.
## Decision
Use ClickHouse for hot storage, S3 for cold archival.
## Consequences
- Fast analytical queries on recent data.
- Complex operational footprint compared to PostgreSQL.
- Migration path defined in ADR 013.
-
docs/architecture/*.mdavec des diagrammes Mermaid pour les limites du système et les flux de données. Exigez une mise à jour de la doc dans la même PR que les changements de code structurels. -
Un test d’architecture qui applique votre invariant le plus coûteux. Si vous n’avez qu’une seule règle, faites en sorte qu’elle empêche le dernier refactor douloureux. Ajoutez-en d’autres au fur et à mesure que le système grandit.
FAQ
Dois-je diagrammer chaque microservice ?
Non. Diagrammez les limites où les équipes se passent le relais, où les données franchissent des zones de confiance, et où les pannes se propagent en cascade. Un diagramme de votre service CRUD interne est généralement inutile. Un diagramme des services qui appellent la passerelle de paiement est généralement utile.
Et si mon équipe utilise déjà Confluence ?
Faites un miroir des docs critiques dans le repo et créez des liens. La source de vérité reste dans git. Le wiki devient une couche de commodité. Si le wiki dérive, les ingénieurs savent où trouver la vraie version.
Combien d’ADR est-ce trop ?
Il n’y a pas de limite supérieure, mais il y a une limite de lisibilité. Si un nouvel ingénieur ne peut pas scanner docs/adr/ et comprendre l’évolution du système en dix minutes, ajoutez un index. Regroupez par sous-système. Marquez clairement les enregistrements superseded.
Et les wikis pour les parties prenantes non techniques ?
Les product managers et les dirigeants ont besoin de résumés de haut niveau. Générez-les depuis l’index des ADR. Ne maintenez pas de récit séparé. Les mêmes faits devraient circuler depuis le code source, à travers les ADR, vers des résumés humains. Une source de vérité, plusieurs vues.
Commencez par un ADR et un test
Vous n’avez pas besoin de réformer votre culture de documentation cette semaine. Choisissez la dernière décision d’architecture qui a causé de la confusion. Écrivez un ADR expliquant pourquoi vous avez choisi ce que vous avez choisi. Choisissez l’invariant que vous souhaiteriez voir appliqué automatiquement. Écrivez un test d’architecture qui fait échouer le build quand quelqu’un le viole.
Ces deux artifacts resteront honnêtes parce qu’ils vivent dans le repo, qu’ils sont relus dans des PR, et qu’ils passent le CI ou ne sont pas livrés. Tout le reste, les pages wiki, les slide decks, les posters de conférence, est secondaire. Bon à avoir. Possiblement utile. Probablement faux.