Stack Labs Blog moves to Dev.to | Le Blog Stack Labs déménage sur Dev.to 🚀
Les ADR pour garder une trace de tous les choix d'architecture
Temps de lecture estimé : 8 minutes
- Pourquoi on a mis ça en place déjà ?
- Euh… ben… je sais plus trop, c’est historique !?
Si vous avez déjà entendu ou utilisé ce genre de phrases, continuez à lire, vous avez vraisemblablement besoin des Architecture Decision Records (ADR).
Que sont les ADR ? C’est très simple : il s’agit de documents qui permettent de retracer toutes les décisions d’architecture importantes qui concernent un logiciel, en leur apportant du contexte.
Contexte
Lors du développement d’un projet, qu’il soit simple ou complexe, on est toujours confronté à un grand nombre de choix architecturaux : quel langage, framework ou système de persistence allons-nous utiliser ?
Ces décisions se font en général en concertation avec les membres de l’équipe en fonction du contexte actuel du projet (nécessité de sortir quelque chose rapidement, applications clients existantes, contraintes de sécurité, etc.). Les décisions en question sont parfois simples (ex. “codons en Java parce que nous avons une équipe de 6 développeurs rôdés à ce langage”) ou parfois plus complexes (“les benchmarks de performance dans notre cas d’utilisation font ressortir Cassandra plutôt que Mongo”). Dans tous les cas, même les décisions qui paraissent simples au moment où elles sont prises peuvent ne plus l’être quelques mois voire quelques années plus tard. C’est particulièrement vrai lorsque les équipes changent rapidement. En effet, les nouveaux arrivés sur le projet auront accès au code qui donnera l’état actuel de l’architecture, mais le code ne permettra pas de donner tout le contexte des décisions prises sur le projet.
La solution ? Demander aux anciens membres de l’équipe ce qui a motivé telle ou telle décision… s’ils travaillent encore sur le projet !
Pour éviter ces écueils les deux solutions les plus fréquemment rencontrées consistent soit à écrire une grosse documentation exhaustive et souvent centralisée, ou alors… à ne pas écrire de documentation du tout. Je ne m’attarderai pas sur le second point, en revanche pour le premier je présume que tout le monde a déjà fait l’expérience d’une belle documentation Confluence qui n’est jamais maintenue et qu’on hésite toujours à aller consulter de peur qu’elle ne reflète plus la réalité de notre architecture. En gros, on peut résumer ça de cette manière :
Ce mécanisme est renforcé dans des contextes agiles où, par définition, toutes les décisions ne sont pas faites au début du projet (on ne démarre pas avec une énorme spécification technique). On construira au contraire notre architecture logicielle au fur et à mesure de l’avancement du projet ce qui signifie d’abord qu’il faut bien penser à mettre à jour la documentation en chemin, mais aussi que l’équipe sera probablement amenée à évoluer au fil du projet. En général quand un nouveau membre rejoint l’équipe et qu’il se pose des questions sur notre application, il peut au choix accepter la décision de peur de casser le système, ou bien refuser la décision et la changer pour une “meilleure” solution. Dans le premier cas, l’accumulation d’acceptations peut mener à une peur de changer l’historique donc à une certaine paralysie du projet. Dans le second cas, changer aveuglément une décision peut avoir des répercussions imprévues et potentiellement dangereuses sur le système.
Décision
Nous allons donc utiliser les ADRs pour documenter tous les choix, toutes les décisions qui ont un impact sur l’architecture du système.
Format d’un ADR
En ce qui concerne le contenu, sachez qu’il n’y a pas de règle absolue sur le contenu d’un ADR. Je vais donc montrer un exemple de structure d’ADR, mais n’hésitez pas à enlever/rajouter/modifier des champs selon votre besoin.
- Date : La date à laquelle on écrit l’ADR
- Title : Le titre de l’ADR, au présent et à l’impératif, et de maximum 50 caractères, tout comme les bons messages de commit.
- Décideurs : Qui était impliqué dans la prise de décision
- Contexte : Qu’est-ce qui, dans l’architure actuelle, a fait que l’on a dû arriver à cette décision. Manquait-il quelque chose, avait-on des problèmes de performance, y’avait-il une limitation métier, etc. Bref, qu’est-ce qui a motivé notre décision.
- Décision : Ce qui a été décidé, c’est-à-dire le changement qui est proposé (ou qui va être mis en place quand on écrit l’ADR un peu tard 😇). En plus de la décision finale, cette partie peut également contenir les différentes solutions envisagées ? Quels étaient les points forts et les points faibles de chacune des solutions ? Pourquoi la solution que l’on a choisie est finalement la meilleure à l’instant t ? Cela permet à de nouveaux développeurs d’avoir l’ensemble du contexte de la décision.
- Statut : L’état de l’ADR : Proposé, Accepté, Rejeté, Déprécié, Remplacé
- Conséquences : Qu’est-ce qui va devenir plus simple, plus compliqué ou quelles sont les nouvelles choses que l’on va devoir gérer suite à cette décision.
Voilà, écrire un ADR revient donc simplement à remplir ces quelques champs !
Quelques recommendations
Pour vous aider sur la manière de stocker, formatter ou faire évoluer vos ADR, voici quelques recommendations supplémentaires :
- Versionnez vos ADR en les poussant dans un repository Git
- Numérotez vos ADR dans l’ordre
- Ecrivez vos ADR avec un langage simple type Markdown ou Asciidoc. Fuyez les outils complexes, vous avez simplement besoin de titres… et de texte.
- Discutez des ADR au statut Proposé. Vous pouvez par exemple utiliser le système de code review de Gitlab ou Github
- Limitez la longueur à une ou deux pages pour que l’ADR reste lisible. Si vraiment vous avez besoin de beaucoup plus de description… c’est peut-être l’heure de découper ? 🤔
Déprécier un ADR
Une fois qu’un ADR est Accepté (ou Rejeté), on n’y touche plus (voir note) ! En cas d’évolution du design décrit dans l’ADR, on créé simplement un nouvel ADR en indiquant qu’il remplace l’ADR précédent.
J’insiste sur ce point car c’est ce qui fait la force des ADR : même si la décision n’est plus valide, il reste important de savoir pourquoi cette décision avait été prise ! Voici un exemple comportant initialement 3 ADRs :
ADR-001
(Accepté)ADR-002
(Accepté) : DécisionA
ADR-003
(Accepté)
Mais un nouveau besoin métier fait que la décision A
prise dans l’ADR-002
est caduque. On va alors simplement créer un
nouvel ADR en indiquant qu’il remplace l’ADR-002
. On conserve ainsi tout l’historique, qui devient alors :
ADR-001
(Accepté)ADR-002
(Remplacé parADR-004
) : DécisionA
ADR-003
(Accepté)ADR-004
(Accepté, remplaceADR-002
) : DécisionB
ℹ️ J’ai un peu menti…
Si on ne doit effectivement pas toucher aux parties “décision” ou “contexte” d’un ADR accepté, il est en revanche utile de faire évoluer le statut d’un ADR remplacé pour indiquer que notre ADR est maintenant caduque et qu’il vaut mieux lire le nouveau. Dans l’exemple ci-dessus on voit en effet qu’on a rajouté au statut de l’ADR-002
la mention (Remplacé par ADR-004
).
Cela permet ensuite à un nouveau développeur qui lit un ADR de savoir en un coup d’oeil que l’ADR en question est déprécié, et qu’il devrait maintenant se référer à l’ADR qui le remplace.
Statut
Accepté.
Conséquences
Les ADR, à condition qu’ils soient remplis consciencieusement par toute l’équipe à chaque décision architecturale impactante, peuvent être un véritable atout pour documenter les décisions et le contexte du projet. A l’inverse d’une documentation centralisée dont on fait évoluer les mêmes pages au fur et à mesure des différents choix, les ADR permettent de garder un historique simple, facilement accessible et compréhensible de toutes les décisions structurantes d’un projet.
Pour reprendre le schéma initial, voici ce que donnerait un projet où l’on utilise les ADR :
Si le but premier des ADR est de garder un historique du contexte architectural tout au long du projet, ce n’est pas leur seul avantage et j’en vois au moins un énorme : il permet la prise de connaissance et l’échange autour de l’ensemble des choix de design. En effet s’il est utilisé de manière intelligente, par exemple commité sur un repository pour être soumis à une code review, il devient alors une véritable source d’échanges et de discussions.
Contrairement à une simple réunion où l’équipe se met d’accord sur les points principaux de design d’une fonctionnalité, ici un des membres de l’équipe prend le temps de décrire le design de manière plus détaillée, en exposant les idées, les contraintes, les problématiques. Il peut également faire des schémas, expliquer le contexte. Une fois le premier jet terminé, l’ADR est soumis aux autres membres de l’équipe qui vont alors le lire et le commenter, en discutant des points flous ou incorrects éventuels à la manière d’une code review, et ce jusqu’à ce que l’ADR prenne une tournure acceptable et atteigne donc le statut Accepté.
Ainsi toute l’équipe est au courant du changement qui va être fait, ce qui permet de ne pas être surpris plus tard en voyant le code.
Enfin, un dernier gros avantage : la solution retenue est celle qui a fait consensus au sein de l’équipe, elle a donc acquis une plus grande légitimité.
Ok, je suis convaincu. Quand est-ce que je commence ?
Maintenant.
Références :