Méthodes et pratiques
Les pratiques d'ingénierie
Une équipe peut tenir toutes ses réunions agiles et livrer malgré tout un logiciel fragile, que chaque modification menace de casser. Les livraisons fréquentes et les changements tardifs ne sont tenables que grâce à des pratiques techniques : écrire les tests d'abord, intégrer en continu, refactorer, programmer en binôme et automatiser la mise en service. Cet article les présente une à une, puis examine ce que la recherche en dit.
Pourquoi la technique compte
Le Manifeste demande d'accueillir les changements de besoins, même tard, et de livrer souvent. Ces deux exigences ont un coût : chaque modification d'un logiciel risque de casser quelque chose qui marchait, et chaque livraison oblige à tout revérifier. Si la vérification se fait à la main et prend deux semaines, livrer chaque mois est ruineux.
Les pratiques d'ingénierie agiles servent à faire baisser ce coût. Elles viennent pour la plupart d'Extreme Programming, et le neuvième principe du Manifeste en donne la raison :
Une attention continue à l'excellence technique et à une bonne conception renforce l’Agilité.
Manifeste agile, principe 9 (texte intégral)
Ward Cunningham, l'un des signataires, avait proposé dès 1992 une image pour décrire ce qui arrive quand cette attention manque. Un code écrit vite et jamais repris est une dette technique : il fait gagner du temps aujourd'hui et se paie ensuite en intérêts, sous la forme de modifications de plus en plus lentes.
Écrire le test d'abord
Un test automatisé est un petit programme qui en vérifie un autre : il lui fournit des données et compare le résultat obtenu au résultat attendu. Le développement piloté par les tests (test-driven development, ou TDD), que Kent Beck a décrit dans XP puis dans un livre de 2002, consiste à écrire ce test avant le code. Les praticiens résument le cycle par trois mots : rouge, vert, refactor. On écrit d'abord un test qui échoue, puisque le code n'existe pas encore. On écrit ensuite le code le plus simple qui le fasse réussir. On améliore enfin ce code sans changer ce qu'il fait, en vérifiant que le test réussit toujours.
L'exemple montre les deux effets attendus du test écrit d'abord. Il oblige à préciser ce que l'on veut avant de le construire, et il laisse derrière lui des tests qui signalent les régressions, c'est-à-dire les comportements qui marchaient et ne marchent plus.
Les enseignants connaissent une démarche voisine, que Grant Wiggins et Jay McTighe ont appelée « planification à rebours » dans Understanding by Design (1998) : on rédige d'abord l'évaluation finale, puis on construit les séances qui y conduisent.
Intégrer en continu
Quand plusieurs personnes modifient le même logiciel, chacune travaille sur sa propre copie, et l'intégration est le moment où l'on réunit ces copies. Plus on attend, plus les modifications se contredisent.
L'intégration continue, pratiquée dans XP dès les années 1990 et décrite par Martin Fowler dans un article de 2000 plusieurs fois révisé, rend l'opération banale à force de la répéter. Chaque développeur verse son travail dans la version commune au moins une fois par jour. À chaque versement, un serveur reconstruit le logiciel et rejoue tous les tests. Si un test échoue, la réparation passe avant tout le reste.
Refactorer et programmer à deux
Refactorer
Le refactoring consiste à modifier la structure interne d'un programme sans changer son comportement visible. Martin Fowler lui a consacré en 1999 un livre, Refactoring: Improving the Design of Existing Code, qui recense des dizaines de transformations élémentaires, comme renommer une variable mal nommée ou réunir deux morceaux de code presque identiques. Chaque transformation est petite, et l'on relance les tests après chacune. Le logiciel fonctionne donc à chaque étape, ce qui distingue le refactoring d'une réécriture.
Le refactoring est la contrepartie de la conception simple. Une équipe qui ne construit que ce dont elle a besoin aujourd'hui devra adapter sa conception demain, et elle ne le fera sans crainte que si des tests la protègent.
Programmer à deux
Dans la programmation en binôme, deux personnes travaillent sur le même poste. L'une écrit pendant que l'autre relit et pense à la suite, et les rôles s'échangent souvent. Ses partisans avancent une relecture immédiate et une connaissance du code mieux partagée, pour un coût apparent doublé.
De la livraison continue à DevOps
L'intégration continue garantit que le logiciel assemblé passe ses tests. Il reste à le mettre en service, opération longtemps manuelle et redoutée. Jez Humble et David Farley ont proposé en 2010, dans Continuous Delivery, de l'automatiser de bout en bout. Leur idée centrale est le pipeline de déploiement. Chaque modification traverse une suite d'étapes automatiques (assemblage, tests rapides, tests plus longs et installation dans un environnement d'essai), et celle qui les franchit toutes est prête à être mise en service. En livraison continue, la mise en service reste une décision humaine. On parle de déploiement continu quand cette dernière étape est elle aussi automatique.
Cette automatisation a rencontré un obstacle d'organisation. Dans beaucoup d'entreprises, les développeurs sont jugés sur les nouveautés qu'ils livrent et les équipes d'exploitation sur la stabilité des systèmes. En 2009, John Allspaw et Paul Hammond racontent dans une conférence comment le site Flickr déploie plus de dix fois par jour grâce à la coopération des deux métiers. La même année, Patrick Debois organise à Gand les premiers DevOpsDays, et le mot DevOps, contraction de development et d'operations, s'impose pour désigner ce rapprochement. On est loin des cycles de « quelques semaines à quelques mois » du troisième principe du Manifeste, mais dans le prolongement de sa « préférence pour les plus courts ».
En 2018, Nicole Forsgren, Jez Humble et Gene Kim publient Accelerate, qui s'appuie sur quatre années d'enquêtes et environ 23 000 réponses. Le livre retient quatre mesures de la performance de livraison : la fréquence des déploiements, le délai entre une modification et sa mise en service, la part des déploiements qui causent un incident et le temps de rétablissement après un incident. Sa thèse la plus commentée est que vitesse et stabilité vont ensemble : d'après ces enquêtes, les organisations qui déploient le plus souvent sont aussi celles qui subissent le moins d'incidents et qui s'en remettent le plus vite.
Ce que disent les études
Le TDD est l'une des pratiques les plus étudiées, et les résultats sont mitigés. Une étude de cas publiée en 2008 par Nachiappan Nagappan et ses collègues porte sur quatre équipes d'IBM et de Microsoft. La densité de défauts avant livraison y était inférieure de 40 à 90 % à celle de projets comparables menés sans TDD, pour un temps de développement initial accru de 15 à 35 % selon l'estimation des responsables. Il s'agit de comparaisons faites après coup, sans tirage au sort des équipes.
La méta-analyse de Yahya Rafique et Vojislav Mišić (2013), qui réunit 27 études, conclut à un petit effet positif sur la qualité et à un effet faible ou nul sur la productivité. Une expérience de Davide Fucci et de ses collègues (2017), conduite auprès de 39 professionnels, suggère que l'ordre compte peu. Les gains de qualité et de productivité y étaient associés au fait de travailler par petits pas réguliers, que le test soit écrit avant ou après le code.
Pour la programmation en binôme, la méta-analyse de Jo Hannay et de ses collègues (2009), sur dix-huit études, trouve un petit gain de qualité, un travail fini plus tôt et un effort total plus élevé. Les auteurs relèvent une forte variation d'une étude à l'autre et des signes de biais de publication. Ils concluent que le binôme n'est pas avantageux en toutes circonstances.
Les résultats d'Accelerate reposent sur des questionnaires remplis par des volontaires, qui évaluent eux-mêmes leurs pratiques et la performance de leur organisation. Ils établissent des corrélations et non des causes, et le programme de recherche, connu sous le nom de DORA, était porté par une société commerciale avant son rachat par Google fin 2018.
Beaucoup de ces études portent sur des étudiants ou sur des tâches de quelques heures, loin des conditions d'un projet de plusieurs années. Le résultat le plus constant est modeste : travailler par petits pas et obtenir un retour rapide semble utile, quelle que soit la pratique qui y conduit. L'article Que valent les preuves ? reprend cette discussion pour l'ensemble du corpus.
Limites et pièges
L'outil sans la pratique. Installer un serveur d'intégration ne suffit pas. Une équipe dont chaque membre travaille deux semaines sur sa propre copie du code avant de la fusionner possède l'outil et n'intègre pas en continu.
Des tests qui ne vérifient rien. Quand une direction fixe un taux de couverture du code par les tests, on voit apparaître des tests écrits pour faire monter le chiffre, qui exécutent le code sans rien contrôler. C'est une illustration de la loi de Goodhart.
La pratique érigée en dogme. En 2014, David Heinemeier Hansson, créateur de Ruby on Rails, a publié un billet intitulé « TDD is dead. Long live testing. », où il reprochait au TDD appliqué avec rigidité de déformer la conception des programmes. Kent Beck et Martin Fowler en ont débattu avec lui dans une série de conversations publiques. Aucun des trois ne contestait l'utilité des tests automatisés : le désaccord portait sur l'obligation de les écrire toujours en premier.
DevOps réduit à un intitulé de poste. Créer une « équipe DevOps » entre les développeurs et l'exploitation ajoute un troisième groupe au lieu de rapprocher les deux premiers.
Le poids de l'existant. Ces pratiques sont faciles à adopter sur un logiciel neuf. Sur un système de vingt ans dépourvu de tests, poser le filet de sécurité demande des mois de travail.
Pour aller plus loin
- L'excellence technique et la simplicité : les principes 9 et 10 et la dette technique.
- Extreme Programming : la méthode d'où viennent la plupart de ces pratiques.
- Accueillir le changement : ce qui rend le changement tardif acceptable.
- Livrer tôt et souvent de la valeur : les principes 1, 3 et 7 du Manifeste.
- Que valent les preuves ? : Accelerate, les enquêtes déclaratives et ce que l'on peut en conclure.
Sources principales : Manifeste pour le développement agile de logiciels (2001), agilemanifesto.org ; Kent Beck, Test-Driven Development: By Example (2002) ; Martin Fowler, « Continuous Integration » (2000, révisé en 2006 et 2024), martinfowler.com ; Martin Fowler, Refactoring: Improving the Design of Existing Code (1999 ; 2e édition 2018) ; Ward Cunningham, « The WyCash Portfolio Management System », OOPSLA (1992) ; Jez Humble et David Farley, Continuous Delivery (Addison-Wesley, 2010) ; Nicole Forsgren, Jez Humble et Gene Kim, Accelerate: The Science of Lean Software and DevOps (2018) ; Nachiappan Nagappan et al., « Realizing quality improvement through test driven development », Empirical Software Engineering (2008) ; Yahya Rafique et Vojislav B. Mišić, « The Effects of Test-Driven Development on External Quality and Productivity: A Meta-Analysis », IEEE Transactions on Software Engineering (2013) ; Davide Fucci et al., « A Dissection of the Test-Driven Development Process », IEEE Transactions on Software Engineering (2017) ; Jo E. Hannay et al., « The effectiveness of pair programming: A meta-analysis », Information and Software Technology (2009) ; Grant Wiggins et Jay McTighe, Understanding by Design (1998).