Le débogage

Posté le 21 août 2015 - Astuces pour développeurs - Par golgotha - Proposer une correction

Même en étant un développeur appliqué et consciencieux il est difficile d'échapper aux bugs. Être capable de résoudre ses propres bugs est un atout essentiel pour être efficace. Aussi, je vous propose aujourd'hui d'aborder quelques méthodes de résolutions qui ont fait leurs preuves durant mes années d'expérience.

Le 50/50

Si vous travaillez sur un gros projet ou un script relativement long et qu'il plante, et que vous ne savez pas pourquoi ni comment, la mauvaise chose à faire est d'essayer de résoudre le problème en tâtonnant et en essayant de modifiant le code de manière erratique.

La première chose à faire est d'identifier l'origine du problème.

  • S'il s'agit d'une erreur de syntaxe, il suffit de se référer à l'erreur qui est donnée par le langage et de chercher autour de la ligne indiquée. Attention cependant avec ce type d'erreur, en effet elles sont souvent provoquées par des oublis faits précédemment. Il vous faudra donc rechercher dans les lignes situées au-dessus de la ligne indiquée par l'erreur.
  • S'il s'agit d'une erreur de logique, on va chercher à comprendre l'origine du problème. Pour y arriver, il est très important de bien comprendre son code afin de pouvoir reproduire dans sa tête le déroulement de l'algorithme. Si vous vous retrouvez perdus et que vous avez du mal à comprendre ce que fait réellement votre script, il ne faudra pas hésiter à déboguer les variables au fur et à mesure (avec des var_dump() en PHP ou des console.log() en JavaScript par exemple). Le but est d'essayer de comprendre comment l'algorithme se déroule et ainsi comprendre quelle partie est à l'origine de l'erreur.

De manière générale, lorsque l'on écrira un script, on cherchera à isoler au maximum les différents blocs en utilisant des fonctions ou des objets. En effet, une fonction relativement courte sera beaucoup plus facile à déboguer qu'une fonction contenant des centaines de lignes. En plus, si plus tard vous souhaitez mettre en place des tests unitaires, tester des fonctions avec une logique simple sera beaucoup plus aisé.

L'appel à un ami

Si vous êtes bloqué sur un problème depuis trop longtemps, il arrive souvent que vous ne soyez pas en mesure de changer de perspective, ce qui vous empêche du coup de résoudre le problème. Une bonne solution est souvent de marquer une pause (c'est un bon moment pour faire une pause café par exemple), de passer à autre chose. En revenant sur le problème l'esprit reposé, vous aurez alors une nouvelle perspective est une nouvelle solution peut apparaître (le fameux moment "ah je suis con c'est évident !").

Ce que vous pouvez aussi faire, c'est demandé à un collègue de regarder votre problème. N'étant pas le nez dans le code, il viendra avec une approche nouvelle vis-à-vis de votre problématique. Ce qui peut permettre d'amener rapidement à la solution.

L'avis du public

L'avantage de vivre en 2015, c'est que si on n'a pas d'amis à portée de main, grâce à Internet on a accès à un très grand nombre de points de vue différents. Attention cependant, pour éviter de vous manger un "va chercher sur Google", il est impératif de respecter quelques règles lorsqu'il s'agit de demander à Internet une solution à nos problèmes.

  • Si possible on privilégiera les tchat ou channel IRC pour des questions très techniques et très spécifiques.
  • Prenez le temps de poster votre question à l'endroit approprié ou sur le forum approprié. Vous ne poserez pas une question spécifique à PHP sur un forum principalement destiné au JavaScript par exemple (ça parait con dit comme ça, mais ça arrive très souvent).
  • Éviter à tout prix des formules du style "je veux", "j'ai besoin", "j'exige !". Rappelez-vous que les gens font ça pour aider.
    • Vous n'êtes pas le seul à poster sur le forum en question, du coup essayez de détailler au maximum votre problématique et si possible limitez la quantité d'information que vous donnez au strict nécessaire. Par exemple, essayez de montrer la partie de code qui selon vous est à l'origine du problème. Évitez de balancer une question du style "ça ne marche pas pourquoi ?" avec 800 lignes de PHP derrière et sans donner de message d'erreur.

Il faut distinguer trois types de forums techniques qui vous aideront, mais sont à aborder de manière différente. Premièrement les forums francophones : vous y trouverez de l'aide rapidement et facilement, sur des problèmes d'ordre général. Si vous n'êtes pas à l'aise en anglais, c'est l'endroit idéal.

Deuxièmement, les forums anglophones (type stackoverflow). Bien que le niveau technique des forums français soit déjà très bon, vous trouverez des ninjas et des gourous du développement sur ces forums. Si vous avez un problème très pointu, je vous conseillerai d'y jeter un oeil. Un niveau d'anglais technique moyen est cependant nécessaire.

Dernièrement, vous trouverez aussi des forums spécifiques (et officiel) à certaines technologies, type oracle, debian, PHP... Ces forums combinent souvent niveau technique très poussé et anglais. C'est l'endoit idéal pour parler d'une erreur de compilation de la version 5.1.2 d'un logiciel sur un kernel 3.14. Attention tout de même, poster sur ce genre de forum reviens un peu à entrer dans un saloon en plein western, il vaut mieux prendre des gants pour ne pas être rembarré par le barman.

Les outils

Pour bien chasser les bugs, il est impératif d'avoir les bons outils ! Même s'il est possible de trouver manuellement une erreur en affichant des consoles.log() ou des alert() un peu partout, la plupart des navigateurs et des langages intègrent des outils permettant de débloquer plus facilement une application.

CSS

Même si le CSS n'est pas un langage de programmation à proprement parler, il a cette capacité extraordinaire à produire une quantité quasiment infinie de bugs (avec notamment des éléments qui ne se placent pas correctement ou encore des styles qui n'affectent pas les bons aux éléments). Heureusement pour nous, tous les navigateurs modernes intègrent une console, accessible en appuyant sur F12, qui nous permet de voir en un clin d'œil comment le navigateur interprète notre page.

La console chrome, votre meilleur allié dans la chasse aux bugs

Dans le cas de la console chrome par exemple, c'est le panneau élément qui regroupe l'ensemble des informations dont vous avez besoin. Pour comprendre comment votre CSS s'applique sur un élément, il vous suffit de le sélectionner et de regarder les propriétés qui lui sont affectées dans le panneau situé à droite. On peut aussi sélectionner l'onglet computed afin de voir l'ensemble des règles qui affectent notre élément (cet onglet est plutôt pratique, car il permet de voir les règles qui affectent notre élément même de manière indirecte). On notera aussi la possibilité de modifier directement des valeurs dans cette console, ceci afin de faire des essais avant de reporter nos modifications dans notre CSS.

Le Javascript

Comme pour le CSS, on va utiliser de manière quasi permanente la console intégrée dans le navigateur. En effet dans l'onglet source, il est possible de voir les différents scripts qui sont importés par notre page, mais aussi de placer des points d'arrêt. Ces points d'arrêt vont permettre d'arrêter le script à un moment donné, et d'inspecter la valeur des différentes variables. Une fois arrêté sur un point d'arrêt, il sera possible de demander au navigateur de continuer l'exécution du script pas à pas, ceci afin de comprendre comment se déroule notre algorithme et d'identifier les éventuels problèmes.

Voici un exemple de point d'arrêt

N'hésitez pas à utiliser ces points d'arrêt afin d'avoir un aperçu du fonctionnement de vos scripts, et de comprendre pourquoi vous obtenez un résultat inattendu.

En plus de la partie source et console, qui va vous servir à identifier les problèmes liés à votre JavaScript, vous pouvez aussi utiliser l'onglet réseau qui vous permettra de voir les différents appels HTTP faits par votre application. Cet onglet servira surtout si vous utilisez beaucoup d'Ajax, car il vous permettra de voir les requêtes qui sont faites par votre navigateur auprès des différents serveurs. Cela peut s'avérer utile pour identifier les en-têtes, mais aussi voir le contenu renvoyé par votre serveur.

PHP

Dans le cas de PHP on rencontre 3 types d'erreurs :

  • Une erreur de syntaxe, dans ce cas-là, comme vue précédemment, on va chercher quelques lignes au-dessus de la ligne indiquée pour identifier notre problème (en général une parenthèse mal fermée)
  • Les exceptions sont des erreurs générées par le code lorsque l'on rencontre un problème inattendu. Dans ce cas-là, il suffit en général de lire l'erreur afin d'en comprendre l'origine. Si jamais vous n'avez jamais rencontré l'erreur en question, il ne faudra pas hésiter à utiliser un moteur de recherche afin de voir si d'autres personnes ont rencontré le problème. Pensez à retirer de votre recherche tous les éléments spécifiques à votre application, afin de copier dans le moteur de recherche une erreur générique du style header alraeady sent PHP (mettre le langage en question permet d'obtenir des résultats plus performants)
  • Une erreur de logique, avec un script qui ne fonctionne pas comme on l'attend. Même s'il existe des outils qui permettent de mettre en place des points d'arrêt, comme en JavaScript, ils sont en général très difficiles à installer et à faire fonctionner efficacement. Du coup on aura souvent recours à la bonne vieille méthode du var_dump($variable); die(); afin de stopper l'exécution d'un script un moment donné et d'analyser le contenu des différentes variables. Certains Frameworks proposent des versions un petit peu plus poussées du die par exemple dd() pour Laravel, ou encore debug() pour CakePHP.

Ruby / Rails

Dans le cas d'une application Ruby on Rails on va souvent rencontrer des exceptions,; Le problème c'est que la page d'erreur par défaut fournie par le Framework est relativement Light.

L'erreur par défaut de Rails

Si on souhaite que le Framework nous donne un peu plus d'informations sur les erreurs rencontrées on peut passer par une gemComme par exemple Better Errors

group :development do
    gem 'better_errors'
    gem "binding_of_caller" # 
end

Cette gem vous permettra d'obtenir des erreurs beaucoup plus jolies qui vous donneront des informations plus précises sur les erreurs rencontrées.

Si vous avez besoin de déboguer votre script de manière plus fine, pour comprendre pourquoi un morceau de code ne s'exécute pas comme vous l'attendez, il est aussi possible d'installer la gem pry-byebug. Cette gemme vous permet ensuite de placer un point d'arrêt dans votre code rubis, et de pouvoir le déboguer pas à pas depuis la console

def some_method
  binding.pry          # Execution will stop here.
  puts 'Hello World'   # Run 'step' or 'next' in the console to move here.
end

Automatiquement, lorsque ce code sera exécuté, la console rails va s'arrêter et va vous permettre de naviguer pas à pas dans votre code.

Et côté serveur ?

Malheureusement, certaines erreurs seront encore plus loin dans votre stacks, et certains problèmes peuvent apparaitre directement sur les applications fonctionnant sur votre serveur. Les erreurs les plus répandues sont souvent des erreurs de configuration, par exemple vous êtes en train d'essayer de mettre en place un système de réécriture d'URL, et lorsque vous sauvegardez votre htaccess vous tombez sur une erreur. Afin d'identifier le problème plus rapidement il est impératif de voir les erreurs. Par défaut, les serveurs sont configurés pour n'afficher qu'un minimum d'information publiquement lorsqu'il y a une erreur, ceci afin d'éviter les problèmes de sécurité. Du coup, il vous faudra fouiller dans les logs pour obtenir un indice sur ce qui a pu causé l'erreur.

Dans le cas d'un hébergement mutualisé certains hébergeurs comme OVH vous permettent d'accéder à ces logs directement depuis votre FTP.

En revanche, si vous êtes sur un serveur dédié et que vous avez la main dessus, il vous faudra analyser les logs manuellement. Heureusement, Linux est bien pensé et tous les logs se situent au même endroit /var/log/.... Ces fichiers peuvent contenir des tonnes et des tonnes de lignes, du coup on utilisera la commande tail qui permet d'afficher les dernières lignes d'un fichier. Voici un exemple de commande dans le cas d'une recherche d'un problème sur apache

tail -f /var/log/apache2/error.log
# -n 30 permet d'indiquer combien de ligne on souhaite
# -f permet de laisser le fichier ouvert, et du coup de voir les nouvelles erreurs arriver en live

Il sera utile d'apprendre à utiliser certaines commandes propres à la visualisation de processus serveur comme top ou htop dans le cas d'un processus qui ne se lancerait pas correctement, mais aussi d'outils d'édition comme nano ou encore vi qui permettent d'éditer rapidement des fichiers de configuration pour corriger éventuels problèmes. Enfin une commande indispensable, mais qui peut se rapidement s'avérer complexe grep un élément particulier dans un fichier de log.

Bonne chasse au bugs !