Leçon d’humilité: Balayer devant sa porte ou la découverte du bug du Pentium

Ca ne fonctionne pas, c’est la faute à l’autre

Dans mon travail, j’entends souvent: Ce n’est pas ma faute, il y’a une anomalie dans le service, il ne retourne pas les bonnes données. Ou encore il y’a un bug dans le framework.
Ou plus rarement, mais c’est arrivé, c’est un bug de la JVM ou de Spring ou de Hibernate.

C’est souvent plus facile d’accuser quelqu’un d’autre, parfois même ça peut rendre service. Mais face à ce genre de situation, dans 99,9999% des cas, le problème provient de ce qui se trouve entre le clavier et l’écran: Le développeur (en l’occurence moi).

Comment s’y prendre

En fait, ce genre de situation me rappelle une anecdote que j’avais entendu quand j’étais encore sur les bancs du cours de Génie Logiciel (en école d’ingénieurs), qui concerne la façon dont a été découvert le bug du Pentium.

Si vous recherchez un peu sur le net, il y’a des articles qui parlent profondeur des tenants et des aboutissants de cette histoire, mais l’idée ici est surtout de décrire la démarche du mathématicien américain Thomas Nicely, de l’université Lynchburg (Virginie).

Ce mathématicien travaillait sur la suite numérique qui additionne les inverses des nombres premiers jumeaux (nombre premiers dont la différence vaut 2, exemple, 5 et 7 , 11 et 13, etc…). Le début du la suite est (1/3 + 1/5) + (1/5 + 1/7) etc… .

Autant dire qu’il s’agit d’un sujet pointu et précis et que notre expert connait bien son domaine, il faut dire que la valeur de cette suite ne change pas. Il possédait alors des tables contenant la valeur de cette suite. Et biensûr, il avait établi des algorithmes et développé des programmes permettant de réaliser ces calculs.

En 1994, il reçoit un nouvel ordinateur équipé d’un processeur révolutionnaire, lui permettant d’approfondir son étude. Il s’empresse de recompiler ses programmes pour ce processeur et les executent avant de s’apercevoir de différences entre les valeurs de ses tables et celle retournées par ses programmes.

Il commence alors par vérifier ses tables, refait les calculs et valide ses résultats. Tout est correct, ses résultats sont bons.
Il reverifie alors ses algorithmes, les écrits dans un autre langage, et obtiens des résultats incorrects sur ce processeur.
Il décortique alors le compilateur afin de rechercher une anomalie dans ce dernier et toujours rien.
Il met alors finalement en cause le processeur et démontre que l’unité de division de calcul flottant contient effectivement un bug.

La morale de l’histoire

Avant de rejeter la faute sur quelqu’un d’autre, je m’assure toujours que l’erreur ne vient pas de moi et de ce que j’ai fait. Aujourd’hui, c’est encore plus simple de s’en assurer avec tous les outils à ma disposition. Voici les quelques pratiques que j’utilise et qui m’aide à faire celà dans mon travail:

  • Les tests unitaires automatisés et tous les frameworks de tests unitaires
  • Le mode debug (et remote debug, on l’oublie souvent celui-là) de mon IDE
  • Les sources des frameworks (ou de la VM) que j’utilise, non pas pour les incriminer mais pour comprendre ce que j’ai fait d’incorrect
  • La documentation de reference et les API