Code-Garage #23 - Apprendre à débugger étape par étape

Durée: 14m15s

Date de sortie: 09/05/2022

Trouver et corriger une défaillance dans du code s'apprend avec l'expérience, mais voici les étapes et méthodes à respecter pour gagner du temps, et de la santé mentale !

Notes de l'épisode :

Salut, c'est Nico de Code Garage.
Code Garage, qu'est-ce que c'est ?
C'est un site avec des contenus gratuits et des formations pour s'améliorer en tant
que dev, passé de juniors à experts grâce à des contenus qui sont faits pour vous.
Aujourd'hui, dans ce nouvel épisode du podcast, on va apprendre à débugger du code.
Parce qu'une des premières frustrations dans le développement, c'est de rester bloqué
pendant des heures parfois sur une défaillance de notre code, qu'on va appeler plus communément
le bug si c'est un sujet que vous intéresse.
J'ai fait un podcast il n'y a pas longtemps sur ce sujet-là.
En tout cas, c'est une étape incontournable dans la vie du développeur, toute la développeuse
et la recherche et la correction de ces problèmes.
C'est une compétence hyper importante pour gagner en autonomie.
Donc moi, j'ai essayé de vous construire un espèce de guide pour apprendre à trouver
les bugs, les comprendre, les corriger, étape par étape.
Parce que même si on pense qu'on sait un petit peu tous faire ça au fur et à mesure,
en fait, il y a des étapes auxquelles on pense pas forcément et qui sont indispensables.
La première grosse étape, évidemment, c'est comprendre.
Et pour comprendre, il faut commencer par lire les erreurs.
Je sais que dans la majorité des cas, lire l'erreur, c'est quelque chose qu'on fait,
mais on le fait trop vaguement.
En fait, il faut la lire vraiment et prendre le temps de l'analyser.
Ça va vous permettre de la corriger parfois très rapidement parce que le système,
que ce soit le compilateur, l'interprèteur, l'environnement,
va essayer de vous donner un maximum d'infos sur la défaillance en question.
Si on prend par exemple un exemple en SQL,
et bien si on a un problème de syntaxe, on va avoir tout simplement une erreur
qui va plutôt un problème de données, on va avoir une erreur qui va nous dire,
et bien il y a une colonne inconnue qui s'appelle Tel dans votre closeware.
En Java, on va avoir par exemple, no such file exception,
ça veut dire ce fichier n'existe pas.
En JavaScript, on va avoir undefined is not a function
avec un numéro de ligne, etc.
Donc ça va nous dire qu'on essaye d'appeler une fonction,
mais qui en réalité n'existe pas.
Donc à chaque fois pour chaque langage, on va avoir des erreurs,
des données qui va falloir qu'on récupère pour en apprendre le plus possible
sur la défaillance en question.
Alors qu'est-ce qui se passe quand on n'a pas d'erreur ?
Des fois il se peut que le dysfonctionnement de votre logiciel,
il n'entraîne pas d'erreur,
et en fait il va entraîner seulement un état invalid du logiciel.
Ça veut dire que à l'origine,
votre logiciel ne spécifie pas suffisamment ses attentes
et vérifie pas suffisamment les données en entrée et en sortie.
Là, vous devrez ajouter des conditions, des try-catchs
pour créer vous-même vos propres erreurs
et éviter que l'état non valide que vous recevez
soit redirigé dans un chemin d'exécution classique de votre application
parce que sinon normalement, vous aurez une erreur.
Ensuite, on va devoir reproduire ces erreurs
parce que reproduire une défaillance c'est indispensable.
C'est le seul moyen que vous aurez pour récupérer suffisamment d'infos
parce que si ça arrive une fois, c'est bien,
mais si ça n'arrive qu'une seule fois,
peut-être que tous ces logs-là,
tout ce que je vous ai dit avant,
vous n'aurez pas eu l'occasion de le voir.
Donc il faut pouvoir reproduire ces erreurs
pour toujours avoir accès à ces informations.
Et donc c'est grâce à ça qu'on va pouvoir trouver une solution,
vérifier, tester que votre solution fonctionne comme prévu.
Globalement, ce qu'il faut retenir, c'est que pour reproduire un bug,
il faut arriver à retrouver l'état dans lequel était votre logiciel
au moment où le bug est apparu.
Un état, c'est quoi ?
C'est la version de votre code instanté,
l'environnement dans lequel tourne votre logiciel,
que ce soit la version de l'OS, le matériel,
la RAM, l'espace disque disponible, etc.
Les opérations précédemment effectuées
et les données passées à votre code pendant la défaillance.
Si vous rassemblez un maximum de ces données,
vous allez être en mesure de remettre l'application
autant que possible dans le même état invalid
et reproduire ce bug-là.
Qu'est-ce qui se passe si il n'y a pas de reproduction possible ?
Eh ben, si vous arrivez pas à reproduire la défaillance,
ça veut dire que vous n'avez pas mis en place suffisamment d'outils
pour analyser votre application.
Donc ça veut dire qu'il va falloir mettre en place des choses
comme du versioning plus précis de votre code,
un système de sauvegarde des exceptions.
Par exemple, quand on travaille sur des applications mobiles,
si c'est un client à vous qui a eu l'erreur,
l'exception est sur son téléphone.
Donc il faut pouvoir la remonter à un serveur
pour que vous vous ayez accès.
Pareil pour les logs.
Et un monitoring de votre environnement complet.
Ensuite, vous n'avez plus simplement qu'à attendre
que la défaillance se représente
et pour avoir suffisamment d'infos
pour la détecter et la reproduire.
Parfois, on peut avoir des cas où on va avoir une reproduction intermittente.
Si jamais vous n'arrivez pas à reproduire le bug de manière régulière,
mais voilà par la intermittence,
donc des fois ça se passe, des fois ça se passe pas,
même en injectant les mêmes données, etc.
Le même état, ça se peut que le problème
soit induit par un facteur externe à votre logiciel.
Ça peut être votre environnement,
par exemple des autorisations manquantes,
ça peut être des problèmes de réseau,
des problèmes d'espace disque,
des problèmes d'aurodatage du système, etc.
Donc ça, c'est pareil.
Ça revient un petit peu à ce que je disais tout à l'heure
de remettre le logiciel dans le même état
et pareil pour son environnement,
mais ce n'est pas toujours évident.
Si vous n'arrivez pas à reproduire,
enfin que vous arrivez à le reproduire de temps en temps,
mais pas tout le temps,
il faut potentiellement se pencher vraiment
sur l'environnement dans lequel tourne votre logiciel.
Ensuite, il va falloir arriver à isoler.
Ce n'est pas parce que vous avez réussi
à reproduire un dysfonctionnement
que vous comprenez exactement ce qui cloche.
Parfois, le problème, en fait,
il est si inhabituel qu'on n'arrive
même pas à mettre le doigt sur une cause possible.
Donc pour avancer dans votre charge,
vous allez devoir isoler ce dysfonctionnement.
Pour l'instant,
vous avez simplement une application défectueuse,
mais l'objectif est d'isoler le plus précisément
le fichier, la classe, la fonction
ou l'opération qui pose problème.
Pour ça, vous allez suivre
pas à pas le fil d'exécution de votre appli
avec un debugger,
des exceptions ou, à défaut, une série de logs
pour remonter à l'opération précise
où le résultat de sortie ne correspond pas
aux comportements théoriques
données d'entrée que vous avez renseignées.
Dans l'idéal,
vous allez vous retrouver avec une ligne précise
que vous devrez analyser
et inspecter de manière très rigoureuse.
Maintenant que vous avez réussi à isoler votre problème,
il va falloir l'analyser et le cadrer.
En fait, vous allez pouvoir essayer de le tordre
pour en apprendre un peu plus
et surtout essayer de multiplier
le nombre d'états défectueux que vous arrivez à générer.
Par exemple,
une fonction qui renvoie un entier
ne renvoie pas le bon résultat
quand on lui passe en paramètres le chiffre 0.
Pour cadrer ce dysfonctionnement
et comprendre ses limites,
on pourra tester cette fonction
avec des paramètres plus susceptibles
de provoquer une erreur,
comme 0.1,
moins 0.1, 1, moins 1,
nul, undefined, etc.
Si vous arrivez à cadrer votre problème,
ce sera plus facile de poser des hypothèses éclairées
et donc après de faire la correction.
Faire des hypothèses,
les hypothèses c'est des questions ciblées
auxquelles vous n'avez pas encore la réponse
mais dont une d'entre elles
devrait vous mener à la bonne piste
soit en analysant votre code,
soit en cherchant vous-même la réponse
ou en allant demander de l'aide.
Par exemple,
quand je m'inscrit un site,
je reçois pas d'emails,
même si toutes mes données sont envoyées
dans le SDK du service d'envoi d'emails.
Là on va poser des hypothèses
et des moyens de les vérifier.
Par exemple, l'email arrive peut-être dans l'espame.
Ça je peux vérifier par moi-même
si j'ai bien un email dans mes spams ou non.
Peut-être que l'email
n'est jamais envoyé.
Il faut que je vérifie sur la plateforme
du service d'envoi d'emails si
ils ont bien une trace de l'envoi.
Peut-être que le service est temporairement
down.
Donc je peux aller voir dans la page de statut
du service si jamais ils ont un problème
de serveur ou quoi que ce soit.
Ou alors, peut-être que j'utilise
la mauvaise méthode
du SDK. Il faut que je vérifie que ça soit
la bonne méthode et dans ce cas-là
je vais aller voir dans la documentation.
Et pourquoi est-ce
que je reçois pas d'erreur ?
Je vais aller voir sur un forum d'entraide
pourquoi est-ce que je reçois pas d'erreur. Peut-être que j'ai mal
configuré mon SDK et donc
que je devrais recevoir
une erreur de mon SDK
de service d'envoi d'emails.
Donc tout ça, ça va nous servir. On va
faire des hypothèses parce que ça va nous servir
pour la suite et la suite ça va être
rechercher une solution
à notre problème.
On va commencer
notre deuxième étape de la recherche par
expliquer.
En fait pour toutes les hypothèses
auxquelles vous n'aurez pas pu répondre par vous-même
il faudra faire des recherches.
Mais pour ces recherches vous allez
avoir besoin de meilleurs
mots-clés et requêtes.
Parce que pour trouver de l'aide
vous allez avoir besoin
de ces mots-clés et de ces requêtes
pour simplement cibler
votre problème et pas tomber dans tous
les problèmes de la Terre.
Et en fait pour trouver ces mots-clés et cette requête
vous allez
trouver l'explication la plus claire
et complète du problème possible.
Une des meilleures méthodes
pour expliquer un problème correctement
c'est de passer par une phase de rubber, duck, debugging.
Donc ça consiste à expliquer
votre problème à un canard en plastique posé sur votre bureau.
C'est une méthode
qui vous forcera à expliquer votre problème de manière claire
en enlevant les détails inutiles
et qui vous permettra même parfois
de trouver la solution par vous-même.
Parce que votre cerveau pourra détecter
les informations incohérentes que vous pourriez
verbaliser à haute voie.
Dans le cas contraire
ça vous permettra de préparer votre discours
pour demander de l'aide
à un collègue ou une collègue
sur un forum etc.
Si jamais le rubber duck debugging
vous intéresse, j'ai fait un épisode complet
du podcast
que vous pourrez retrouver
sur toutes les plateformes.
Ensuite on va essayer de trouver de l'aide.
Alors dans l'ordre
où est-ce qu'on peut trouver de l'aide ?
On va trouver de l'aide dans la documentation.
On va trouver de l'aide sur GitHub
pour les projets open source
par exemple dans les issues.
On va trouver de l'aide sur les forums
sur Stack Overflow.
On va trouver de l'aide sur les blogs, les sites etc.
On va trouver de l'aide sur les groupes d'entraide
les Slack, les Discord.
Et ensuite, si on n'arrive pas
à trouver notre solution
grâce à ces ressources
on va pouvoir demander à des collègues
des pères, des experts etc.
C'est hyper important
d'essayer de garder un petit peu
cette priorité parce que
c'est là où vous allez pouvoir trouver les réponses
les plus complètes
qui sont données par les gens les plus amèmes
de vous donner les bonnes réponses
et surtout de les trouver le plus rapidement possible.
Parce qu'effectivement si vous demandez
à un ou une collègue, ça peut être très rapide
la réponse peut être bonne
mais vous allez prendre du temps à quelqu'un
et vous le tenter d'aller voir, d'expliquer etc.
ça vous prend du temps aussi. Donc, dans l'idéal
si vous pouvez trouver par vous-même
c'est mieux.
Ensuite, on va
passer à la troisième étape, la troisième
et dernière étape, c'est
la correction. On pourrait se dire
ok, j'ai trouvé ma solution
je corrige et c'est terminé en fait
on va passer par plusieurs sous-étapes
la première c'est l'implémentation
je ne vais pas revenir dessus mais c'est effectivement
réécrire
ou du moins adapter
et comprendre ce qu'on
a trouvé comme solution
et l'adapter à notre code et l'implémenter directement
dans notre code. L'idéal c'est
de pas copier-coller parce que c'est pas
comme ça qu'on apprend le mieux donc c'est de réécrire
cette solution. Ensuite, ça va être
de tester. On a vite tendance à arrêter
la phase de debugging après l'implémentation
du correctif mais en réalité
les phases qui suivent c'est les plus
importantes et c'est celle qui apporte
le plus de valeur à votre code.
Vous allez pouvoir tester
manuellement votre modification avec
plusieurs cas de tests valides
et invalides. Ça c'est un minimum
mais pour être serein
sur la pérennité de votre logiciel
évidemment il faut mettre en place des tests
automatisés donc pour chacun
de vos correctifs mettez en place un
ou plusieurs nouveaux tests pour vous assurer
que votre logiciel ne
ne régressera jamais et que ce que vous avez
corrigé sera accro... j'ai pour toujours.
Ensuite on va ajuster
et nettoyer. Une fois de votre code
il est implémenté et testé
vous allez pouvoir passer à la phase de nettoyage
enlever les logs, éventuellement
du code superflu etc.
Mais ça peut être aussi de rendre votre code
plus performant et plus lisible
et plus adapté et surtout
vous allez être sûr que votre code
fonctionne toujours, que votre correctif
fonctionne toujours parce qu'avant vous avez
implémenté des tests et donc là ça va vous
permettre d'ajouter et nettoyer sereinement
et la dernière étape c'est la documentation.
Alors parfois il arrive
qu'une erreur, ça soit simplement
une faute d'inattention donc
là cette étape elle n'aura pas forcément
de grands intérêts, si
en fait vous aviez simplement
faute de frappe oublié un point virgule
ou quoi que ce soit. Mais si le dysfonctionnement
il vient d'un problème de calcul
d'une imprécision dans la documentation
d'un outil, d'une bizarrerie
de la logique métier dans laquelle
vous travaillez, le mieux c'est
de documenter votre solution. Ça peut
être un simple commentaire, ça peut être
des informations dans un rythmy
ou bien une entrée dans une base de connaissance
interne de l'entreprise. Mais
il faut vraiment penser à pas sauter
cette étape parce qu'en réalité
elle vous sauvera peut-être la vie dans
6 mois. J'espère que
cet épisode de Codegarage vous aura
été utile.
N'hésitez pas si le podcast vous plaît
à laisser 5 étoiles sur la plate-formes
sur laquelle vous écoutez ce podcast
ça aide à être référencé
et donc c'est
vraiment un gros plus pour nous.
Et moi je vous dis à la semaine prochaine
pour un prochain épisode du podcast. Salut !

Les infos glanées

Je suis une fonctionnalité encore en dévelopement

Signaler une erreur

Code-Garage

Découvrons ensemble des sujets passionnants autour du métier de dev et de la programmation en général !
Tags
Card title

Lien du podcast

[{'term': 'Technology', 'label': None, 'scheme': 'http://www.itunes.com/'}]

Go somewhere