Réponse à « Test-Driven Development: un pacte diabolique »

On a attiré mon attention il y a quelque temps sur un article présentant les tests comme un “pacte diabolique”. Ce texte, accessible ici a été publié par le théoriquement très sérieux “Comité Français des Tests Logiciels”.

Imbécile un jour, imbécile toujours ?

Après le pathétique papier publié par Anne Aussem dans le Journal du Net, voici un nouvel exemple d’article diffusant de fausses vérités. Mauvaise foi ou manque d’information ? Je constate simplement qu’avec la rapide diffusion de l’approche agile ce genre d’article de désinformation se multiplie. C’est clairement un phénomène récent, on n’en voyait pas trace il y a quelques années. S’agit-il en d’une stratégie de défense de la part des promoteurs des approches classiques ?

De toute manière, seules deux raisons peuvent amener à commettre un tel texte: (1) la stupidité ou (2) la désinformation volontaire. Je vais partir du principe que l’auteur est honnête, ce qui me dirige vers l’hypothèse (1). Qualifier cela de stupidité peut sembler fort, mais pour moi pour attaquer un sujet, il faut commencer par être bien informé (je vais bientôt revenir là-dessus). Ce n’est clairement pas le cas ici. Avant de développer, je livre aussi deux petites réflexions:

  • Avec l’article d’Anne Aussem, je pensais que notre cher pays était déjà bien équipé en imbéciles (une idée en fait antérieure à l’article en question). Drôle d’idée d’avoir en plus besoin d’un produit d’importation…
  • L’auteur fait valoir son doctorat et sa chaire de professeur. Cela confirme une conclusion à laquelle j’étais arrivé depuis longtemps: le diplôme n’est pas synonyme d’autorité et de qualité. C’est aussi une conclusion rassurante. Par ailleurs faire valoir sa notoriété voir son autorité dans la signature d’un article hausse le niveau d’exigence que l’on peut avoir par rapport au texte. Ce texte n’est pas digne d’une chaire de professeur. Il n’est pas digne de grand chose, en fait. Voyons cela.

TDD, un processus ?

Ma première remarque concerne l’appellation “processus TDD” employé par l’auteur. TDD n’est pas un processus, mais une pratique. Une technique faite pour améliorer certains aspects du développement logiciel, à savoir s’assurer que le code écrit fonctionne bien suivant l’intention de l’auteur. C’est une technique qui vient en compléter d’autres venant du monde agile, comme les “acceptante tests”, le pair programming, etc… et pourquoi pas d’autres issues de l’ingénierie classique. On parle bien de pratique, donc de quelque chose qui est mis en oeuvre conjointement avec d’autres choses. TDD n’impose rien d’autre. Et même si TDD est souvent associé avec d’autres pratiques comme les “user stories” et le “refactoring”, le fait qu’il y ait des facteurs convergents (surtout avec le refactoring) n’en font pas des éléments obligatoires de la mise en oeuvre de TDD !

Ainsi non seulement cette première section diffuse une contre-vérité, mais la figure (1) est également fausse: on écrit pas un ensemble de cas de tests avant de coder la tâche, mais on écrit UN cas de test, puis du code, puis du refactoring si nécessaire, puis UN nouveau cas de test, etc. (cf “Test-Driven Development” par Kent Beck).

Viennent ensuite les fameux 12 points.

La montée en échelle de TDD

Comme je l’ai dit, TDD est une pratique en elle-même. Si pour un projet de grande taille ou critique, l’approche User Stories ne semble pas la bonne (bien que contrairement à l’affirmation de l’auteur, les user stories puissent être gérées de manière hiérarchiques cf “Scaling Lean & Agile Development” par Larman & Vodde), utilisez-en une autre mieux adaptée à votre contexte. Cela n’empêche pas de faire du TDD ! Non, car TDD est fait pour tester le code que l’on écrit.

Les pratiques et outils à utiliser sur un projet doivent être adaptées au contexte du projet. En fait de nombreux outils existent dans la boite à outil agile (epics, story map, release plan, design session, 5 niveaux de planification, requirements area), mais on peut aussi aller les chercher hors de l’univers agile. Et on peut toujours pratiquer TDD dans tous les cas ! L’approche agile nous apprend surtout à nous adapter et à utiliser ou ne pas utiliser certains outils en fonction du contexte. Bref, elle nous apprend à travailler avec notre intelligence, un concept visiblement étranger à l’auteur. Exit le point numéro 1.

Une (avant) dernière chose, pour ce qui est des applications critiques: TDD est la seule pratique, à ma connaissance, qui garantit que du test pertinant correspondant à du code. En effet avec TDD vous n’avez pas le droit d’écrire du code si le test correspondant n’existe pas préalablement. A ce titre, TDD devrait être une pratique obligatoire lors du développement des systèmes dits critiques, n’est-ce pas ?

Enfin, bien sûr, Mr Jorgensen a raison quand il dit qu’il y a une limite à ce qu’un développeur peut garder à l’esprit à un moment donné. C’est un des points que TDD traite avec succès: quand on développe quelque chose, on se focalise dessus avec le test accompagnant la chose. Une fois terminé, je peux l’oublier ! Si par malheur ce que je fais ensuite impact une réalisation précédente, mes tests vont me le rappeler en échouant. Je n’ai pas besoin de garder à l’esprit les dépendances entre objets ou fonction, mes tests unitaires font cela à ma place. Au contraire de l’affirmation de l’auteur, sans TDD je serais obligé de tout garder à l’esprit !

Comment TDD traite-t-il de la complexité applicative ?

Ah ! Je vais devoir rappeler que TDD n’est pas un processus, n’est-ce pas ? Il y a en fait plusieurs points à adresser ici.

Le premier points concerne la façon dont TDD adresse effectivement la complexité applicative: elle ne l’adresse pas. Ce n’est pas son rôle. Mais il y a de nombreux éléments de projet qui n’adressent pas la complexité applicative. Le document de Vision (ou elevator statement, quel que soit le nom que vous lui donnez), il n’adresse pas la complexité applicative, est-il mauvais pour autant ? Mais je vais revenir sur ce point en parlant d’une autre pratique: le refactoring.

Le second point concerne la matrice d’incidence dont l’auteur semble friand. Je connais un peu ce genre de technique, avec UML nous appelions cela des “use case realizations”. J’avoue que d’un point de vue intellectuel et académique, ce genre de référentiel croisé est très attrayant. C’est sans doute pour cela que je me suis efforcé de mettre cela en oeuvre, il y a une douzaine d’année. Finalement sans grand succès, hélas. Ce genre d’approche souffre de deux ou trois faiblesses:

1 – Avoir une matrice juste et à jour est un vrai challenge. On est toujours en retard sur le développement, pour autant que l’on soit juste ! Il faut sans relâche traquer l’évolution du développement pour être à jour.

2 – Difficulté d’automatiser cette matrice. Ce point fait suite au précédent. Mais à mon avis le seul moyen d’être à jour est de faire en sorte que ce genre de matrice s’entretienne automatiquement à partir du code. Hélas en l’absence de lien formalisé entre le code et les cas d’utilisation, ce n’est guère possible. Ce genre de lien se matérialiserait très bien à l’aide de tests d’acceptante automatisés (ATDD), mais visiblement le TDD, c’est l’antre du mal, donc oublions…

3 – Ca ne sert à rien. Certes les matrice éparses permettent de constater un design “diffus”. mais c’est juste une constations, qui intervient après coup. Idéalement il faudrait alors corriger le tir … en refactorant. Oui mais, en l’absence d’un harnais de sécurité mis en place grâce aux tests, c’est bien trop dangereux !

En fait, la boite à outil agile offre d’autres outils pour traiter cette fameuse complexité applicative. Ce sont juste des outils complémentaires de TDD ! Et finalement, si vous aimez les matrices d’incidence et pensez qu’elles peuvent apporter à votre projet: faites-les ! Il n’y a aucune contre-indication avec TDD !

Comment TDD traite-il la compréhension du système ?

Un petit éclaircissement d’abord: l’auteur amène ici les termes “projet TDD” et même “projet purement TDD”. Une telle chose n’existe pas. TDD est une pratique, parler de “projet TDD” est vide de sens.

TDD n’a pas pour objet de documenter un système de manière globale. Il a le double objectif de tester le code lui-même et de le documenter par l’exemple.

Contrairement à une croyance largement répandue, les projets agiles ne sont pas réfractaires à la documentation (cf “agile modeling” de Scott Ambler, ou “agile documentation” d’Andreas Rüping). Mais ils mettent l’accent sur la documentation “juste à temps” dont l’écriture vient d’un besoin de transmettre un niveau de compréhension du système ou d’éclairer un aspect particulier du système. Il est vrai que l’on ne réalise pas un type de document simplement parce que cela est demandé par la méthode. Au final, ce type de documentation (comme les documentations “générées”) finissent par être des documents en “write only”.

L’approche agile nest pas non plus hostile aux commentaires dans le code, à certaines réserves près:

  • Un commentaire ne doit pas être une excuse à du code mal écrit et difficile à lire par lui-même. Il faut toujours privilégié le code clair. Si celui-ci se lit naturellement, alors cela diminue ou élimine la nécessité d’écrire un commentaire à ce sujet. A ce titre, on peut souvent considérer la nécessité d’écrire un commentaire comme un aveu d’échec à l’écriture d’un code clair !
  • Le commentaire ne doit pas paraphraser le code ! Il doit apporter une information et un éclairage particulier.

Le commentaire amène avec lui un danger réel: celui de ne pas être à jour par rapport au code auquel il s’adosse ! En fait, en plus de 30 ans, je n’ai jamais vu, même sur les projets les plus disciplinés, un commentaire qui n’était pas, à un moment donné et/ou à un endroit particulier, divergent ou en retard par rapport au code. C’est un danger pour le mainteneur car il sera induit en erreur.

Un nommage et un design clair, de bons tests unitaires sont une forme de documentation qu’il faut privilégier. Ils ne mentent jamais et ne sont jamais en retard par rapport au code. jamais. Les développeur aguerris à la technique des tests unitaires prennent l’habitude de s’appuyer sur ceux-cis pour comprendre le code qu’ils abordent. 

Il y a-il une quelconque garantie que les cas de tests développés dans le processus TDD constituent réellement un bon test ?

Là encore, ce point en couvre plusieurs.

1 – Quelle garantie a-t-on qu’un test est vraiment un bon test ?

En fait, cette question est une bonne question ! Une réellement bonne question ! mais vous aurez  peut-être remarqué que j’ai volontairement omis la partie “TDD” dans ma reformulation ? En effet cette question se pose autant aux tests TDD qu’aux autres ! Répondons à ce premier volet complètement éludé par l’auteur

a) La pratique du “pair programming”.

Contrairement à l’idée parfois admise qu’une personne super-compétente sera quasi infaillible, la communauté agile a développé ses pratiques sur l’idée que nous sommes tous faillibles, mais que ces failles se trouvent compensées ou évitées en travaillant ensemble (cf “Pair Programming Illuminated” par Williams & Kessler). L’une des pratiques mises en oeuvre est le travaille en binôme. La revue de pair est considérée comme l’une des méthodes de vérifications les plus efficaces (cf “Peer Reviews in Software, a pratical guide” par Karl Wiegers). Pour donner à cette technique le maximum d’efficacité, le pair programming propose de faire de cette activité une pratique systématique et continue, qui s’applique à l’écriture de code et de tests ! Ce n’est pas une garantie, mais cela s’en rapproche

b) Des “workshop” de cas de tests.

Il ne s’agit pas en soi d’une pratique agile largement documentée, mais d’un exemple de mise en oeuvre que l’on peut imaginer mettre en oeuvre sur un projet agile. C’est une chose que j’ai fait en pratique. L’idée est la suivante: sur la base de besoins exprimés on réunit un petit commando regroupant différentes facettes du projet: développer, équipe de validation, utilisateur, analyste, etc… Ce petit groupe produit, par le biais de discussions et contradictions un semble de cas de tests passants et non-passants. la présence de points de vue différents permet de combler les lacunes inhérentes à une vision partielle du projet !

c) Des testeurs dans l’équipe de développement.

Les équipes agiles font grand cas de la polyvalence des membres qui composent l’équipe. Cela ne signifie pas que l’on ne puisse avoir recours à des experts. Le test du code via TDD ne constitue qu’une partie des tests que l’on va appliquer au logiciel développé. L’une des mantra des approches agiles est d’avoir du feedback le plus tôt possible. Le test est une forme de feedback, on s’évertuera à avoir ce feedback au plus tôt en incorporant les testeurs à l’équipe de développement (cf “Agile Testing” par L. Crispin & J. Gregory) qui travailleront en étroite collaboration pour développer et outiller les tests nécessaires.

2 – Qu’en est-il des différents niveaux de tests ?

TDD, comme son nom l’indique se focalise sur le test du code, donc le test “boite blanche”. Cela ne signifie pas que l’on effectue pas d’autres types de tests sur les projets agiles. Non seulement ils sont fait, mais d’une manière générale mieux faits que sur des projets classiques. Pour développer ce point, il me faudrait évoquer une autre pratique (la 4ème de ce papier, je pense): l’intégration continue. En intégration continue, le logiciel est construit de manière continuelle, à chaque “commit” dans le gestionnaire de source, et les tests automatiques (que ce soient des tests unitaires ou non) sont exécutés à la suite. Fini d’attendre de long cycles d’intégration pour savoir ce qui va mal ! A chaque changement, on obtient un feedback presque immédiat !

Revenons un moment sur les différents types de tests. Hélas, je ne suis pas un spécialiste de la taxonomie des tests, mais je vais essayer.

  • Les tests unitaires: il s’agit du focus principal du TDD. L’unité de test est la méthode. C’est le focus principel de l’approche TDD. La mise en place de ces tests s’appuie traditionnellement sur des frameworks de test de la famille xUnit (cf “xUnit Test Patterns” de Meszaros).
  • Les tests de composants: C’est un type de tests assez proche du précédent, on emploie d’ailleurs souvent les mêmes outils. C’est aussi un test de type “boite blanche”, pas très facile à décrire à mon avis, car la notion de “composant” est elle-même difficile à établir à l’aide d’une définition fermée ! De manière générale, on peut dire que ces tests s’appliquent à des groupes de classes, donc à des scénarios mettant en oeuvre l’interaction entre ces différentes classes. On peut parfois réaliser ces tests en TDD, mais dans la pratique cela s’avère plus difficile à faire que pour les tests unitaires. Beaucoup de développeurs écrivent ces tests juste après avoir écrit le code.
  • Les tests d’intégration: On peut voir d’une part ces tests comme des tests de composant à plus grande échelle, traversant toute l’architecture du système, mais souvent ces tests intègrent l’interaction avec les systèmes externes (base de données annuaires, etc…). Les agilistes essaient souvent de mener leurs tests le plus loin possible sans y intégrer de système externe, en “mockant” ces systèmes externes, puis de réaliser des tests plus ciblés adressant uniquement les couches d’interfaçage avec le système externe ! Quoi qu’il en soit, ces interactions avec les systèmes externes doivent être adressées. Je n’ai personnellement jamais vu ces tests d’intégration réalisés en TDD, mais en principe rien ne l’interdit ! Au niveau de l’outillage, on voit soit des solutions spécifiques, soit des adaptations à base de xUnit. Certains systèmes viennent aussi parfois accompagnés de librairies ou d’outils facilitant ces tests d’intégration, c’est le cas de certaines solutions open-source.
  • Les tests de performance: Il n’y a guère de différence de mise en oeuvre de tests de performance entre un projet agile et un projet non-agile. Dans un projet agile, on essaiera simplement de mettre en place ces tests au plus tôt, puis d’intégrer ceux-ci à la plateforme d’intégration continue. Les tests de charge, de par leur nature sont eux, hélas, difficile à concilier avec une logique d’intégration continue. Que ce soit pour les tests de charge ou pour les tests de performance, on est plutôt dans une logique de “test after”. Peut-être il y a-t-il là matière à progrès ? Les outils destinés à ce type de tests sont spécifiques à ces problématiques, souvent hélas un peu lourd de mise en oeuvre.
  • Les tests d’acceptance: Il s’agit de tests fonctionnels, donc de type “boite noire”. Au niveau de l’approche outillée, il y a deux courants de pensée:
    • Une approche de tests par l’IHM, comme cela est fait avec des outils tels que Selenium. La difficulté étant alors la combinaison de problématiques de comportements dynamiques d’interface avec le comportement purement fonctionnel. L’avantage est que ces tests garantissent effectivement ce qui est perçu par l’utilisateur.
    • Une approche s’abstrayant de l’IHM, testant le comportement fonctionnel au niveau de la couche sous-jacente à la couche présentation. L’avantage est une meilleure stabilité comportementale, car le comportement dynamique de l’IHM est exclu. S’il permet de se focaliser sur l’aspect métier, il ne s’agit pas ici d’un test applicatif. L’émergence de technologies telles que HTML 5 et de librairies Javascript lourdes comme JQuery mettent aussi à mal cette approche par ailleurs attrayante.

          L’une des pratiques agiles qui fait l’objet de plus en plus d’attention est l’ATDD, ou Acceptance Tests Driven Development. Il s’agit d’une pratique complémentaire au TDD, focalisé ur l’aspect fonctionnel. Dans cette approche, on perçoit les cas de tests comme une information complémentaire au recueil des besoins, lui donnant à la fois une concrétisation (une expression de besoin est par nature abstraite) et des précisions pour traiter des cas particuliers ou ambigües. L’expression des besoins est donc alors le recueil des besoins initial (les User stories ou autre chose) plus les cas de tests d’acceptante. Dans l’approche ATDD, les cas de tests sont écrits en grande partie et implémentés avant que le travail de développement commence, à l’image de ce que l’on fait pour le TDD. Ces cas de tests ne sont pas écrits par le développeur mais par toutes les parties prenantes à l’expression du besoin (le développeur peut y participer). La mesure du suivi de l’accomplissement de l’itération devient alors le suivi du passage au vert des cas de tests, permettant un suivi du projet hors pair !

  • Les tests exploratoires: Ce sont les seuls tests qui ne peuvent être automatisés, ils sont laissés au jugement humain. La découverte de cas de figure non couverts par des tests d’acceptante peut participer à la consolidation de la couverture de tests.

L’approche agile ne limite pas les tests au test du code. En fait, tout ce qui a été identifié comme nécessitant des tests doit l’aide en utilisant la technique adéquat. Que dit l’approche agile à ce sujet ? Si quelque chose a été identifié comme nécessaire, alors faites-le ! Sinon ne le faites pas (donc ne faites pas quelque chose par simple dogmatisme). Simplement, faites-le le plus tôt possible et le plus souvent possible ! C’est une question de bon sens.

Comment TDD traite-til des exigences non-fonctionnelles, telles que la performance, la fiabilité, la sécurité, la capacité de débit ou la bande passante et la maintenabilité ?

Sur ce point, l’auteur de l’article est à la fois dans l’erreur mais répond lui-même à une partie de ces questions.

1 – Performance, fiabilité et sécurité

Pour ce qui est des autres types de tests, encore une fois s’ils ont besoin d’être fait, alors il faut les faire. Je me répète mais il n’y a aucune incompatibilité ni contre-indication entre TDD et des tests de performance ou de sécurité ! Bien au contraire, ils sont complémentaires !

2 – A propos de l’analyse

Mais qu’en est-il de traiter avec succès ces points avec “une analyse rigoureuse” ? Je répondrais en deux points:

  • Qui a prétendu que l’on ne faisait pas d’analyse sur les projets agiles ? Encore une fois j’y vois une ignorance complète de ce qu’est un projet agile de la part de l’auteur !
  • Cette fameuse “analyse rigoureuse” est-elle une garantie de succès ? Ayant audit des projets, j’ai eu mon compte de modélisations malheureuses et d’analyses erronées. 

En filigrane, j’y vois une faiblesse majeure des approches classiques: substituer une description prescriptive des processus à la compétence ! Cela conduit ces équipe à construire des équipes en “optimisant les coûts” donc avec des personnes moins chères mais moins expérimentés et/ou peu brillantes en pensant que les lourds classeurs descriptifs des méthodes vont compenser cela. C’est faux ! Il n’y a pas de substitut à la compétence !

3 – Et enfin, au sujet de la maintenabilité

Le dernier point concerne la maintenabilité. Le problème majeur qui se pose lors de la manigance logicielle est: qu’est-ce que je risque de casser en modifiant le code existant ?

Sur un projet classique, on commence par lire la documentation. Puis on lit le code (souvent peu clair, car il y a peu de contraintes sur la lisibilité du code), de toute façon en fait, on ne fait pas confiance à la documentation ! Finalement, on opte souvent par l’écriture de “rustine” interagissant à minima avec le code existant, conduisant le plus souvent à de la duplication de code et de fonctionnalité. Celle-ci amplifie encore le problème de maintenance car les prochains correctifs devront agir au niveau de toutes les portions de code dupliqués !

Sur un projet mettant en oeuvre TDD, on commence aussi par lire la documentation existante (car il y en a souvent, même si elle est plus synthétique). Puis on exécute les cas de test pour comprendre le comportement du code existant. On ajoute de nouveaux cas de tests correspondant aux évolutions ou corrections à implémenter et on s’assure avant tout que ces tests ne passent pas. On effectue les évolutions / corrections dans le code existant en s’assurant que les codes préexistant ne cassent pas. On vérifie aussi qu’il n’y a pas de duplication de code et que le design est “clean” en terminant chaque cycle d’implémentation par du refactoring. On n’a aucune crainte à le faire, car contrairement à un projet sans tests unitaires, on a les garanties qu’il n’y aura pas de régression ! On s’assure régulièrement, à chaque “commit” de code que les tests d’intégration et d’acceptante passent tous, y compris les nouveaux tests d’acceptante. On s’assure que tout est au vert sur la plateforme d’intégration continue.

TDD n’est peut-être pas l’arme absolue en ce qui concerne la maintenabilité, mais c’est sans aucun doute possible ce qui s’en rapproche le plus ! Aucun autre outil ne peut nous donner de meilleurs assurances à ce sujet. L’auteur propose comme outil de l’analyse et de la modélisation rigoureuse, mais en quoi peut-on être sur que ces documents sont à jour avec le code ? Est-on certain que les évolutions ont été faites sur les deux fronts ? Y compris lors des correctifs d’urgence (ce n’est pratiquement jamais le cas) ? Et finalement en quoi ces outils aident-ils le développeur à s’assurer de la non-agression ?

En fait, c’est bel et bien l’approche classique qui ne sait pas répondre aux problématiques de la maintenabilité. En tout cas l’auteur de l’article n’y répond pas !

L’approche non-agile ne donne aucun outil réellement opérationnel par rapport à la problématique de la maintenabilité. Pire, elle occulte cette lacune avec une illusion simplement à même de tromper un management qui finira, si cette maintenance devient problématique ou trop coûteuse, par blâmer le développeur !

Vu que les cas de tests au niveau des tâches dirigent le processus TDD, que se passe-t-il si ces tests sont inadéquats, par exemple incomplets, insuffisants ou incorrects ?

C’est une question assez générale: que se passe-t-il si les tests sont inadéquats, etc… Pas seulement en TDD, mais en général ! Quelle réponse apporte les processus classiques ? Visiblement on parle de vérification croisée !

Sur ce point, TDD est utilement complété du pair programming. Si votre développement est réalisé en pair programming, vous avez l’assurance que tous les tests sont toujours revus par une autre personne, tout le temps, au moment où ils sont écrits ! Est-ce parfait ? Non ! Mais au moins a-t-on l’assurance que tous les tests sont revus contrairement aux processus de revue croisé à postériori qui ne sait garantir (à moins de coûts exorbitants) que tous est toujours revu !

ATDD complète aussi utilement cet arsenal grâce à des tests s’appuyant et complétant les spécifications. La garantie que ces tests sont “parfaits” n’existe pas. On réduit simplement le risque en faisant participer à leur écriture toutes les personnes qui peuvent être concernées. Fini l’approche taylorisme du testeur écrivant ses tests dans un coin en s’appuyant sur une lourde spécification envoyée par mails, le cahier de test étant ensuite lui-même envoyé par mail aux personnes en charge de l’exécuter ! L’approche agile croit en la collaboration et la communication.

L’affirmation d’effet tunnel est aberrante: au contraire, les projets agiles donne une visibilité idéale sur le projet: on connait à tout instant le nombre de tests unitaire qui passent, les tests d’acceptante qui sont OK, la plateforme d’intégration donne un statut sur la qualité d’intégration et souvent d’autres métriques qualité. Les projets Scrum donne aussi une visibilité en continu sur les tâches en cours et réalisées via un “kanban” des tâches. On parle ici de visibilité à l’heure, voir à la minute. Sur aucun des 4 volets que j’ai cité, les processus classiques ne peuvent prétendre donner le même niveau de visibilité et de feedback. Il y a bien un problème d’effet tunnel, mais il est du côté des processus classiques.

Les défauts qui ne peuvent être détectés que par le test de flux de données…

J’avoue ma méconnaissance de cette technique. C’est une des nombreuses choses que la communauté des tests peut enseigner à la communauté agile !

Je n’ai qu’une chose à dire: si ce type de test est utile, alors faites-les ! Il n’y a aucune incompatibilité avec la pratique de TDD.

Quel est le processus de TDD qui garanti que les composants créés et testés isolément avec succès seront sujet à une forme de test d’intégration ?

Tester l’intégration est l’affaire des tests d’intégration ! TDD est une pratique de développement, donc les tests d’intégration ont toujours lieu, comme je l’ai dit précédemment.

En ce qui concerne l’intégration, les projets agiles s’appuient sur des plateformes d’intégration continu qui jouent tôt et souvent les tests d’intégration. Ce qui dans des projets classiques correspond à une phase d’intégration pouvant durer plusieurs mois est ici littéralement réduit à zéro !

Comment la documentation délibérément parcellaire, supporte-t-elle le besoin éventuel de maintenance du programme ?

J’ai répondu à ce point précédemment. Le problème majeur de la maintenance est la non-regression. La documentation n’aide en aucune manière sur ce point.

Maintenant, il est utile d’avoir une compréhension de haut niveau, pour comprendre l’organisation des modules, le style architectural, le cinématique des services. Documenter cela de manière compréhensible et synthétique est souvent utile. Et dans ce cas, il faut le faire, tout simplement ! Certaines équipes emploient même à plein temps un “technical writer”.

Mais pour ce qui est de garantir la non-regression, la documentation n’est d’aucune aide. Les tests unitaires développés et maintenus tout au long de la vie du programme avec TDD sont le meilleur outil que je connaisse, de très loin.

La maintenabilité des projets développés avec TDD sont incomparablement plus maintenables que les projets non-agiles. En fait, ils sont simplement maintenables, alors que les projets sans tests unitaires ne le sont pas.

Comment la refactorisation répétée produit-elle une conception élégante ?

L’auteur parle de controverse. Je partage ce point de vue mais de mais de manière inverse: Je reste dubitatif sur cette affirmation que la conception émergente ne produit pas des architectures élégantes. A l’appui des dires de Mr Jorgensen, il y a une étude qu’il a mené dans son université. Mais on ne sait rien de cette étude (et l’on sait qu’on leur fait dire ce que l’on veut, aux études): sur quelles critères ? Avec qui ? Sur quelle base ? Répondre au “comment” que nous soumet l’auteur est difficile. Mais je peux soumettre des éléments de réponse !

  • Un très grand nombre de projets open-source, notamment dans la fondation Apache sont le fruit d’une conception émergente, je pense que c’est une base sur laquelle s’appuyer pour parler d’élégance.
  • La qualité d’une conception ou d’une architecture est essentiellement subordonnée au savoir-faire du développeur. Le raffinement d’une architecture par le biais de refactoring demande effectivement un savoir-faire à part entière. Au final, c’est le talent et le savoir-faire qui sont la garant d’une bonne conception.
  • Les architectures fruit d’une conception initiale “à priori” souffrent d’un manque de recul sur le sujet:
    • Des couches dont on a décidé à priori qu’elles seraient utiles s’avèrent surnuméraires et génèrent des lourdeur et de la dette technique.
    • Certains modules ou concepts n’ont pu être identifiés au départ, encore une fois par manque de recul. Les fonctionnalités correspondantes finissent sous forme de code utilitaire “rustiné” ailleurs ou pire encore sous forme de traitements dupliqué !
    • On fait fi d’une réalité du développement informatique: il s’agit d’une activité de découverte et d’apprentissage. Les idées naissent et murissent en travaillant sur le sujet. Il ne faut pas hésiter à remettre en cause des idées premières à la lumière de ce que l’on a appris.
  • En commençant petit, avec le niveau et la complexité de conception correspondant à ce que l’on fait sur le moment, on s’assure de ne pas faire de “sur-conception”, on ne fait pas d’hypothèse sur des évolutions futures dont on ne sait pas si elles auront lieu et enfin on écrit uniquement du code qui sert, que l’on peut tester, et non pas un dette technique et peut-être même une bombe à retardement.

Ayant répondu à ce point, j’attire maintenant l’attention sur le fait que TDD et refactoring s’ils sont complémentaires et se marient bien ensemble, sont deux pratiques différentes ! TDD n’a pas pour but de traiter la qualité de la conception.

Par contre, une constatation que j’ai pu faire au début des années 2000, c’est que le noyau dur de la communauté agile s’est construit à partir de la communauté “design patterns” donc des personnes particulièrement affutées en conception et qui ont voulu mettre en place des méthode de travail permettant l’émergence de conceptions de qualité !

Comment une “vision tunnel” générée par TDD peut-elle amener une conception qui traite efficacement de la performance

Ce point nest pas un nouveau point, car l’auteur a déjà évoqué ces points en (4) et en (5). La réponse reste la même: TDD est une pratique de développement, elle ne prétend pas couvrir les tests de performance, ni résoudre la crise économique ou établir la paix dans le monde. les projets agiles font des tests de performance dans la mesure où ces critères ont été identifiés. Et dans ce cas, ces tests sont intégrés à la plateforme d’intégration. On peut alors suivre heure par heure l’impact des évolutions ou des refactoring sur ces performances. Les projets classiques peuvent-ils prétendre la même chose ?

Je ne vais pas m’étendre sur l’accusation d’effet tunnel qui met simplement en lumière la complète ignorance du sujet auquel s’attaque Mr Jorgensen.

Comment détecter des inconsistances, même légères entre les tâches d’une user story ou entre les user stories elle-même ?

Qu’est-ce qu’un découpage en tâche dans un développement agile ? C’est simplement une façon d’organiser le travail afin de le répartir et de voir le développement progresser. Bien sûr, lorsque l’on découpe en tâches on s’évertue à donner une définition du “done” de la tâche. mais au final, quand les tâches constituant une user story sont terminées, ce sont les tests d’acceptance qui font foi du bouclage de la user story. Possédant cette indication, quelle valeur il y a-t-il à relier des incohérences “même légères” entre les tâches ? Si cela ne va pas, les tests d’acceptance sauront nous le dire, car il ne passeront pas. Si ils passent ces que ces incohérences sont sans importance, ou alors peut-être du point de vue académique … mais sur les projets agiles, on refuse de passer du temps sur des choses qui ne servent à rien.

Les incohérences entree user stories sony des choses qui peuvent arriver. Je vois deux moyens de contrer ce problème

  • Sur les user stories, la communauté agile a développé deux techniques: les “epics” et le “story zapping” afin de regrouper et analyser de manière transversales les user stories.
  • La seconde technique n’a rien de novatrice mais elle marche toujours très bien: le peer-review.

L’utilisation des “user story” est indépendante de TDD. Même si cette technique est très répandue dans la communauté agile, elle n’est pas “obligatoire”. Et si elle est utilisée, elle peut être complétée par nombre de formalismes ou techniques qui peuvent s’avérer pertinentes sur le projet. 

L’heure du bilan ?

Le premier point que que l’on retiendra est la méconnaissance totale du sujet par Mr Jorgensen. Il présente TDD comme un processus alors qu’il s’agit d’une pratique. Une erreur qu’il n’aurait pas faite s’il avait lu quelque ouvrage sur le sujet ! On comprend maintenant pourquoi il n’y a aucune référence bibliographique à l’appui de ses observations.

Ma réponse est beaucoup plus longue que l’article d’origine. J’ai voulu étayer chaque point d’explications et non asséner des affirmations. Pourtant j’aurais aimé développer encore plus !

Cette approche éronée explique pourquoi certains points ne sont pas “traités par TDD”. Dans un projet agile on utilise un ensemble de technique pour couvrir ces différents aspects, comme une plateforme d’intégration pour vérifier en permanence la qualité d’intégration. On voit alors que les points en questions sont adressés de manière pertinente et efficace.

Pour ce qui est des points sur lesquels TDD présente une plus-value, on a vu que, contrairement aux affirmations de Mr Jorgensen, TDD donne une réponse de très bonne qualité, bien supérieure aux approches classiques. Est-ce un manque d’information, une erreur de jugement ou une volonté délibérée de tromper qui ont conduit Mr Jorgensen à ces conclusions ?

Les dangers de juger sans savoir

Vous aurez surement noté que j’ai appelé l’auteur “Mr Jorgensen” et non “Professeur Jorgensen”. A la lumière de cette oeuvre édifiante, il ne mérite pas ce titre. Il y a de réels dommages qui naissent de la diffusion de la désinformation et de la diffusion de contre-vérités auprès d’un public non encore au fait du sujet. Cela est encore aggravé lorsque cela est fait en s’appuyant sur une soi-disante autorité !

Et pourtant !

Pourtant, il y a beaucoup à gagner d’un véritable dialogue. Il est utile que des pratiques ou des approches nouvelles soient critiquées, challengées. Parfois, effectivement, de nouvelles idées s’avèrent de mauvaises idées et les bonnes idées sont améliorées car elles ont été poussées dans leurs retranchements ! Ces débats, cette stimulation est importante ! Mais elle doit se faire intelligemment, en connaissant le sujet, avec un esprit d’ouverture. Avec la confrontation constructive d’experts, et même en mettant face à face experts, moins experts et débutants !

Utiliser intelligemment les richesses d’une communauté vers une autre

De nombreux domaines d’ingénierie possèdent une très grande richesse de pratique et d’expérience, forte de décennies de travaux, de publications. La communauté des tests fait partie de celle-ci ! La communauté agile a beaucoup à apprendre de cette richesse et de cette expérience, sans devoir renoncer à ses conviction.

Dans l’autre sens, la communauté des tests a certainement des idées à emprunter au jeune courant agile. On a souvent besoin d’idées disruptives pour ortie du carcan des idées reçues ! De cette rencontre devrait naitre un renforcement mutuel.

Publicité

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.