Comment bien appréhender un bug ?

Comment bien appréhender un bug ?

Trucs et astuces de débuggueur

Bonjour à toutes et à tous, je m'appelle Lionel et travaille à Shop Application depuis 2011.
J'ai fait du support technique pendant 5 ans et suis aujourd'hui dans le pôle développement.
Ma mission principale est de traiter les bugs logiciels. Ces bugs sont généralement remontés par le support technique dans une liste de tâches où chacune correspond à un bug.

J'ai donc voulu, dans cet article, partager les points qui me semblent importants pour appréhender un bug.
Il ne parlera pas de la technique pure de correction. Il n'est pas non plus destiné à lister des outils permettant de gagner du temps. Ce n'est pas non plus une liste de tâches permettant de mieux gérer le bug remonté.

Pour la rédaction de cet article, j'ai commencé par tenter d'élaborer une liste de tâches partant de la remontée du bug jusqu'à la résolution.
Mais j'ai eu beau retourner le truc dans tous les sens, je ne suis pas parvenu à trouver une procédure élégante et universelle : une sorte de formule mathématique de débug.
On avait des retours en arrières, des branches qui se multipliaient à tout va.

J'ai donc tout remis à plat et ai essayé de dégager des idées générales qui me servent souvent ou systématiquement quel que soit le bug. Qu'il soit mineur, complexe, spécifique à un site, quelles sont les réflexions qui me servent à l'appréhender ?
J'ai réussi à dégager 6 remarques. Elles sont soit des conseils, soit de simples constats issus de mon expérience.

 

Chaque bug est unique

Ce point est très lié à l'introduction de cet article et au choix des points à aborder.
Évidemment, on trouve des récurrences. On peut régulièrement avoir cette sensation de "déjà vu" quand on corrige beaucoup de bugs. Mais faire une liste de procédures qui dit : si tel type d'erreur, aller au bloc A sinon aller au bloc B, peut, certes, faire gagner du temps dans certains cas, mais en fera perdre beaucoup sur le long terme.
Si on un message d'erreur, il ne faut pas en comprendre sa forme, mais son fond. Pourquoi est-ce que j'ai cette erreur ? Depuis quand est-elle présente ? De quelle fonctionnalité on parle exactement ? Le code à l'origine de cette erreur existe dans quel but ? Est-ce lié à une étourderie de développeur, à un manque de test ou autre chose ?

Il faut vraiment comprendre le pourquoi du comment.
Pour cela, il est primordial de connaître le logiciel (et évidemment les langages de programmation utilisés). Et si on débute, rester dans son coin est la pire erreur : il faut communiquer avec ses collègues afin d'être sûr d'avoir compris la problématique remontée.
Un bug mal compris sera un bug mal corrigé.
Un bug mal corrigé pourra créer des dommages collatéraux (un correctif qui crée un autre bug, mais j'y viendrai).

Encore une fois, cela est du cas par cas. Tout ne nécessite pas une telle réflexion. C'est justement au débuggeur de doser cela et c'est pour ça que ce premier conseil existe : chaque bug est unique. Et chaque problématique doit être gérée au cas par cas. À ma connaissance, il n'existe pas de procédure claire et qui fonctionne permettant d'appréhender un bug.

 

Reproduire le bug

Cela paraît évident au premier abord. Mais il y a des cas où une erreur rapportée n'est ensuite pas constatée.
Il arrive même que l'on ait un message d'erreur explicite dans les logs. Il y a bien eu une erreur venant du logiciel. Et pourtant, impossible de la constater.
Il est néanmoins essentiel de reproduire l'erreur afin d'être sûr que la modification apportée corrigera bien l'erreur. Se dire "vu le message d'erreur, je suppose que ça vient de ça, on modifie donc cette ligne et tout ira bien" est une erreur. Sommes-nous vraiment sûr que le bug sera corrigé ?
Il faut pouvoir constater un "avant" et un "après" correctif.
À part de rares cas où l'erreur est tellement explicite, il faut tout faire pour trouver les conditions permettant de reproduire l'erreur remontée.

 

Avoir une configuration témoin

Une fois le bug reproduit, il est recommandé d'avoir une configuration témoin qui n'a pas d'erreur. Si, par exemple, on a une erreur de calcul de prix sur un article, avoir un autre article sans erreur est un plus non négligeable.
Car, une fois que le correctif permet à notre produit d'avoir un bon prix, constater que cela n'a impacté aucun autre prix est un gage de qualité.
Donc, dès que vous en avez la possibilité : créez une configuration témoin pour éviter un dommage collatéral.
Dès que l'on peut avoir une configuration témoin, il faut en avoir une.
Croyez-moi, cela m'a évité bien des soucis. Car avoir une remontée de bug liée à un correctif récent n'est pas agréable du tout. Cela implique généralement un correctif qui doit être déployé rapidement et il faut donc, dans l'urgence, trouver un correctif pour 2 problèmes (car revenir en arrière reviendrait à créer le bug précédemment remonté).

 

Faire un résumé du bug

Il peut arriver que la personne qui remonte une erreur n'a fait que la survoler. Soit parce qu'elle n'a pas les compétences techniques ou soit parce qu'étant sur une autre tâche (lors de la remontée du bug) n'a pas approfondi les analyses.

On peut donc avoir des descriptions de bug avec des termes non techniques ou des conditions inutiles.
Une condition inutile est un critère censé impacter la reproduction du bug mais qui ne l'est, en réalité, pas.
On peut, par exemple avoir en description : "Quand on met l'article ABCD en promotion, le prix n'est pas bon".
Seulement, en faisant des tests, on s'aperçoit que même sans promotion, le prix n'est pas bon. Aussi, qu'est-ce qu'un prix "pas bon" ?

Dans ces cas-là, l'idéal est de rédiger à nouveau le bug (à la suite de la première description par exemple). Par exemple "Sur l'article ABCD, le prix est de XX€ au lieu de ZZ€".
Ça n'a l'air de rien comme ça, mais ça change la manière d'appréhender le bug. Contrairement à la première description, on a supprimé les conditions inutiles (on n'aura pas la fonctionnalité de promotion à analyser). On s'est aussi créé un objectif clair : Le prix doit être de ZZ€.

Un résumé clair et le plus concis possible du bug fera gagner du temps.
S'il y a des problèmes de compréhension, il ne faut pas hésiter à demander plus de détails à la personne ayant remonté le bug. Ou même lui faire valider la nouvelle description afin de s'assurer que tout le monde est d'accord sur la problématique et le résultat désiré.

Une bonne description de bug doit contenir :

  • L'erreur rencontrée (si besoin expliquer pourquoi cela est considéré comme une erreur)
  • Les conditions qui permettant de constater l'erreur (en ayant retiré toutes les conditions inutiles)
  • Indiquer le résultat attendu

Évidemment, quand le bug concerne une basique erreur PHP, il n'est pas utile de partir dans une telle procédure.
Mais il faut savoir que notre logiciel contient, par exemple, un outil d'export comptable et que, quand une erreur de calcul m'est remontée, utiliser ce fonctionnement me fait non seulement gagner du temps, mais aussi à mes collègues.

 

Lire le code avant de se lancer

Bien souvent, et encore plus quand je ne parviens pas à reproduire le bug, je ne fais qu'une lecture de code avant de me lancer dans le correctif. Je ne touche à rien, je ne fais que regarder.
On en revient finalement au premier point : comme chaque bug est unique, se lancer tête baissée en modifiant du code sera source d'erreur.
Peu importe les techniques utilisées ensuite pour débugger (Xdebug, print_r, logs, …). Si vous n'avez pas exploré ne serait qu'un peu la fonctionnalité impactée, vous perdrez du temps. Pire, vous pourrez même créer un dommage collatéral.

 

Analyser un bug, c'est déjà débugger

Ce dernier conseil concerne surtout l'organisation et un piège dans lequel on peut vite tomber.
Quand on a une liste de bugs à traiter, on peut avoir tendance à d'abord les survoler; ce qui d'ailleurs est une bonne chose car on peut prioriser les bugs à traiter.
Le piège dans lequel on peut tomber, à la lecture d'un bug, c'est qu'on a tendance à commencer à l'analyser. Il faut savoir qu'à ce moment, on est déjà dans un processus de débug. Débugger ne consiste pas qu'à appliquer un correctif; ce n'est qu'une étape du débug. Un débug est une suite de tâche :

  1. Analyser (lire le code, reproduire l'erreur, tester)
  2. Appliquer un correctif (modifier le code, tester le résultat)
  3. Déployer le correctif

L'étape 3 est quasi toujours la plus rapide et dépend surtout de l'organisation dans l'entreprise. L'étape 2 peut parfois prendre du temps car plusieurs correctifs sont parfois à envisager avant d'en trouver un satisfaisant. L'étape 1 est souvent la plus longue car elle nécessite de bien comprendre la fonctionnalité impactée et comment l'erreur a pu survenir.
L'analyse est déjà le processus de débug. Il est important d'avoir conscience de ça. Car on peut très vite commencer le débug d'une erreur mineure alors que des erreurs majeures sont également à traiter.
Mais avoir conscience de ça permet surtout de réaliser que débugger n'est pas que lié au code. Si on néglige la phase d'analyse, on passe à côté de la moitié (ou plus) du temps de correctif.

 

Un petit résumé qui peut servir de mémo si cet article vous a plu :

  1. Chaque bug est unique :  un bug mal compris sera un bug mal corrigé
  2. Reproduire le bug : il faut pouvoir constater un "avant" et un "après" correctif
  3. Avoir une configuration témoin pour éviter un dommage collatéral
  4. Faire un résumé du bug clair et le plus concis possible fera gagner du temps
  5. Lire le code avant de se lancer
  6. Analyser un bug, c'est déjà débugger

Partager sur les réseaux