2 points par GN⁺ 2025-01-14 | 1 commentaires | Partager sur WhatsApp
  • 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

 
GN⁺ 2025-01-14
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

    • Si l’objectif n’est pas d’apprendre du problème, le plus rapide peut être de remplacer toute la guirlande au lieu de tester chaque ampoule une par une
      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

    • Tout à fait d’accord. Pendant une astreinte SEV-2, quand les managers des équipes impactées débarquent en nombre et que chacun intervient de son côté, c’est extrêmement frustrant
      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
    • D’après une histoire racontée dans le livre, sur les sous-marins nucléaires, il y a une barre en laiton devant les cadrans et les poignées, et les ingénieurs sont formés, en cas de problème, à ne pas toucher immédiatement les poignées mais à « tenir la barre »
    • La lenteur est fluide, et la fluidité est rapide
      Si vous n’avez pas le temps de bien le faire, pourquoi pensez-vous avoir le temps de le faire deux fois ?
    • Un ancien supérieur décrivait son rôle comme celui d’un « parapluie à merde »
      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
    • Le principe qui en découle est d’avoir toujours un bon plan de rollback
      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 bisect est d’une grande aide
    Si 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

    • À cause de 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éployable
      Je 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
    • Quand je déboguais un problème de configuration réseau dans les années 1990, un collègue plus expérimenté m’a expliqué le principe général qui sous-tend git bisect
      Il 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
    • Ici, l’essentiel n’est pas git bisect lui-même, mais le principe plus général de recherche dichotomique
      On 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
    • bisect est 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 pratiques
      Quelqu’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
    • J’ajoute un article que j’ai écrit sur git bisect run. C’est vraiment un petit outil étonnant
      https://andrewrepp.com/git_bisect_run
  • Il faut vérifier que l’on modifie le bon fichier sur la bonne machine

    • C’est une variante de « vérifiez la prise »
      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
    • Dieu seul sait combien de temps j’ai perdu à modifier des fichiers générés, des fichiers d’une autre version, ou à oublier d’enregistrer
    • Le plus grand principe que je me suis toujours répété, et que j’ai enseigné aux autres, est de vérifier que le code en cours d’exécution est bien celui que je crois
    • C’est pourquoi il faut d’abord le faire casser différemment
      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 »

    • La première règle est connue dans The Pragmatic Programmer sous la forme « select n’est pas cassé »
      Un résumé se trouve sur https://blog.codinghorror.com/the-first-rule-of-programming-...
    • L’approche consistant à se dire « comme c’est peut-être un bug, essayons de créer un cas de test à signaler sur la mailing list » est parfois utile aussi
      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
    • J’ai toujours eu l’état d’esprit « c’est ma faute », mais le fait que ma station de travail Linux plante sans cesse à cause d’un i9-13900K a franchement été humiliant
      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
    • Il est plus sain de partir du principe que son code est faux
      Mais le mieux reste de faire quelques étapes de recherche dichotomique de plus dans la chaîne cause-effet pour en être sûr
    • À propos de la « famille et des amis », il m’est arrivé plusieurs fois qu’en corrigeant de petits problèmes périphériques, apparemment sans rapport, le bug que je cherchais apparaisse
  • 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

    • Cet article a été écrit en 2004, l’année de l’IPO de Google
      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...
      1. https://www.perl.com/article/extracting-the-list-of-o-reilly...
    • Ici, l’interprétation semble un peu différente
      « 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-bisect
    • Sur le fond, c’est juste
      L’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

    • Le plus gros dépôt JavaScript pur sur lequel j’ai travaillé, un projet d’environ 150 000 lignes, appliquait cette règle, et cela a vraiment été un sauveur
      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
    • Je ne pense pas que cela en vaille toujours la peine
      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
    • Plus généralement, il faut documenter
      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
    • Que faire des tests de correction de bugs vieux de plusieurs années ?
      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...!

    • D’accord. Je trouve que Zen and the Art of Motorcycle Maintenance saisit le mieux l’art de résoudre les problèmes
      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
    • Je ne vois pas quelle partie de Three Body Problem a un rapport avec le débogage, la résolution de problèmes ou la planification
      À 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