Via Negativa -- à la recherche de pratiques robustes
Tests, Bugs, et Preuves de programme…
Dans son livre, Antifragile, N.N. Taleb introduit la notion de via negativa, qu’il emprunte à la théologie classique, afin d’expliquer la robustesse d’un savoir formé par négation : nous avons une connaissance bien plus solide de ce qui n’est pas vrai, (de ce qui ne fonctionne pas), que de ce qui est vrai (ou fonctionne) :
So the central tenet of the epistemology I advocate is as follows: we know a lot more what is wrong than what is right, or, phrased according to the fragile/robust classification, negative knowledge (what is wrong, what does not work) is more robust to error than positive knowledge (what is right, what works). So knowledge grows by subtraction much more than by addition — given that what we know today might turn out to be wrong but what we know to be wrong cannot turn out to be right, at least not easily. If I spot a black swan, I can be quite certain that the statement “all swans are white” is wrong. But even if I have never seen a black swan, I can never hold such a statement to be true.
N.N Taleb - Antifragile
Cette notion de "savoir négatif" rappelle une considération fameuse émise par Edsger Dijkstra dans le domaine du génie logiciel :
Program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absence.
La remarque de Dijkstra a certainement conduit à donner aux tests la réputation d’une activité douteuse, entachée d’empirisme, intrinsèquement incomplète. C'est malheureux, car en dépit de leur inaptitude irrémédiable à démontrer l’absence de bugs, les tests apportent un savoir négatif qui permet d’augmenter progressivement la qualité d’un logiciel, un peu de la même manière (sur une toute autre échelle) que l’ensemble des accidents depuis la naissance de l’industrie aéronautique a contribué à améliorer la fiabilité des transports en avion. Lorsqu'un test ne passe pas, l'information obtenue à propos du système sous test est bien plus robuste que si le test passait. Par robustesse, j'entends le degré de confiance avec lequel on peut prendre une décision concernant le programme. Il en va de même pour une revue, qui est une sorte de test dans la mesure où elle met à l'épreuve un artefact. Lorsqu'une revue produit une liste de points à améliorer, l'information obtenue est plus robuste que si elle n'en relève aucun. En cela la revue est une forme d'exposition volontaire au retours d'information, même si ces retours peuvent bien souvent avoir une connotation négative, qu'il convient de pondérer. Jerry Weinberg relate un cas où un manager avait décidé de mettre fin au process de revue parce que celui-ci ne relevait plus autant de défauts qu'initialement, devenant ainsi une "dépense injustifiée". En réalité les développeurs avaient cessé de remonter les défauts trouvés parce ce qu’ils subissaient alors les foudres du manager en question.
Une opération qui permettrait d’obtenir une information positive plus fiable que les tests est celle qui consiste à établir une démonstration logique de la justesse du programme. Encore faut-il que cette démonstration (ou le modèle sur lequel elle s’appuie) ne comporte pas d’erreur; dans un commentaire (devenu plus célèbre que le code qu'il accompagnait), Donald Knuth écrit ceci:
Beware of bugs in the above code; I have only proved it correct, not tried it.
A la recherche de pratiques robustes
En matière de développement de logiciel, il est parfois difficile de faire la distinction entre une pratique qui peut s'avérer très utile (en fonction du contexte) et une recette inefficace, vague, incomplète ou obsolète dont le seul atout est d'être fortement répandue. Pour s'en convaincre, il suffit de demander à une personne travaillant dans ce domaine depuis 30 ans (on les trouve facilement, si on fait fi du jeunisme de surface arboré par notre industrie) de nous faire une liste des différentes pratiques et standards qu'elle a pu suivre et/ou défendre au cours de sa carrière et qu'elle a abandonné depuis. À titre d'exemple, voici une partie de ma liste :
- Etude de faisabilité
- Spécifications Fonctionnelles Générales
- Spécifications Fonctionnelles Détaillées
- Estimations en jour x hommes
- Estimation Détaillées des Charges
- Analyse Fonctionnelle
- Analyse Organique
- Cas d'Utilisation
- Modèle Conceptuel de Données
- Modèle Logique de Données
- Modèle Physique de Données
- Modèle Conceptuel de Traitements
- Modèle Logique de Traitements
- Modèle Physique de Traitements
- Modèle Relationnel des Données
- Cinématique des Écrans
- Modèle des Objets de l'Entreprise
- Entêtes de procédure
- Rapport d'exécution de tests unitaires (d'intégration, d'assemblage, de recette…)
- Notation hongroise
- Notation en trigrammes
- Commentaire systématique de chaque paragraphe du code
- Déclaration des variables en tête de chaque procédure
- Pas de if sans else
- Interdiction des procédures récursives (la liste des interdictions serait trop volumineuse à citer entièrement)
- Programmation Structurée
- Programmation Orientée Objet
- Exécution systématique du code au débogueur
Pour me consoler de toute cette énergie investie dans des idées que je considère comme obsolètes (dans la majorité des contextes), je me dis que c'est la vie, que tout passe, et qu'en matière de développement comme ailleurs les modes changent. Ou bien est-ce que nos pratiques évoluent, c'est à dire que les pratiques qui ne "marchent pas" disparaissent au profit de pratique plus robustes ? Il serait dangereux de le croire aveuglément, mais il y a tout lieu de parier sur une telle possibilité : après tout, les pratiques qui deviennent suffisamment robustes sont intégrées dans la culture, comme l'observe Jerry Weinberg (dans l'indispensable ouvrage Quality Software Management) :
Software engineering processes are a lot simpler when you can depend upon ordinary developers not to make simple mistakes that were well understood years before they were born. This illustrates the trade-off between culture and process: Whatever you can safely assume in the culture, you don't have to specify in your process description.
A suivre…
Dans cette série d'articles, nous nous mettons à la recherche de la "Via negativa", cette robustesse construite à partir du savoir négatif, en examinant des pratiques couvrant divers aspects du développement logiciel : programmation, tests, revue, conception, spécification, et en se demandant si elles possèdent ou non cette forme de robustesse.