- Debugging de David J. Agans traite des fondamentaux du débogage : comment trouver la cause d’un bug après sa détection et le corriger. Il fournit des principes auxquels revenir régulièrement, aussi bien pour les développeurs débutants et intermédiaires que pour les plus expérimentés
- Le livre s’articule autour de 9 règles et les relie à des cas concrets de terrain : comprendre le système, reproduire l’échec, observer, diviser pour régner, contrôler les changements, conserver une piste d’audit, vérifier ses hypothèses, obtenir un regard extérieur et valider la correction
- Même si l’ouvrage évoque des technologies anciennes ou des exemples extérieurs à l’informatique, l’essentiel n’est pas un outil particulier mais une manière de penser pour circonscrire le problème, applicable au débogage matériel comme logiciel
- Pour les bugs difficiles à traiter, comme les problèmes intermittents, les conseils de Make it Fail sont particulièrement utiles, même s’il est regrettable que le terme Heisenbug ne soit pas abordé directement
- Contrairement à des livres qui expliquent l’usage de GDB ou la rédaction de tests, l’ouvrage se concentre sur la vision d’ensemble du débogage ; il faut donc compléter avec d’autres ressources pour les outils et les tests de régression
Le problème visé par le livre
- Debugging: The 9 Indispensable Rules for Finding Even the Most Elusive Software and Hardware Problems de David J. Agans traite du processus consistant à trouver la cause d’un bug après sa détection, puis à le corriger réellement
- Il synthétise des principes de débogage destinés avant tout aux développeurs logiciel et matériel informatique, plutôt qu’à une technologie ou un outil particulier
- Il convient particulièrement aux développeurs débutants et intermédiaires, tout en aidant aussi les profils expérimentés à retrouver des bases qu’on oublie facilement dans l’urgence
- Son point fort est de condenser en principes et en exemples un savoir-faire de débogage qui s’acquiert souvent avec l’expérience
Les 9 règles du débogage
-
Comprendre le système
- Lire le manuel, saisir l’architecture d’ensemble et comprendre les principes de base comme les détails de fonctionnement
- Vérifier aussi ce que les outils utilisés montrent… et ce qu’ils masquent
-
Provoquer l’échec
- Relancer le problème, repartir du début et stimuler directement les conditions d’échec
- Au lieu de simuler l’échec, provoquer la panne réelle et identifier les conditions non maîtrisées qui produisent les bugs intermittents
- Tout consigner, ne pas trop se fier aux statistiques et accepter que des événements rares puissent réellement se produire
- Ne pas écarter les outils de débogage, mais s’en servir pour faire apparaître le problème
-
Arrêter de réfléchir et regarder
- Avant de se lancer dans des réparations complexes sur la base d’intuitions, commencer par réunir des données observables
- Examiner l’échec et ses détails, créer des instruments de mesure internes ou ajouter une instrumentation externe
- Ne pas éviter d’aller en profondeur, tout en restant attentif à l’effet de Heisenberg, où l’observation elle-même peut modifier le comportement
- Utiliser les hypothèses non comme des conclusions, mais seulement comme un moyen de réduire le champ d’exploration
-
Diviser pour régner
- Réduire progressivement le périmètre de recherche par approximations successives (successive approximation) et déterminer de quel côté se situe le bug
- Utiliser des motifs de test bien visibles et partir d’un état dégradé pour remonter vers la cause
- Éliminer d’abord les bugs déjà connus et le bruit afin de simplifier l’objet de l’enquête
-
Ne changer qu’une seule chose à la fois
- Isoler les facteurs clés et comprendre ce qui ne va pas avant de corriger
- Modifier les tests eux aussi un par un, en comparant avec les cas normaux
- Vérifier enfin ce qui a changé depuis le dernier moment où tout fonctionnait
-
Conserver une piste d’audit
- Garder une piste d’audit de ce qui a été fait, dans quel ordre et avec quels résultats
- Même des détails apparemment mineurs peuvent être la cause ; il faut donc noter les événements en les reliant entre eux
- La piste d’audit du processus de conception peut aussi aider pour les tests et doit être consignée
-
Vérifier la prise
- Remettre en question les hypothèses tenues pour évidentes et revérifier depuis le début
- Inclure aussi dans le périmètre de test les outils eux-mêmes qui servent à chercher le problème
-
Obtenir un regard neuf
- Quand on bloque seul, chercher un nouvel éclairage auprès d’une autre personne ou via une autre façon d’expliquer le problème
- Le simple fait d’exposer le problème à un mannequin peut déjà aider à clarifier sa pensée
- Mettre à profit l’expertise disponible, écouter ceux qui ont de l’expérience et faire passer le partage des symptômes et la demande d’aide avant l’ego
-
Si ce n’est pas corrigé, ce n’est pas corrigé
- Après une modification, vérifier que le problème est réellement résolu et que le changement a bien éliminé la cause réelle
- Les problèmes ne disparaissent pas tout seuls ; il faut corriger à la fois la cause et le processus
La manière dont les exemples donnent vie aux principes
- Une simple liste de règles pourrait paraître sèche, mais les explications détaillées et les récits de cas ancrent les principes dans des situations réelles
- Comme beaucoup d’exemples entrent dans les détails techniques, certains lecteurs pourront les trouver exigeants
- Certains cas portent sur des technologies anciennes, mais comme l’essentiel réside dans les principes plutôt que dans la technique elle-même, ce n’est pas un vrai problème
- Tous les exemples ne concernent pas l’informatique ; le livre inclut aussi un cas amusant lié au câblage d’une maison
- Sans aucune connaissance du matériel ou du logiciel informatique, il sera difficile de suivre une bonne partie des exemples
- Après l’explication des règles viennent des histoires où plusieurs règles s’appliquent ensemble, des exercices simples pour le lecteur, des astuces de help desk et des remarques de conclusion
Points particulièrement marquants et limites
- Le principe « Arrêter de réfléchir et regarder » est particulièrement important
- Beaucoup de gens essaient de corriger un problème à partir de suppositions avant même d’avoir réuni les données permettant de confirmer ou d’infirmer une hypothèse
- « Si ce n’est pas corrigé, ce n’est pas corrigé » est un autre principe qui marque durablement
- Il faut vérifier non seulement qu’une correction a été appliquée, mais aussi quelle était la cause et pourquoi le problème a été résolu
- La discussion autour de « provoquer l’échec, ne pas l’imiter » est moins limpide que d’autres parties du livre, mais elle mérite d’être comprise
- Les problèmes intermittents sont souvent les plus difficiles à traiter, et le livre fournit sur ce point des conseils directs dans Make it Fail
- Heisenberg est mentionné, mais pas le terme Heisenbug, pourtant courant dans le développement logiciel
- Un Heisenbug désigne un bug qui disparaît ou change de comportement quand on essaie de l’observer ou de l’isoler
Ce qui le distingue des autres ressources
- Ce livre se distingue des manuels d’outils ou des ouvrages sur les tests par son focus sur les principes fondamentaux du débogage
- Debugging with GDB: The GNU Source-Level Debugger de Richard Stallman et d’autres auteurs explique surtout une technique ou des commandes d’outils spécifiques
- Il existe aussi des ressources de conseils généraux comme Guide to Faster, Less Frustrating Debugging de Norman Matloff, mais elles ont une portée moins large que le livre d’Agans
- Des ouvrages de test comme Software Testing Techniques de Boris Beizer se concentrent sur l’écriture de tests pour découvrir les bugs, et traitent relativement moins de la manière de corriger un bug une fois trouvé
- Une fois un bug identifié, il faut ajouter un test correspondant à la suite de tests de régression, mais les tests et la régression sortent du cadre de ce livre
Ressources complémentaires et regrets
- Le site compagnon du livre, debuggingrules.com, propose des liens vers des informations connexes ainsi qu’une affiche téléchargeable et imprimable des 9 règles
- Il est regrettable que la liste complète des sous-règles, importante pour bien comprendre les règles, ne soit pas rassemblée sur une seule page du livre ou du site
- L’ouvrage aurait été encore plus utile avec des conseils et exemples plus concrets sur des outils et types de problèmes courants, comme les débogueurs symboliques, les sondes de logique numérique ou ddd on gdb
- Un autre livre étendant ces mêmes règles à la résolution de problèmes généraux hors informatique semblerait aussi pertinent, mais les exemples de celui-ci sont trop techniques pour un lectorat non informatique
- Les principes de base peuvent sembler évidents en surface, mais les débutants doivent les apprendre et les expérimentés ont besoin qu’on les leur rappelle régulièrement ; ce livre convient bien à cet apprentissage comme à ce rappel
1 commentaires
Avis de Hacker News
Je pense que la tentation la plus nuisible est d’ajouter une « correction » au code cassé existant pour essayer de le faire fonctionner
Un code cassé est difficile à réparer parce qu’il y a trop d’endroits possibles à modifier, et il est bien plus facile de casser du code qui fonctionne
Quand une guirlande de Noël ne s’allume pas du tout, remplacer les ampoules une par une échoue s’il y a plusieurs ampoules défectueuses
À la place, il faut partir d’un exemple minimal fonctionnel, ajouter des éléments progressivement jusqu’à trouver l’endroit où l’erreur apparaît ; en pratique, repartir de zéro fait souvent gagner du temps
Sur un problème difficile à cerner en production, certains membres de l’équipe ont réécrit la routine problématique, et la version réécrite a été déployée avant que les autres n’aient fini de déboguer
Au moins une fois, nous n’avons jamais fini par trouver le bug d’origine, parce qu’on ne pouvait pas passer un temps infini sur un problème déjà « corrigé »
La règle numéro 0 est : ne pas paniquer
Les échéances et les clients en colère empêchent de réfléchir clairement ; un bon manager digne de confiance doit donc protéger les ingénieurs de cette pression pour qu’ils puissent se concentrer sur la résolution du problème
Un bon manager nous a déplacés sur un autre appel et a dit : « ignorez ce qu’ils disent et concentrez-vous, je m’en occupe », et mon respect pour ce manager a beaucoup augmenté après ça
Si vous n’avez pas le temps de bien le faire, pourquoi pensez-vous avoir le temps de le faire deux fois ?
C’est-à-dire protéger les ingénieurs de ce qui tombe d’en haut pour qu’ils puissent se concentrer sur leur vrai travail
C’est bien mieux si l’on peut revenir à une version qui fonctionne, puis déboguer sans la pression d’une situation de crise
Pour la règle 4, « diviser pour régner »,
git bisectest d’une grande aideSi vous avez un commit correct, puis parmi des dizaines ou des centaines de commits suivants un seul mauvais commit, vous pouvez réduire en quelques étapes le champ au commit ou au code problématique
Un exemple d’utilisation se trouve sur https://nickjanetakis.com/blog/using-git-bisect-to-help-find...
Lors d’une mission de conseil en direct sur une grande base de code inconnue, cette méthode a permis de réduire rapidement le périmètre ; sans cela, l’espace des choses susceptibles d’être cassées aurait été beaucoup trop vaste
git bisect, je respecte la discipline selon laquelle chaque commit qui arrive dans la « vraie » branche doit pouvoir être compilé individuellement, passer les tests connus à ce moment-là et, à ma connaissance, être déployableJe considère cela plus important que le principe de préserver chaque frappe de clavier ou de garder le dernier commit « Fixes. », car ces principes rendent la recherche dichotomique inutile
Je ne l’utilise pas souvent, mais quand il tombe juste ne serait-ce qu’une fois sur les plus gros bugs mystérieux, il donne d’un coup des indices qui auraient pris des jours, donc il vaut largement le coup
git bisectIl s’agit de comparer un système cassé avec un système qui fonctionne et d’éliminer systématiquement les différences pour trouver le défaut
Cela s’applique au-delà du logiciel ou du matériel ; autrefois, quand j’avais deux jet-skis identiques, c’était pratique de pouvoir en réparer un en le comparant à l’autre
git bisectlui-même, mais le principe plus général de recherche dichotomiqueOn peut l’utiliser non seulement sur une plage de commits, mais aussi pour diviser l’espace d’un système
Par exemple, si un workflow en 10 étapes est cassé, vous pouvez vérifier si l’étape 5 fonctionne, ou réduire le champ pour déterminer s’il s’agit ou non d’un problème matériel
C’est particulièrement important quand la cause du problème n’est peut-être pas un commit de code dans le dépôt sur lequel vous êtes en train de faire la dichotomie
bisectest excellent, mais il faut distinguer les « règles », c’est-à-dire la philosophie et la manière de penser de ce livre, des « outils », qui sont des conseils pratiquesQuelqu’un qui part de « quel outil utiliser ? » est désavantagé par rapport à quelqu’un qui part de « est-ce que ça ne marchait pas avant ? »
Le monde est plein d’outils, et si vous essayez de tous les garder en tête, vous allez devenir fou ; mieux vaut d’abord adopter la philosophie
git bisect run. C’est vraiment un petit outil étonnanthttps://andrewrepp.com/git_bisect_run
Il faut vérifier que l’on modifie le bon fichier sur la bonne machine
De nos jours, j’ajoute toujours temporairement une ligne qui provoque une erreur fatale, pour vérifier que c’est bien le bon fichier et, selon le contexte, la bonne ligne
Pour vérifier que mon changement a réellement un effet
Il existe des règles supplémentaires
« Tout est de ma faute » : il peut s’agir d’un bug du compilateur ou d’une erreur matérielle, mais c’est très rare ; il faut donc d’abord soupçonner mes propres modifications de code
« Quand tu trouves un bug, trouve aussi sa famille et ses amis » : il faut se demander où le même type de problème a pu se produire ailleurs et vérifier
« Optimise d’abord pour les utilisateurs, ensuite pour les programmeurs de maintenance, et en dernier pour l’ordinateur »
Un résumé se trouve sur https://blog.codinghorror.com/the-first-rule-of-programming-...
En général, c’est en réduisant le code qui provoque l’erreur à un cas plus simple qu’on finit par trouver le bug dans sa propre logique
Une ou deux fois, il est réellement resté quelque chose qui valait la peine d’être signalé aux développeurs ; c’était le plus souvent une bibliothèque avec quelques centaines d’utilisateurs au maximum et peu de tests
Au final, j’ai été très soulagé de comprendre que ce n’était pas une erreur de code apparemment impossible, mais un problème de CPU
Mais le mieux reste de faire quelques étapes de recherche dichotomique de plus dans la chaîne cause-effet pour en être sûr
Le conseil « comprenez le système : lisez le manuel, lisez tout en profondeur, connaissez les bases, connaissez la feuille de route, comprenez les outils, cherchez les détails » sonne un peu étrange
On a l’impression que, s’il y a un bug dans le code, il faudrait d’abord lire l’intégralité du manuel de 700 pages de la bibliothèque utilisée, puis 7 livres sur le sujet, et ne regarder le bug qu’un ou deux mois plus tard
Je me demande s’il existe ne serait-ce qu’un programmeur qui suit réellement ce conseil
Atwood et Spolsky ont créé Stack Overflow en 2008, et c’était une époque où les gens connaissaient des livres sous des noms comme le « Camel book » et possédaient simplement ce savoir
0. https://stackoverflow.blog/2021/12/14/podcast-400-an-oral-hi...
« Lire tout en profondeur » ne signifie pas forcément « lire d’abord l’intégralité du manuel de 700 pages de la bibliothèque qu’on utilise »
Si l’on a un problème avec
git bisect, au lieu d’assembler quelques fragments venus de Stack Overflow, on peut approfondir un peu le sujet sur https://git-scm.com/docs/git-bisectL’erreur, toutefois, est de considérer que le résultat de plusieurs mois de travail serait de corriger vaguement un seul bug
L’objectif est de corriger réellement autant que possible tous les bugs de ce type, et d’éviter d’en introduire dès le départ
L’alternative consiste à être parachuté dans un système qu’on ne connaît pas, à toucher un peu à tout sans le comprendre, puis à ouvrir une PR quand les tests passent au vert en espérant ne pas avoir aggravé les choses ; en faire son quotidien ressemble fort à un cauchemar
Au passage, si le manuel de la bibliothèque que vous utilisez fait 700 pages, il y a de bonnes chances que vous utilisiez la mauvaise bibliothèque
En 10e étape, ne faudrait-il pas ajouter le bug aux tests CI pour éviter les régressions ?
Il faut vérifier que la CI échoue avant la correction et qu’elle passe après
Notamment parce qu’il y avait des commits vieux de plus de 5 ans et, comme c’était un composant/une bibliothèque, pas mal de hacks étranges pour IE
Certains tests prennent longtemps à écrire, sont complexes et nécessitent de la maintenance ; il faut aussi accepter qu’une suite de tests ne vérifie pas toutes les conditions aux limites
Cela peut vouloir dire qu’un bug arrivé jusqu’en production peut réapparaître, mais s’il s’agit d’une simple erreur, sa probabilité de récidive n’est pas forcément plus élevée que celle de centaines d’autres erreurs potentielles
Au final, cela dépend du contexte, et écrire des tests n’est pas gratuit
J’ai vu d’innombrables fois la cause profonde se réactiver et le même problème revenir, ou bien personne ne savoir que je l’avais corrigé et tout le monde continuer à utiliser des contournements comme si le bug existait encore
Même après être arrivé à « c’est corrigé ! », laisser une brève trace et une analyse de la cause racine aide les autres
Une fois les tests accumulés depuis longtemps, à quelle vitesse la CI peut-elle encore tourner, et est-il toujours pertinent de les conserver sur le long terme ?
Si vous voulez inculquer cet état d’esprit à des enfants, à vous-même ou à d’autres, je recommande au minimum les ouvrages suivants
The Martian by Andy Weir https://en.wikipedia.org/wiki/The_Martian_(Weir_novel)
https://en.wikipedia.org/wiki/Zen_and_the_Art_of_Motorcycle_...
https://en.wikipedia.org/wiki/The_Three-Body_Problem_(novel)
To Engineer Is Human - The Role of Failure in Successful Design By Henry Petroski
https://pressbooks.bccampus.ca/engineeringinsociety/front-ma...
https://en.wikipedia.org/wiki/Surely_You%27re_Joking,_Mr._Fe...!
J’aime particulièrement le concept de “gumption traps”
Si l’on tombe dans le piège de la rigidité des valeurs, on va de toute façon ralentir ; il faut donc ralentir volontairement, revenir sur ce qu’on a déjà parcouru et vérifier si les choses que l’on jugeait importantes l’étaient vraiment
Le passage disant qu’il n’y a rien de mal à simplement regarder la machine un moment, et qu’en l’observant comme une ligne de pêche viendra un instant où un petit fait demandera prudemment si l’on s’intéresse à lui, tient presque du guide de vie
À mon avis, les événements surviennent simplement à coups de grands sauts logiques, et c’est en réalité plus proche de la fantasy recouverte d’un très mince vernis de jeux de mots scientifiques
J’ai écrit il y a quelques années un texte similaire. Je n’avais pas lu le livre original mentionné ici
https://explog.in/notes/debugging.html
Le zine de Julia Evans sur le débogage est également excellent : https://wizardzines.com/zines/debugging-guide/
Même après avoir débogué avec succès, le travail n’est pas terminé
L’idée centrale de “Three Questions About Each Bug You Find” <http://www.multicians.org/thvv/threeq.html> tient en trois questions
Cette erreur existe-t-elle ailleurs, quel est le prochain bug caché derrière celui-ci, et que faut-il faire pour empêcher ce type de bug