Karl Popper est un philosophe des sciences ayant fait des apports majeurs à l’épistémologie, avec entre autres sa définition de la démarche scientifique par la réfutabilité. Je me suis amusé à appliquer certaines de ses thèses à la mise au point de programmes, en supposant qu’un programme soit une connaissance objective au même titre qu’un théorème ou qu’une théorie scientifique.
Si on applique ces thèses, on peut démontrer que la lecture du code source ne suffit pas, par la seule puissance de la déduction, à prouver que le programme est correct. D’ailleurs, un test ne peut pas prouver la validité d’un programme, au contraire, il ne peut que mettre en évidence une erreur. Popper démontre que le raisonnement inductif n’est pas la méthode rationnelle pour se rapprocher de la vérité, mais que nous procédons par conjectures et réfutations. Tout raisonnement fonctionnerait à partir de théories que l’on essaie de contredire, par l’expérimentation ou par la logique. Pour valider un programme on cherche à le mettre en défaut, ce qui est pourtant intuitivement l’inverse du résultat visé.
Je vois donc la programmation comme l’ajout de conjectures sur un fond initial (langage de programmation employé, librairies, système d’exploitation, autres applications). Fond qui, en passant, est également réfutable selon Popper, contredisant les philosophes affirmant que tout raisonnement rationnel ne se fait qu’à partir d’une base de vérités que l’on augmente par déduction.
En poussant plus loin l’analogie, le test unitaire consisterait donc à tenter de réfuter la conjecture (le programme). Popper affirme également qu’une théorie qui en supplante une autre doit expliquer mieux ou plus de choses que la précédente mais également « survivre » aux mêmes tentatives de réfutation. C’est ce que j’appellerais les tests de non-régression.
Mais alors, si programme = conjecture et test = réfutation, que penser de cette pratique XP : « écrire systématiquement les test unitaires en premier, et ensuite seulement le programme qui va passer les tests unitaires avec succès » (le fameux Test-Driven Development) ?
En termes « popperiens » cela revient à faire des réfutations avant même de conjecturer ! Les « XPeurs » feraient-ils de la programmation d’une façon irrationnelle ?
Disons plutôt que cela signifie que la conjecture est implicite, qu’elle trotte dans la tête du programmeur (ou est discutée au sein du binôme pour ceux qui pratiquent également le « pair-programming ») pendant la programmation des réfutations/tests. Et c’est seulement une fois que toutes les réfutations sont posées que l’on rédige l’équation ou le programme. Connaissant à l’avance les tests, la programmation ressemble plus à mon avis à une sorte de régression au sens statistique (trouver la courbe qui passe par tous les points connus à l’avance).
Cela revient à peser tous les cailloux de la terre et trouver l’équation vraie pour tout un tas de cailloux donné afin de formuler la gravité. Il me semble donc à la fois plus rationnel (et plus intuitif, je l’avoue) de poser la conjecture (le programme) avant d’essayer de le réfuter (par les tests).
Là où je rejoins les partisans du test extrême c’est que la qualité d’un programme est proportionnelle à la quantité de tests tentant de le réfuter, tout comme la meilleure théorie, toutes choses égales par ailleurs, est celle qui se prête et s’est prêtée au plus de tentatives de réfutation.
Ayant moins de connaissances en philosophie qu’en informatique, il est probable que je résume mal la pensée de Popper, je vous recommande donc chaudement la lecture de l’original, comme par exemple « la connaissance objective » disponible en livre de poche.
—
Guillaume Rams