Ça a commencé comme beaucoup de projets inter-équipes : avec de bonnes intentions et une multitude d’avis. Une autre équipe a été intégrée pour travailler sur une partie importante de notre système. Nous partagions le même dépôt de données, mais pas les mêmes habitudes. Nos compétences, nos normes et nos conceptions de la « bonne architecture » étaient diamétralement opposées.
On nous avait demandé de tout documenter dans Confluence. Mais Confluence est vite devenu ce qu'il est souvent : un véritable cimetière de processus. Personne ne le consultait pour prendre des décisions, et ceux qui le faisaient étaient incapables de savoir quelles pages étaient à jour ou qui avait donné son accord.
Les décisions se prenaient partout : en réunion, lors de demandes de fusion, dans les couloirs, par messages tardifs. Chacun disposait d’informations partielles et personne n’avait une vision d’ensemble. Le décalage était devenu à la fois technique et culturel.
C’est alors que nous avons rapproché les décisions du travail lui-même, en les intégrant au référentiel. Nous avons introduit les fiches de décision d’architecture (FDA), ou ADR en anglais : de courts documents servant à capturer le raisonnement derrière les choix techniques. Traditionnellement utilisées pour les décisions stratégiques, nous avons commencé à les appliquer également aux petits choix du quotidien. Ces micro-décisions, concernant la nomenclature, la structure, les tests ou les limites, étaient précisément le point faible de la collaboration. Leur encapsulation a permis de rétablir la clarté.
Plus tard, lorsque les outils d'IA sont entrés dans notre flux de travail, ces mêmes ADR se sont avérés utiles d'une seconde manière : ils offraient aux agents quelque chose de mieux que du code à lire. Ils leur fournissaient une mémoire durable.
Plus la documentation s'éloigne du travail, plus elle perd rapidement de son autorité. L'IA ne fait qu'accentuer ce décalage.
Sur papier, nous avions déjà de la documentation : des pages consacrées à l’architecture, des schémas et des normes. Elle suivait un schéma bien connu : une période d’activité marquée suivie d’un lent déclin.
Le problème n'était pas la paresse, mais la distance. Lorsqu'une décision parvenait à Confluence, elle avait déjà perdu son contexte. La page n'était plus que l'écho d'une conversation qui avait eu lieu ailleurs. Avec le temps, ces échos s'estompaient. Les nouveaux ingénieurs ne savaient plus ce qui était encore pertinent. Les plus expérimentés, quant à eux, ont cessé de faire confiance à la documentation.
Confluence était devenu un musée des décisions passées plutôt qu'un lieu où les décisions actuelles pouvaient continuer d'évoluer. Il nous fallait quelque chose de plus proche du code, une documentation qui reflète les conséquences de nos actes.
Ce problème s'accentue avec l'IA. Un développeur humain peut parfois compenser une documentation insuffisante en se renseignant, en interprétant les sous-entendus ou en se remémorant des conversations antérieures. Un agent d'IA a besoin que ce contexte soit consigné par écrit, facilement accessible et à proximité de son environnement de travail. Sans une mémoire architecturale claire, il optimise localement. Il perçoit des schémas, mais pas les intentions. Il peut reproduire une convention sans savoir si elle est délibérée, obsolète, accidentelle ou contestée.
C’est ainsi que les équipes se retrouvent avec du code généré par l’IA qui semble plausible tout en violant l’architecture. L’agent peut suivre le schéma local qu’il perçoit, sans pour autant déterminer si ce schéma est pertinent.
L'architecture est devenue plus facile à discuter une fois que le raisonnement a été associé au code.
Nous avons intégré la documentation architecturale au dépôt lui-même, sous forme de simples fichiers Markdown stockés à côté du code. Chaque ADR (Architectural Decision Record) décrit une décision : son contexte, ses compromis et son résultat. Sans cérémonies ni modèles de gestion. Juste une réflexion structurée et transparente.
Au départ, nous utilisions les ADR pour les décisions de conception majeures : patron de conception, modèles de données, intégrations. Les véritables frictions résidaient souvent dans des choix plus mineurs. Il s’agissait des zones d’ombre où le style, l’intention et la responsabilité s’entrechoquaient. Nous avons donc commencé à rédiger des micro-ADR : de courts enregistrements pour les conventions locales, la nomenclature, les stratégies de test, les limites des API, les structures de dossiers ou les règles de dépendance. Leur rédaction ne prenait que quelques minutes et nous a permis d’économiser des heures de débat.
Une mauvaise procédure d’ADR est généralement une décision prise sans réflexion.
Décision: Utilisez le modèle de dépôt pour l'accès aux données.
Statut: Accepté.
Raison: Cest plus propre.
Ce type d’ADR ressemble à de la documentation, mais son utilité est très limitée. Elle enregistre le résultat sans saisir la tension qui rendait la décision pertinente. Un nouveau développeur peut voir le choix effectué, mais doit encore deviner le raisonnement. Un agent d'IA rencontre le même problème : il peut suivre les instructions, mais il est incapable de comprendre les contraintes architecturales sous-jacentes.
Une meilleure procédure d’ADR permet de rendre le raisonnement visible :
Titre : Utilisez des dépôts dédiés pour les opérations de domaine nécessitant de nombreuses écritures.
Statut : Accepté.
Contexte : Les contrôleurs mélangeaient la logique de validation, de persistance et de transaction. Cela rendait les flux d'écriture plus difficiles à tester et provoquait des bogues récurrents liés aux mises à jour partielles.
Options envisagées : Conservez la persistance dans les contrôleurs, masquez toute la persistance derrière des dépôts génériques ou introduisez des référentiels dédiés aux opérations nécessitant de nombreuses écritures.
Décision : Utilisez des dépôts dédiés aux écritures complexes, tout en conservant les lectures simples dans les services de requêtes.
Conséquences : Les flux d'écriture sont plus faciles à tester. Les lectures simples restent légères. Évitez les dépôts qui se contentent d'encapsuler des appels ORM basiques.
Déclencheur de révision : À revisiter si les dépôts deviennent des abstractions passe-plat.
La seconde version conserve la justification du choix. Elle explique dans quels cas le patron s'applique, dans quels cas il ne s'applique pas et quand l'équipe devrait le revisiter. C'est utile aux développeurs et c'est précisément le type de contexte dont un agent a besoin avant de générer du code.
Pour que les décisions restent pertinentes, nous avons créé une boucle légère :
Au fil du temps, cette pratique s'est intégrée à la routine plutôt que de constituer une étape supplémentaire du processus. Les décisions sont devenues visibles, vérifiables et continues car elles étaient gérées de manière autonome, au même titre que le travail qu'elles influencent.
Une fois que nous avons commencé à utiliser des assistants IA, les ADR sont devenus, le plus souvent, partie intégrante du contexte de développement que nous souhaitions voir consulté par les agents. Un agent de développement pouvait être configuré pour consulter le dossier ADR avant de proposer une refactorisation. Un assistant de relecture pouvait signaler les demandes de fusion qui contredisent les décisions déjà acceptées. Un chatbot d'intégration pouvait expliquer pourquoi le système utilise un modèle particulier en citant l'ADR correspondante, au lieu de fournir une explication saugrenue.
Cela a transformé notre vision de la documentation. Les ADR sont devenues un contexte exploitable lors du développement. Une décision est plus facile à réutiliser lorsqu'elle conserve les contraintes, les pressions et les compromis qui la sous-tendent.
Ici, le terme « agent » désigne tout outil d’assistance par IA capable de lire le contexte d’un projet et d’agir sur une tâche : un assistant de codage, un robot de révision, un assistant de documentation ou un chatbot d’intégration.
Les outils d'IA abordent souvent chaque tâche avec une vision partielle du système. Cela peut suffire pour des modifications mineures, mais l'architecture repose sur la mémoire : les contraintes passées, les options rejetées, les compromis acceptés et les raisons qui justifient l'existence d'une limite.
L'architecture accumule les jugements au fil du temps. Pourquoi avons-nous évité un framework ? Pourquoi avons-nous scindé un service ? Pourquoi tolérons-nous la duplication à un endroit et l'interdisons-nous à un autre ? Pourquoi avons-nous rejeté une abstraction ? Le code, lui, conserve rarement ce type de raisonnement de lui-même.
Les ADR transforment ce jugement manquant en mémoire récupérable. Ces données ne sont pas dissimulées dans un modèle. Elles sont disponibles en texte brut dans le dépôt : versionnées, consultables et appartenant à l’équipe.
Un bon ADR fournit à l'agent le raisonnement que le code laisse généralement implicite. Il explique le contexte d'une décision, nomme les contraintes pertinentes, consigne les alternatives envisagées, recense les compromis acceptés par l'équipe et énonce la décision actuelle avec suffisamment de clarté pour être appliquée.
Trois comportements d'agents se sont avérés particulièrement utiles.
1. Récupérez avant de changer
Avant de modifier la persistance, les limites de l'API, la stratégie de test ou la structure du service, l'agent consulte les ADR acceptées et obsolètes pour identifier les décisions pertinentes. Il peut ainsi synthétiser les contraintes avant de proposer du code. L'agent ne se base plus uniquement sur les fichiers environnants; il consulte l'historique des décisions de l'équipe avant d'agir.
2. Conflits de surface
Lors de l'examen, l'agent compare la modification proposée aux ADR existantes et signale toute dérive.
Cette implémentation introduit la logique de persistance dans le contrôleur. L'ADR-014 recommande de réserver la persistance intensive en écriture à des dépôts dédiés, car la persistance au niveau du contrôleur a provoqué des bogues transactionnels récurrents. Il est conseillé de déplacer cette logique dans le dépôt d'écriture existant ou de mettre à jour l'ADR si l'équipe souhaite modifier cette convention.
Ce type de commentaire est utile car il est précis, étayé et vérifiable. Il arrive que le code doive être modifié. Il arrive aussi que l’ADR soit obsolète. L'important est que le conflit soit mis en évidence.
3. Rédigez le document manquant
Lorsqu'une demande de fusion introduit une nouvelle convention, annule une ancienne convention ou expose une décision discutée de manière informelle, l'agent peut suggérer une ébauche de résolution de problèmes. Celle-ci peut résumer le contexte, lister les compromis et demander à l'auteur de confirmer le raisonnement. Cela permet de réduire le coût de la documentation tout en préservant la responsabilité au sein de l'équipe.
Les agents peuvent également contribuer à détecter les incohérences. Si un ADR indique que le système suit un modèle alors que l'implémentation a manifestement évolué, l'agent peut signaler cette incohérence. L'équipe peut alors décider de mettre à jour le code, l’ADR ou d'annuler officiellement l'ancienne décision.
Utilisé de cette manière, le dossier ADR s'intègre au contexte de travail de l'équipe. Les développeurs et les agents peuvent ainsi comprendre l'intention, remettre en question les hypothèses et veiller à ce que les décisions architecturales restent liées au code qu'elles affectent.
Les premières semaines ont paru interminables. Rédiger des ADR pour des choix de conception mineurs semblait excessif, une sorte de paperasse qui s'immisçait dans le domaine de l'ingénierie.
Puis quelque chose a changé.
Les conversations qui s'éternisaient auparavant ont commencé à se résoudre plus rapidement. Les revues de code sont devenues plus faciles. Les désaccords semblaient moins personnels car le raisonnement était déjà consigné par écrit. L'intégration des nouveaux développeurs a été plus rapide car la question « Pourquoi procédons-nous ainsi? » disposait d'une réponse claire et durable. Les ingénieurs juniors ont appris en consultant les ADR précédents. Les ingénieurs seniors ont peaufiné leurs arguments par écrit au lieu de s'appuyer sur l'autorité.
Lorsqu'une autre équipe externe a rejoint le projet par la suite, la différence était flagrante. Ils n'avaient plus besoin de deviner notre mode de fonctionnement. Les ADR ont permis de clarifier nos normes et de les présenter comme des échanges ouverts plutôt que comme des règles strictes. Ils ont même intégré leurs propres ADR, combinant ainsi leur expérience à la nôtre.
L'IA a amplifié cet effet. Au lieu de considérer le dépôt comme un ensemble de code et de documentation éparse, nous pouvions le considérer comme un dépôt contenant à la fois le code et sa justification. Le code décrivait l'état actuel du système, tandis que les ADR expliquaient le raisonnement sous-jacent à cet état. L'agent pouvait ainsi naviguer entre les deux.
Cela a rendu l'assistance par IA plus sûre et plus utile. Les instructions sont devenues plus simples, car nous pouvions orienter l'agent vers le bon souvenir au lieu de réexpliquer l'ensemble du système à chaque fois. « Suivez les ADR acceptées. » « Vérifiez si cela entre en conflit avec nos stratégies de test. » « Trouvez la décision qui explique cette limite. » Ces instructions ont fonctionné car le souvenir était déjà présent.
Par exemple, lorsqu'un développeur demandait à un agent d'ajouter un nouveau point de terminaison, l'agent pouvait d'abord consulter la directive ADR relative aux conventions d'API. Il constatait alors que nous privilégions les objets de requête explicites plutôt que les ensembles de paramètres non structurés, que la validation devait être effectuée au plus près de la limite de l'API et que la logique métier devait rester en dehors des contrôleurs. Le code généré était ainsi plus conforme à nos normes, car l'agent avait accès à leur justification.
Lorsqu'une nouvelle approche d'intégration était proposée, un agent pouvait consulter l'ancien ADR qui expliquait le rejet d'une approche similaire. Cela ne mettait pas fin à la discussion, mais l'enrichissait. L'équipe pouvait ainsi vérifier si les contraintes initiales étaient toujours applicables, au lieu de devoir redécouvrir le même compromis depuis le début.
En définitive, les commentaires les plus pertinents s'appuyaient sur des décisions reconnues plutôt que sur des préférences personnelles. Au lieu de débattre de la pertinence d'un modèle, nous pouvions nous référer à la décision administrative, examiner le compromis initial et déterminer si la modification actuelle restait appropriée.
C’est là qu’a eu lieu le changement culturel. L’architecture ne se résumait plus aux API, aux flux de données et aux dépendances. Elle est devenue une manière partagée d’appréhender la complexité. Les équipes répètent les mêmes erreurs lorsque la mémoire fait défaut. Les désaccords prennent une tournure politique lorsque le raisonnement est occulté. Les ADR nous ont permis de préserver à la fois la décision et le débat qui l’entourait.
Les ADR ont bouleversé bien plus que nos habitudes de documentation. Elles ont transformé notre processus décisionnel. Le dépôt contenait le code et le raisonnement collectif qui le sous-tendent. L'IA a ensuite simplifié la récupération, la réutilisation et la mise à l'épreuve de ce raisonnement.
La plus petite réponse utile aux ADR n'a pas besoin d'être longue. Elle doit simplement répondre clairement à quelques questions :
Cette dernière question est particulièrement importante. Une décision sans possibilité de réexamen peut devenir un dogme. Une décision assortie d'une possibilité de réexamen demeure valable.
Pour les équipes assistées par l'IA, j'ajouterais un champ supplémentaire :
Conseils de l'agent : Lors de la génération ou de la révision de code dans ce domaine, veuillez respecter cette décision, sauf si l'équipe la réexamine explicitement. Si une modification semble entrer en conflit avec cette ADRs, veuillez signaler le conflit avant de proposer une implémentation.
Ce simple ajout transforme l’ADR en un outil exploitable par un agent. Il traduit le raisonnement architectural en comportement opérationnel. Un modèle complet peut être stocké séparément, en annexe ou comme fichier de démarrage, dans le référentiel. L'article lui-même n'a besoin que du principe suivant : les ADR utiles comportent une justification suffisante pour permettre aux personnes et aux agents d'agir de manière responsable.
Commencez par des décisions simples, une à la fois. Conservez les ADR au plus près du travail afin qu'elles préservent le raisonnement sous-jacent au système. Rédigez-les de manière suffisamment claire pour qu'un nouveau développeur puisse les comprendre et suffisamment concrète pour qu'un agent puisse les utiliser.
Dans un contexte d'ingénierie assistée par l'IA, une documentation imprécise devient un handicap. Les agents agissent en fonction du contexte qu'on leur fournit, et le silence en fait aussi partie. Les ADR permettent aux équipes de formaliser clairement leurs intentions et de les rendre pérennes et accessibles au moment de la prise de décision.
Un dossier ADR bien tenu à jour permet de conserver les décisions pour les personnes qui maintiennent le système aujourd'hui et pour les outils qui les aideront de plus en plus à le faire évoluer demain.
ADR-018 : Évitez d’intégrer la logique métier aux contrôleurs
Statut : Accepté
Contexte
Les contrôleurs du service de facturation avaient commencé à accumuler des validations, des contrôles d'autorisation, une logique de persistance et des règles de domaine. Cela a permis d'accélérer la création des points de terminaison au départ, mais a rendu leur test et leur modification plus difficiles. Plusieurs bogues provenaient de petites différences entre des contrôleurs censés appliquer la même règle.
Décision
Les contrôleurs doivent gérer les aspects liés au transport : analyse des requêtes, contexte d’authentification, formatage des réponses et délégation. Les règles de domaine doivent résider dans les services applicatifs ou dans les objets de domaine, selon la complexité du flux.
Alternatives envisagées
Pour des raisons de performance, il est recommandé de conserver la logique dans les contrôleurs. Cette solution a été rejetée, car le comportement variait déjà d’un point de terminaison à l’autre.
Déplacer toute la logique dans des entités de domaine. Cette proposition a été rejetée car certains flux coordonnent des systèmes externes et n'ont pas leur place dans les entités.
Utilisez les services applicatifs pour l'orchestration et les objets de domaine pour les règles principales. Cette approche a été retenue car elle permet de limiter le nombre de contrôleurs tout en évitant des entités de domaine trop volumineuses.
Conséquences
Les nouveaux points de terminaison peuvent nécessiter une structure légèrement plus élaborée. Les tests sont plus faciles à cibler, car le comportement se situe en dehors de la couche de transport. Les revues de code doivent signaler les règles métier ajoutées directement aux contrôleurs.
Révision du déclencheur
Reconsidérer cette décision si les services applicatifs deviennent des dépotoirs de procédures ou si des points de terminaison simples nécessitent des formalités excessives.
Conseils de l'agent
Lors de la génération du code des points de terminaison, privilégiez des contrôleurs légers. Placez l'orchestration dans les services applicatifs et les règles métier principales dans les objets de domaine, le cas échéant. Lors de la revue, signalez les règles métier au sein des contrôleurs et citez cette directive de conception. Si l'utilisateur demande une implémentation plus simple, expliquez-lui les avantages avant de modifier la structure.