Mais pourquoi ça bug ?

Itinéraire d'une erreur de programmation

Un bug a fait le buzz

Bonjour à tous ! Faut que je vous parle car là, on en a gros !

Sire ! ça bug !

J’ai envie de vous le dire : ça ne marche pas !

Alors comment ce bug si embêtant a-t-il pu se glisser dans le logiciel? Et par quelle magie les développeurs réussiront-ils à le corriger?

Cet article parlera un peu de gestion de projet, un peu de technique, un peu d’outils pour faciliter la gestion et la correction de bug. L’article a aussi pour but de recueillir vos expériences en commentaires pour aider toutes les personnes qui se posent les deux questions ci-dessus.

Nous avons programmé

Notre logiciel a besoin d’une nouvelle fonctionnalité. Elle est primordiale cette fonctionnalité. Par exemple, tenez :

Comment les membres de Zeste de Savoir feront-ils pour savoir qu’un nouvel article a été publié ? Que quelqu’un a besoin d’aide dans le forum « Développement Web » ?…

V comme…

Alors on s’est mis à imaginer un système de notifications centralisées et parce qu’on était jeunes et insouciants, on s’est dit qu’il fallait qu’on prépare ça comme il faut pour qu’au moment de développer, ça soit dur comme du béton cette affaire.

Dans la vie de tous les jours, lorsqu’on se lance dans un projet, il est préférable de s’organiser un minimum. En informatique, les développeurs suivent ce même conseil.

Pour imaginer notre « hub » de notification, nous avons donc demandé aux utilisateurs ce dont ils avaient besoin.
Puis, on a spécifié1 tout cela. Puis on a codé. Pour s’assurer que notre code n’était pas mauvais on a testé unitairement. Puis on a qualifié2 tout ça. Enfin, on vous l’a présenté.

Dans le petit monde des gestionnaires de projets, on appelle ça le Cycle en V.

Vous voyez, ça ressemble à un V3

Comme vous pouvez le constater, on a bien une suite de tâches qui part du besoin utilisateur puis se rapproche de plus en plus de la technique. Une fois le développement fait, on s’éloigne de la technique pour voir ce qu’il se passe du point de vue de l’utilisateur.

Aujourd’hui, cette méthode n’est plus systématiquement utilisée – surtout en informatique – car elle est considérée comme trop peu souple.

Si l’équipe de ZDS avait choisi le cycle en V au départ (et les ZEP), c’était pour permettre à chacun de s’exprimer. Mais trop peu de membres non techniques s’exprimaient et trop de débats s’avéraient sans fin entre les développeurs, ce qui a mené à l’abandon de cette pratique pour la suite.


  1. Cela signifie qu’on a écrit noir sur blanc ce que le logiciel doit faire. Plus tard la conception permet de définir comment le logiciel le fera.  

  2. On parle aussi de faire la recette du produit. C’est-à-dire qu’on regarde point par point s’il correspond aux besoins en se plaçant dans la peau d’un utilisateur et non plus d’un développeur. 

  3. Image par ineumann sur http://ineumann.developpez.com/tutoriels/alm/agile_scrum/ 

Ça a buggé

Mais du coup pourquoi ça a buggé ?

Nous avons donc développé notre logiciel. Au fur et à mesure, nous l’avons testé unitairement.

Tester un logiciel unitairement ça veut dire qu’on a pris toutes les briques qui composent le logiciel et qu’on les a testées une a une. C’est un moyen de savoir quelle brique a des défauts.

Car il faut savoir utiliser le bon vocabulaire :

  • Lorsqu’on parle du bout de code qui génère un problème, on dit que c’est un défaut. Un défaut est inclus dans le produit. Parfois il est sans conséquence. Parfois, il en a.
  • Les conséquences, quand elles arrivent sont appelées défaillances ou bug. Une défaillance peut être due à plusieurs défauts.

Quand un développeur débug son logiciel, il essaie de provoquer une défaillance pour ensuite corriger le défaut1.

Tenter de provoquer une défaillance, c’est ce que fera la qualification2.

Souvent le test consistera à regarder ce qu’il se passe quand :

  • il n’y a aucune notification ;
  • il y a une notification ;
  • il y a plusieurs notifications (3 est un nombre sympa pour tester) ;
  • il y a beaucoup de notifications (c’est-à-dire plus que la limite qu’on s’est imposé pour vous les afficher).

Pourtant, il est impossible de tout tester. Parfois parce que le logiciel est vraiment trop complexe pour penser à tout, mais le plus souvent parce qu’entre ce que le développeur pense que l’utilisateur va faire et ce que l’utilisateur fait, il y a une différence.

Un exemple très connu de cette différence

Mais ça bug quand même

Eh oui, il semblerait que tu aies trouvé un cas auquel nous n’avions pas pensé. De ce fait, le défaut est toujours dans le code et ni les tests unitaires, ni la qualification, ni les autres tests (je tease la troisième partie là) n’ont mis à jour de défaillance.

Pour les développeurs, ça sera ce moment qu’ils choisiront pour « ouvrir un ticket ».

Cette phrase signifie qu’ils vont mettre « résoudre le bug » dans leur base de « tâche à faire ». Mais ils ne vont pas le faire n’importe comment.

Ils vont devoir donner quelques informations :

  1. Quelles sont les étapes pour en arriver là ?
  2. Quel est le comportement observé ?
  3. Quel est le comportement désiré ?

Ces trois informations sont primordiales. Si on ne connaît pas les étapes pour reproduire, on ne peut pas à notre tour provoquer la défaillance.

Si on ne sait pas quoi observer, on ne verra même pas la défaillance.

Si on ne sait pas ce qui est désiré, on ne saura pas comment retirer le défaut puisqu’a priori « tout sauf ce qu’il y a maintenant » est possible.


  1. En fait, tous les tests fonctionnent comme ça. Mais ici le but est d’agir comme le ferait un utilisateur. Les tests unitaires tentent de provoquer une défaillance entre ce que le développeur essaie de faire dans sa brique et ce qu’il fait vraiment. 

  2. et je remercie pierre et firm1 qui savent trouver les défaillances du site durant les périodes de bêtatest. Soyez attentif aux messages de la zone dev si vous voulez faire comme eux. 

Et ce fut corrigé !

La correction passe aussi par le test

Armé de cette description, les développeurs ne vont pas tout de suite aller modifier le code pour corriger le défaut. Ils vont écrire un test. C’est-à-dire qu’il vont créer un programme qui va faire fonctionner le logiciel (dans notre cas créer des notifications) puis vérifier que le comportement est celui attendu.

Ce test sera ajouté à l’ensemble des tests qui sont déjà ajoutés dans le projet.

Mais du coup le test échoue, non?

Eh oui, le test va échouer, il faut qu’il échoue. Cela permet de s’assurer qu’on reproduit la défaillance.

Une fois que le test a échoué, le développeur va probablement lancer un programme appelé débuggeur1. Grâce à lui, ils pourront parcourir le programme pas à pas tout en connaissant son état à tout moment.
Cela permettra de comprendre ce qu’il se passe pour s’assurer que le défaut sera totalement corrigé.

Un exemple de suivi pas à pas des bugs

Maintenant que le défaut est identifié et corrigé, on va lancer tous les tests. Cela permet deux choses :

  • s’assurer qu’on a corrigé le défaut (car le nouveau test doit désormais réussir !) ;
  • s’assurer qu’on n’a pas ajouté un défaut lorsqu’on a corrigé le défaut précédent.

Vous vous dites que c’est probablement long de lancer tous les tests vous-même? PAS DE PANIQUE !

Il existe une classe d’outils appelée « intégration continue » (C.I. en anglais). Pour Zeste de Savoir, nous utilisons Travis CI, mais si vous êtes plutôt fan de framagit vous allez probablement utiliser gitlabci2.

En tout cas ces outils permettent de :

  • faire tourner les tests unitaires et de non régression (c’est-à-dire les tests qu’on a ajoutés pour s’assurer qu’on ne cassait pas ce qu’on a déjà réparé) ;
  • faire tourner des outils qui analysent le code pour être certains qu’il sera lisible et bien formaté ;
  • créer des packages – c’est-à-dire une sorte de « zip » qui va contenir le logiciel pour qu’on le déploie sur le serveur final/chez l’utilisateur.

  1. Si vous avez l’habitude d’utiliser ces logiciels et que vous vous demandez comment ça fonctionne, je vous encourage à regarder cette conférence 

  2. mangez-en, gitlabci permet aussi de créer des instances complètes pour tester vos modifications puis les éteints une fois que vous avez terminé les tests :) 


Finalement, pour un développeur, comprendre et corriger un bug, est une activité qui tient plus de la méthode scientifique ou du diagnostic médical que de la magie.

Les tests sont alors le moyen le plus efficace pour les développeurs de s’assurer qu’ils ont corrigé le problème sans en créer d’autres.

Merci à Gabbro pour ses retours et à qwerty pour sa validation.

22 commentaires

Oui le but etant de démystifier le phénomène "ça bug" puis sa correction (et le temps que ça prend), je n’ai pas été trop technique.

artragis

Peut-être dire qu’il y d’autres types de tests que les tests unitaires, comme les tests d’intégration ou les tests end-to-end (qui sont « drôles » à voir pour des sites je trouve).

+0 -0

Je pense qu’il serait bon aussi de définir ce qu’est un bug. L’article commence sur le constat qu’un bug s’est produit, sans expliquer en quoi cela consiste, comment ça se manifeste, ce que ça a de différent d’un plantage, etc.

Je pense qu’il serait bon aussi de définir ce qu’est un bug. L’article commence sur le constat qu’un bug s’est produit, sans expliquer en quoi cela consiste, comment ça se manifeste, ce que ça a de différent d’un plantage, etc.

en fait c’est dit dans l’article.

Car il faut savoir utiliser le bon vocabulaire :

  • Lorsqu’on parle du bout de code qui génère un problème, on dit que c’est un défaut. Un défaut est inclus dans le produit. Parfois il est sans conséquence. Parfois, il en a.
  • Les conséquences, quand elles arrivent sont appelées défaillances ou bug. Une défaillance peut être due à plusieurs défauts.

Et comme un plantage EST un bug, je vois pas trop ce que tu veux dire.

Peut-être dire qu’il y d’autres types de tests que les tests unitaires, comme les tests d’intégration ou les tests end-to-end (qui sont « drôles » à voir pour des sites je trouve).

il est vrai que j’évoque les tests unitaires, mais je n’ai pas restreint le champ des tests à cela. "écrire un test", surtout quand on a un scénario, ça ressemble beaucoup à un test d’intégration, voire end to end.

Le but est d’écrire un article accessible et donc pas trop long. On a déjà 1300 signes là, c’est la borne haute pour de la vulgarisation, je pense. Sinon on passe au format tuto et là faut expliquer comment utiliser les outils de CI par exemple.

+0 -0

en fait c’est dit dans l’article.

Ben pas vraiment je trouve, c’est pas très clair.

Et comme un plantage EST un bug, je vois pas trop ce que tu veux dire.

artragis

Non, un plantage peut être dû à un bug, mais ne l’est pas nécessairement. Si tu débranches un périphérique de stockage pendant une copie sur celui-ci, ça plante, mais je ne vois pas en quoi il serait question de bug.

Et c’est bien pour ça que je trouve que ce n’est pas très clair dans cet article.

Non, un plantage peut être dû à un bug, mais ne l’est pas nécessairement.

si si, un plantage est un bug. Il est dû à un ou plusieurs défauts (c’est ce qui est dit dans l’article) mais c’est bel et bien un bug.

Si tu débranches un périphérique de stockage pendant une copie sur celui-ci, ça plante, mais je ne vois pas en quoi il serait question de bug.

C’est pourtant simple : si tu t’attends à ce que la copie ne fasse que s’arrêter avec un simple message "le périphérique a été perdu durant la copie", alors un plantage est une défaillance ou en langage courant un "bug".

+0 -0

C’est pourtant simple : si tu t’attends à ce que la copie ne fasse que s’arrêter avec un simple message "le périphérique a été perdu durant la copie", alors un plantage est une défaillance ou en langage courant un "bug".

artragis

En fait, de mon point de vue, s’arrêter avec un simple message « le périphérique a été perdu durant la copie » est un plantage (et non un bug, c’est un comportement prévu par le programme), c’est sûrement la source de notre incompréhension.

Le programme n’a pas réalisé la tâche qui lui incombait, il n’a pas pu à cause de divers problèmes externes, et il s’est éteint. Une erreur s’est produite et il a planté.

Mais au niveau du programme en lui-même, tout s’est déroulé correctement : une écriture a remonté une erreur, il a identifié qu’il n’était plus possible d’accéder au périphérique, il s’est coupé en indiquant le message d’erreur correspondant.

J’ai compris la remarque d’entwanne ainsi : si le ventilateur du processeur lâche, le système d’exploitation va éteindre la machine pour la préserver suite à la montée en température. Pas de bogue dans ce programme. Le PC va s’éteindre comme il se doit. Il y a pourtant eu un dysfonctionnement : l’utilisateur demandait à regarder des vidéos de loups trop mignons, son PC s’est éteint – ce n’est pas le comportement voulu par l’utilisateur (même si c’est celui souhaitable).

Il y a eu plantage, et pourtant aucun logiciel ne bogue. Soit tu considère qu’on a affaire à un bogue matériel, et alors on peut en conclure que tout plantage est un bogue, mais je ne suis pas sûr que ce soit la définition habituelle, soit on a un cas de plantage sans bogue.

+2 -0

C’est effectivement assez vrai mais je me pose cette question
Utilise-t’on les bon mots pour désigner un erreur du au programme et pour désigner une erreur du à des faits externes au programme?
Car pour moi un bug est interne au programme et un plantage est du à un fait externe au programme(fait qui n’est pas forcement en lien avec le programme.
ex: l’utilisateur ne rentre pas ce qui est attendu, le programme s’arrête. -> erreur interne au programme car l’utilisateur doit bien rentrer quelque-chose
Quelqu’un débranche le ventilateur du cpu(très mauvaise idée :colere2: ) l’OS éteint la machine. -> erreur externe au programme car si le programme se stop ce n’est pas du au code du programme mais à l’OS)

Utilise-t’on les bon mots pour désigner un erreur du au programme et pour désigner une erreur du à des faits externes au programme?

dans les deux cas si tu observes un comportement qui diffère de ce que tu attendais, alors c’est une défaillance. Lorsqu’on est dans le cas d’un logiciel on appelle ça un bug. Pour ce qui est du matos, on peut avoir une défaillance de conception (par exemple on n’a pas prévu d’arrêt d’urgence) ou de fabrication (vice caché) mais aussi une défaillance d’usure (exemple du ventilateur qui se désaxe petit à petit puis finit par lâcher).

En soi, si tu as un ventilo qui est débranché à la main, on n’a pas de défaillance, au contraire tous les systèmes fonctionnent !

Par contre si le ventilo s’arrête à cause de l’usure, tu es bien content que le circuit détecte automatiquement le changement d’impédance et en profite pour killer le proco. Et là la défaillance se situe côté ventilo, pas côté carte mère. Cela reste néanmoins une défaillance.

Franchement, j’en sais rien. :-° J’ai essayé de comprendre la différence que faisait entwanne entre plantage et bogue, c’est tout.

Cette discussion montre pour moi que la question « qu’est-ce qu’un bogue » n’est pas aussi facile qu’elle en a l’air. :P

+1 -0

D’expérience, la définition du bug est intrinsèquement liée au ressenti de la personne qui utilise le produit. En particulier, et c’est là que c’est important, ça dépend de si on demande à l’utilisateur final ou au développeur :

  • Le développeur va considérer comme bug n’importe quel comportement dans lequel le logiciel ne donne pas le résultat qu’il est censé donner selon les spécifications.
  • L’utilisateur final, surtout non informaticien, va avoir tendance à cataloguer n’importe quel comportement que lui-même, en tant qu’utilisateur, n’a pas prévu en tant que bug.

Donc, l’utilisateur va considérer comme bug des choses qui n’en sont pas, comme par exemple :

  • Des comportements tordus, mais dont c’est l’implémentation correcte parce que la spécification elle-même est étrange (et c’est plus fréquent qu’il n’y parait).
  • Des comportements inhabituels provoqués par des circonstances exceptionnelles (comme par exemple l’arrachage d’une clé USB en pleine écriture). C’est d’autant plus vrai si l’utilisateur n’a pas de notions techniques et donc ne comprends pas la circonstance et ce qu’elle peut impliquer.
  • Des modifications volontaires et spécifiées d’interface ou de procédure entre deux versions d’un logiciel (cf la notion de résistance au changement).

À noter qu’un bon support utilisateur, c’est aussi comprendre, prendre en compte et résoudre (par un correctif, un accompagnement au changement, une explication) les problèmes remontés par les utilisateurs qui n’en sont pas d’un point de vue technique. Mais ça nécessite que le développeur ne parte pas du principe hélas très commun qui consiste à dire que l’utilisateur est un con qui ne comprends rien à rien.

Juste pour information, j’utilise les définition de "défaillance" et de "défaut" qu’on trouve dans le glossaire ISTQB (international software test and quality board). Si vous les trouvez gênantes, je peux le comprendre, mais je trouve qu’elle sont plutôt claires en fait.

Pour reprendre l’exemple de l’arrachage de périphérique et expliquer un peu mieux mon point de vue, je viens de repenser à Pokémon.

Sur les premières versions, sur game boy, il était possible d’échanger des Pokémons entre deux cartouches via un câble link reliant les deux consoles.

Imaginons (à tout hasard) que nous débranchions le câble pendant l’échange. Le comportement normal (attendu) serait que le transfert plante : on arrête tout, l’échange échoue et on en informe les utilisateurs avec un beau message d’erreur. Si cela provoque un clonage du Pokémon, on peut dire que l’on a affaire à un bug. Plutôt que de planter, le programme a mal réagi à un événement extérieur et provoqué une situation qui ne devait pas arriver.

D’ailleurs, c’est un peu HS mais si vous avez envie de rigoler et d’apprendre des choses, il existe un recueil d’histoires vraies et rigolotes sur le sujet qui m’a bien fait marrer.

Beaucoup de ces histoires sont assez techniques et pas très accessibles, mais d’autres comme celle de l’email qui ne va pas plus loin que 800 Km devraient être compréhensibles par n’importe qui qui comprend un peu l’anglais.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte