headerphoto

Des bugs dans le cerveau aux bugs dans le code

Pourquoi est-il si difficile de créer du logiciel sans bugs? Probablement en grande partie parce que l'outil principal que nous utilisons est lui-même un très mauvais exemple de conception rationnelle, et pour cause, et quand on y regarde de près s'avère bourré de bugs.

Cet outil, c'est le cerveau; ou si l'on veut, mais en ne le prenant que comme une métaphore, le logiciel, appelé "Intelligence", que nous faisons tourner sur le matériel qu'est le "Cerveau". (Faire le parallèle entre l'esprit-logiciel et le cerveau-matériel, c'est en soi rentrer dans la vaste controverse de l'intelligence artificielle, et ce n'est pas mon propos.)

La Loi des Bugs

Je ne suis pas loin de penser que l'énoncé suivant est une loi fondamentale du développement:
Il n'existe de bugs dans nos programmes qu'en raison de bugs dans notre pensée.
Le terme "bug" est en soi un choix terminologique malheureux, c'est un excellent exemple de la psychologie de la projection que j'évoquais dans un précédent billet: on visualise une petite bestiole dont l'existence et les décisions sont autonomes et indépendantes de notre volonté. Je lui préfère en général le terme "défaut", qui indique plus clairement ce qui est, selon moi, toujours à l'origine de ce qu'on appele familièrement un bug: une erreur du programmeur, se traduisant par un code source qui spécifie un comportement différent de ce qu'il devrait être.

Mais c'est au moins un terme familier, et si vous dites à quelqu'un "tu ne t'en aperçois pas mais ton cerveau est plein de bugs", vous êtes au moins sûr de faire une forte impression.

Biais cognitifs

L'étude des bugs du cerveau relève de la psychologie, et le terme plus communément accepté est celui de "biais cognitif". Contrairement à la situation qui prévaut dans le domaine du logiciel, les sciences cognitives ont produit, s'agissant des biais cognitifs, des connaissances scientifiques démontrées de façon robuste, répétable, qui ne sont plus affaire d'opinion. Indépendamment de ce que je voudrais croire ou de mes bonnes intentions, je suis bien contraint de reconnaitre que mon cerveau, à peu de choses près dans la même mesure que celui de mes congénères, est sujet à un certain nombre de biais cognitifs.

Intéressons-nous par exemple au biais de confirmation. Nous allons voir que ce phénomène, qui est par ailleurs l'un des plus importants et sournois dans la psychologie humaine, est tout à fait pertinent pour éclairer notre approche du développement logiciel.

Il est mis en évidence par de nombreuses expériences dont les premières remontent aux années 1960 avec les travaux de Peter Wason.

Wason montre à ses sujets un triplet composé de trois chiffres: (2, 4, 6) et indique que ce triplet répond à une "règle de construction" qu'il s'agit de deviner. Il demande aux sujets de lui fournir des exemples supplémentaires afin de "tester" diverses hypothèses quant à l'énoncé de cette règle. L'expérimentateur se borne à donner une réponse binaire: "oui, votre exemple est conforme à la règle" ou bien "non, votre exemple n'est pas conforme". C'est donc une tâche inductive, très ouverte par nature.

En étudiant de près les hypothèses formulées par les personnes confrontées à cet épreuve et les "essais" fournis successivement, Wason est en mesure de démontrer une tendance tout à fait systématique: on propose beaucoup plus facilement des exemples "de confirmation", c'est-à-dire conformes à l'hypothèse qu'on a la plus récemment formulée. Or c'est une erreur, car si des exemples confirmés peuvent nous amener à valider une réponse avant de la proposer, la démarche la plus fructueuse consiste à proposer des exemples qui (s'ils sont acceptés par l'expérimentateur comme conformes à la règle) invalident notre hypothèse et nous forcent à la reformuler.

D'autres expériences de Wason conforteront le "biais de confirmation" comme une erreur de raisonnement tellement courante qu'on peut la considérer comme systématique chez l'être humain: ainsi sur une tâche consistant à déterminer lesquelles parmi quatre cartes on doit retourner pour vérifier une règle du type "SI telle figure apparaît au recto ALORS telle autre doit apparaître au verso", seuls 10% des sujets donnent la bonne réponse! Ceci alors que plus de 90% des sujets reconnaissent, une fois qu'on leur a donné cette réponse, qu'elle est effectivement correcte et qu'ils pouvaient logiquement le déterminer à la lecture de l'énoncé: ce qui écarte donc l'hypothèse d'une ambiguité ou d'une mauvaise compréhension de la tâche.

(Si vous êtes tenté à la lecture de ce billet de développer vos propres facultés en matière d'induction et de formulation d'exemples contradictoires, essayez le jeu Zendo, passionnant pour les petits et les grands...)

Application au développement

Revenons au développement de logiciels, et plus précisément à un des épisodes de l'historique du génie logiciel. En 1976, Glenford Myers, auteur de l'ouvrage de référence "Software Reliability, Principles and Practices", écrit ceci:
Il est impossible de tester vos propres programmes. Aucun programmeur ne devrait tenter de tester son propre programme. Ceci s'applique à toutes les formes de test, que ce soit le test système, fonctionnel ou le test unitaire. [...] Le test doit être une activité extrêmement destructrice, et il est des raisons psychologiques profondes qui empêchent le programmeur d'adopter une attitude destructrice vis-à-vis de son propre programme."
Les mots employés sont très forts: "impossible", "toutes les formes de test". Myers ne cite pas Wason et ne détaille pas dans cet ouvrage les "raisons psychologiques profondes" auxquelles il fait allusion, mais il semble clairement s'agir de notre tendance à imaginer plus facilement des jeux d'essais qui visent à confirmer nos hypothèses que ceux pouvant les infirmer. (Il existe d'ailleurs quelques études cherchant à démontrer directement l'impact du biais de confirmation sur l'incidence des défauts dans le code.)

Cette affirmation que Myers présente comme un "axiome" deviendra pendant de nombreuses années l'orthodoxie en matière de test logiciel. (Une recherche Google avec la phrase "test their own code" donne assez facilement des exemples récents de billets d'opinion reprenant sans la critiquer cette idée, comme si elle allait de soi.)

En un sens, cette affirmation a eu un effet positif: elle a favorisé l'apparition d'une sous-discipline, le test indépendant, dont l'apport est certainement bénéfique; bien qu'en France la culture soit apparemment bien moins sensible à l'intérêt d'employer des personnes dans un rôle dédié de "testeur" ou "assurance qualité", par rapport aux Etats-Unis.

TDD ou l'inversion géniale

Pourtant, je soupçonne cette attitude d'avoir également généré de sérieux dégâts, en berçant d'innombrable développeurs dans la douillette illusion que "tester leur propre code" était non seulement une erreur mais une faute professionnelle. Pensez-y la prochaine fois que vous rencontrez sur un site Web une NullPointerException, l'exemple par excellence d'une défaillance logicielle qu'on peut parfaitement éviter en testant plus soigneusement son code.

Les choses n'ont commencé à changer que relativement récemment, et grâce à l'introduction de la pratique agile du Développement par les Tests (ou TDD).

Il s'agit pour moi (et pour d'autres, comme Steve McConnell dans Code Complete) de l'une des contributions majeures de la mouvance Agile à ce qu'il faut bien encore appeler le génie logiciel. Depuis les années 2000 le discours autour de cette pratique a considérablement évolué en sophistication, mais l'idée élémentaire est restée la même.

Elle exploite la notion d'un test unitaire automatisé, c'est-à-dire un bout de code qu'on écrit uniquement pour mettre en évidence qu'un autre bout de code (celui-là utilisé directement dans le programme réel) fonctionne comme attendu. Il va de soi qu'un test unitaire automatisé, en soi, reste un "test", un "essai" qu'on confronte à une hypothèse: l'automatisation ne change rien de fondamental.

Ce qui est radical, c'est l'idée suivante:
écrire le test avant d'écrire le code correspondant
Cela n'a l'air de rien mais cette simple inversion suffit simultanément:
  • à donner raison à Glenford Myers sur l'importance du biais de confirmation en matière de test
  • à lui donner tort sur les conclusions: un développeur peut et doit tester son code
En effet, avant d'avoir écrit un élément de programme, nous ne sommes pas sujets au biais de confirmation, puisque nous ignorons encore les détails de l'implémentation. Ces détails fonctionnenent en programmation comme l'hypothèse à tester dans la tâche de Wason: si nous avions connaissance de notre implémentation, nous serions tenté de ne penser qu'à des jeux d'essais qui confortent l'impression que nous avons que notre code est correct.

En inversant l'ordre de marche, nous avons tenu compte de nos propres limitations cognitives, et nous leur avons apporté une solution nettement plus efficace, car nécessitant moins de coordination, que la solution classique "embaucher des testeurs indépendants pour tester le code mal fichu des développeurs". (Cette dernière solution garde cependant de son intérêt, car il existe bien d'autres aspects de la qualité logicielle qui peuvent bénéficier du travail d'un testeur que la seule qualité technique du code source.)

Conclusions

Ce premier exemple donne une perspective un peu différente sur le TDD que celle habituellement présentée, et surtout démontrant à quel point s'intéresser au développement logiciel par le biais des sciences cognitives, et notamment par celui des biais cognitifs, peut être puissant et fructueux.


L'approche usuelle du génie logiciel a été d'écarter systématiquement ces considérations, qui reposent pourtant sur des bases scientifiques robustes, pour ne considérer que les aspects "objectifs" du logiciel, vu comme une "chose naturelle" indépendante de l'esprit humain qui l'a créé: c'est pourquoi, à mon sens, cette discipline telle qu'elle a été conçue jusque là ne peut pas résoudre les difficultés qu'elle prétendait aborder. Pour progresser, il est impératif de tenir compte des aspects cognitifs qui jouent un rôle déterminant dans la création de logiciels.

Le champ d'application de cette démarche va bien au-delà de la technique, on peut lui trouver des applications dans la gestion de projet, la gestion des compétences, l'estimation des délais, bref à l'ensemble des préoccupations des professions du logiciel.

1 commentaires:

Dave a dit…

En ce qui concerne les connotations du mot "bug": Le premier bug avait déjà pris une décision autonome avant tout cerveau humain se sont impliqués. http://www.jamesshuggins.com/h/tek1/first_computer_bug_large.htm

(Avec nos remerciements à Google Translate)

Enregistrer un commentaire