Les aventures de Mokona au pays des chonchons

Aller au contenu | Aller au menu | Aller à la recherche

jeudi 4 décembre 2008

Avoir confiance en son code (et en celui des autres)

Il est là, le bug, celui que tout le monde redoutais. Il se cache, il arrive parfois, pas tout le temps. Entre les programmeurs, la suspicion s'installe : c'est certainement dans le code d'untel !

Les pistes sont explorées une à une, parfois plusieurs fois. Il est 23h et la version livrable doit l'être absolument demain à 10h. Les machines de compilation sont silencieuses, elles attendent l'archivage salvateur pour démarrer leur production.

Et soudain, ça y est ! Bidule à trouvé. Bidule a corrigé un bug et le crash n'apparaît plus. Enfin, il est possible qu'il n'apparaisse plus car, forcément, la nature de celui-ci étant aléatoire, le doute subsiste. Mais la correction semble un bon candidat.

L'erreur ? Oh, une broutille. Une méthode qui, dans le cas d'un paramètre nul et pour éviter une division par zéro n'effectue pas la division et laisse le résultat indéterminé [1]

Le bug est-il vraiment corrigé ? Peut-être, peut-être pas. Peut-être était-ce un effet de bord. Les plus sceptiques vont se coucher avec un doute subsistant. Est-ce que ce module là a bien été testé ? Oui, machin l'a faut. Enfin je crois. Ah ! Pourvu que la version tienne !


Dans cette petite histoire, vécue par de nombreux programmeurs, le premier problème est le doute, le manque de confiance. Est-ce que les collaborateurs ont bien fait leur boulot ? Est-ce que le programme fait ce qu'on lui demande ? Est-ce que la correction de bug est la bonne ?

J'avais déjà parlé précédemment d'une manière de passer des contrats avec votre programme (les assertions). C'est une manière d'être certain qu'au moment de l'exécution, certaines conditions sont respectées. Les assertions statiques peuvent aussi vérifier certaines conditions au moment de la compilation.

Les assertions sont intéressantes et utiles. Mais elles présentent un défaut : elles ne vérifient la condition que si le code est exécuté et il n'est pas dit qu'elles ne se déclenchent pas dans certaines situations. C'est même ce qu'on attend d'elle : leur déclenchement en cas de situations malvenues.

C'est un premier pas dans la confiance dans son code : en passant un contrat, on écarte des cas.

Mais est-ce qu'on ne pourrait pas aller un cran plus loin et s'assurer que tout le code est exécuté à un moment où à un autre ? On peut imaginer un programme qui s'assure que tous les cas du programme à tester sont executés. L'ennui est que les programmes sont généralement complexes et les entrées innombrables.

Tests Unitaires

Une idée est alors de considérer qu'un programmme auquel on peut faire confiance est avant tout un programme basé sur des composants auxquels ont peut faire confiance.

C'est ici qu'interviennent les tests unitaires. Les tests unitaires, comme leur nom l'indique, sont des tests qui testent une chose à la fois. En couvrant chaque « chose » du programme indépendamment en s'assurant que les sorties sont conformes à ce à quoi on s'attend en fonction des entrées, on a une bonne base de confiance.

Besoin d'un exemple ? Prenons une classe qui maintient une liste de valeurs et est capable de donner certaines statistiques sur ces valeurs. La valeur maximum et la moyenne par exemple.

Les tests unitaires couvrant cette classe pourraient vérifier ces choses [2] :

  • à la création, la méthode getNumberOfValue() renvoie 0 ;
  • à la création, la méthode getAverage() provoque une exception ;
  • à la création, la méthode getMax() renvoie la valeur minimale possible pour le domaine des valeurs ;
  • à la création, après avoir ajouté une valeur, getNumberOfValue() renvoie 1 ;
  • à la création, après avoir ajouté une valeur, getMax() renvoie cette valeur ;
  • à la création, après avoir ajouté une valeur, getAverage() renvoie cette valeur ;

Etc...

Ici, certains prennent peur. N'y a-t-il pas plus de code à écrire pour tester que dans la classe elle-même ? Oui. Dans ce cas exemple, c'est vrai. Et c'est vrai aussi dans la pratique dans un certain nombre de cas. Mais est-ce un mal ? Quelqu'un sans gros passif peut le penser. Quelqu'un qui a passé des nuits entières sur un bug idiot comprend vite que le temps passé à écrire les tests est gagné sur du temps qu'on ne passe pas plus tard à la recherche des bugs.

Ce n'est pas forcément évident à accepter car le temps qui n'est pas passé dans le debug est difficilement quantifiable.

Avec quoi tester ?

Il existe des frameworks de tests unitaires dans à peu près tous les langages de programmation. Pour le C++, vous pouvez en trouver quelques-uns que j'avais testé dans cet article. Pour Java, le plus connu est JUnit. Pour C#, NUnit.

Les frameworks sont généralement dotés de fonctions qui vérifient des résultats et d'une manière de signaler que du code est du code de test. Lorsque les tests sont lancés, chaque test est exécuté et une erreur lors d'une vérification provoque un message contenant des informations de ligne et un message indiquant l'erreur.

Par exemple, une erreur pourrait ressembler à cela :

testclass.cpp: 130 ; Test failed "TestGetMax" , expected 3 but got 1.

Tester pour développer

Tester a posteriori est intéressant. Et si l'on testait avant d'implémentation ? Idée étrange de prime abord, c'est une étape supplémentaire pas bête du tout. En anglais, le "test driven development" consiste donc à commencer par écrire le code de test avant ce que l'on test.

Forcément, lors des premiers lancements de tests, il y aura beaucoup d'erreurs. Mais pourvu que les tests soient bien écrits, on s'assure que lorsque tous les tests passent, l'implémentation testée fait ce qui lui a été demandée.

Un savoir faire

Tester ses implémentation ou encore tester avant d'implémenter ne sont pas des choses naturelles en programmation lorsque l'on débute. Ce ne sont pas non plus des choses, à ce que j'en sais, qui sont enseignées ou tout du moins appliquées après avoir été enseignées.

La plupart de temps, il faut avoir été confronté aux problèmes que ces méthodes règlent (ou tout du moins adoucissent) pour comprendre leur intérêt.

C'est aussi un savoir faire. Quoi tester, comment tester, comment bien isoler la classe à tester dans un langage objet, tester efficacement et complètement,... Mais c'est un outil qui se révèlera utile. En d'autres mots : ça vaut le coup de s'y lancer.

Un graal ?

Je n'ai pas mis les tests unitaires et le « test driven development » (TDD) dans ma série « Ceci n'est pas le Graal ». Je ne pense pas que le TDD ait suivi le processus par lequel je définis un faux graal. Peut-être parce que ce n'est pas tant utilisé que ça. Peut-être parce que les utilisateurs de TDD sont convaincus et n'ont pas été forcés d'en faire. Peut-être parce qu'il n'y a pas eu un énorme buzz autour de cette méthode de développement.

Ou peut-être parce que la promesse est tenue et n'est pas sur-évaluée. Le test permet une chose : une confiance accrue dans le code. C'est le sujet de l'article. En surveillant qu'une modification ne provoque pas des régressions. En s'assurant que ce qui a été programmé fait bien ce à quoi on s'attend.

Cette confiance permet même d'oser plus. Qui n'a pas en tête le moment où un sous-système d'un programme est arrivé à un point où l'on voudrait le changer, mais où l'on n'ose pas, de peur de tout casser. Ou alors il faudra tester manuellement, mais sans vraiment être sûr de tous les cas. Ou alors il sera temps d'ajouter des tests unitaires, mais les faire a posteriori et bien après l'implémentation entraine le risque d'oublier des cas. Avoir développé en TDD assure que les tests sont déjà là lorsqu'on en a besoin.

Le TDD est vraiment quelque chose que je conseille d'essayer. Je conseille aussi de commencer petit, avec des petites classes ou fonction que l'on a déjà implémentée, que l'on connait bien et donc pour lesquelles on a une bonne idée de ce qu'il y a à tester. Puis d'aller un peu plus loin à chaque fois.

Notes

[1] ce cas est assez classique pour être neutre dans cet article. Il aurait pu s'agir d'un vecteur non normalisé, d'un dépassement de tableau, d'un pointeur fou,...

[2] ce que l'on vérifie dépend du design de la classe.

lundi 27 octobre 2008

Je me suis fait croquer

Ce matin, dans le train m'amenant au boulot, un jeune homme se met en face de moi puis, quelques instants après, sort un cahier de croquis. Cette activité pour un voyageur ne fait pas partie des plus courantes, je lève donc un sourcil curieux. Quelques mots sont jetés sur une des pages que je ne cherche pas à lire. L'autre page est vierge.

Je retourne à mon livre.

Une station plus tard, je jette, tout en tournant une page, un regard vers le cahier. Celui-ci est à présent parcouru par un feutre qui, d'après les mouvements, est en train de faire un croquis. Je me recale un peu, façon peu discrète pour jeter un coup d'oeil. C'est encore très brouillon et je ne distingue rien, d'autant plus que le dessinateur relève légèrement le cahier ; façon peu discrète de cacher ce que l'on fait.

J'esquisse un sourire : si ça se trouve, je suis le sujet du croquis.

Je replonge dans mon livre.

Entre les paragraphes, je jette un regard. Les formes se précises et je reconnais le front dégarni, les cheveux en arrière sur le dessus de la tête, la tête penché qui mettent les yeux au dessus des verres des lunettes et surtout, cette position du bras qui fait que le poing remonte la joue.

En effet, c'est moi. Dans la position de lecture appuyé contre la fenêtre, lorsque le croqueur a pris place dans la rame quelques stations plus tôt. Je ne peux juger à l'envers de la ressemblance exact, mais la pose, l'allure général y est.

L'homme referme le cahier et sort.

Sentiment étrange que d'être couché sur papier, spontanément et sans permission par un inconnu. Mais demander la permission, si cela avait été plus poli, aurait fait perdre à ma pose cette spontanéité. L'inconnu lui-même savait qu'il pouvait gêner, sa volonté de toujours mettre son travail hors de mes yeux le trahissait.

Mais au final, je ne suis pas mécontent. J'aurais été agacé si j'avais été pris en photo. Ici, le croquis me représente sans être exactement moi. Et cette façon de croquer spontanément est un exercice chez le dessinateur que j'admire un peu.

Un collègue m'avait, il y a quelques années, dessiné de profil en quelques traits. Une évocation de ma personne devant son ordinateur. Je ne sais pas si j'ai encore le dessin, mais j'avais trouvé cela amusant.

Si un jour par un hasard extraordinaire, l'inconnu croqueur venait à passer par cette page, j'aimerais qu'il contente ma part narcissique et m'envoie une copie du dessin.

lundi 25 août 2008

Train flou

Qu'arrive-t-il lorsqu'on a un appareil réglé en « tout automatique » dans la poche, et bébé dans les bras et que l'on entend au loin la sonnerie d'un passage à niveau qui se ferme ?

Poser le bébé par terre pour prendre le temps de régler l'appareil n'est pas une option.

Qu'est-ce que cela donne quand en plus, au moment de viser, on s'aperçoit qu'on a le soleil dans les yeux ?

Ça :

Train flou

mercredi 6 août 2008

Donjons et Dragons, 4ième édition, mon avis

Il y a un tout juste deux mois maintenant, je parlais de la sortie de Donjons et Dragons 4ième édition. Un mois plus tard, les livres lus, les forums parcourus et le jeu joué, voici ma revue de la bête.

Lire la suite

mardi 8 juillet 2008

Ceci n'est pas le Graal : les Design Patterns

Les Design Patterns (abréviation DP) sont présentes dans l'industrie, ont droit à des articles innombrables, des pour, des contre, suscitent l'excitation des débutants... Voilà encore un bon candidat pour les faux Graals.

Lire la suite

lundi 9 juin 2008

Passage à Ubuntu 8.04

J'avais chargé la version d'installation [1] d'Ubuntu 8.04 à sa sortie, mais je n'avais pas encore pris le temps de regarder. Puis je me méfie toujours un peu des mises à jours, surtout que je n'avais pas de raison particulière d'effectuer celle-ci si ce n'est d'être... à jour.

J'avais aussi laissé passé la déclaration des impôts sur le revenu. Il vaut mieux éviter d'avoir une machine en panne juste à ce moment là, même s'il est toujours possible de faire migrer le certificat sur une autre machine, ça reste un petit stress pas vraiment nécessaire.

Il m'était aussi revenu quelques expériences négatives sur cette mise à jour. Renseignements pris, c'étaient souvent une première expérience de mise à jour complète du système et les problèmes étaient minimes et résolus rapidement.

Donc, samedi, j'appuie sur le bouton magique : mise à jour vers version 8.04.

Cela va être très rapide : le programme me signal qu'il n'a pas assez de placer sur le disque pour charger les paquets d'installation. Je regarde... oui, pas faux. Bon, dommage mais j'ai autre chose à faire.

Le lendemain dimanche, je jette un coup d'œil dans le gestionnaire de paquets à la rubrique des paquets détectés comme obsolètes et pouvant être effacés sans risque. J'y trouve effectivement 4 ou 5 version d'anciens noyaux Linux, de vieux splash screens. Je n'ai vraiment fait de ménage depuis ma première installation d'Ubuntu, la 5.04, il y a donc 3 ans. Le ménage libère 500 Mo. Ah quand même.

Je relance la mise à jour et là, ça ne râle plus. Seul petit soucis, du a une bidouille : j'ai monté l'iso d'installation sur un répertoire locale et je l'ai déclarée à apt. Mais visiblement par comme il faut, car l'installation me demande d'insérer le CD dans le lecteur CD-Rom. Pas grave, je remonte l'image sur le chemin du CD-Rom et le programme d'installation n'y voie que du feu.

Le programme m'annonce alors qu'il doit charger près d'1 Go de fichiers. Je le laisse tranquille et je vais faire autre chose.

Deux heures plus tard, la mise à jour en elle-même démarre. Il y a moins de questions que d'habitude, et c'est tant mieux. La configuration des packages est toujours la partie un peu pénible car il faut rester dans le coin pour accepter (ou refuser) quelques modification des configurations. Il y a peut-être moyen de faire ça automatiquement et d'un coup, mais je ne connais pas ce moyen.

Les surprises au redémarrage :

  • le driver de ma carte graphique a été remis sur un driver libre. La surprise, c'est que le DRI est tout de même activé, alors que ce n'était pas le cas auparavant. Ubuntu me propose néanmoins de charger le driver propriétaire nVidia. Je n'ai rien contre, j'accepte. Petit désagrément, cela nécessite un redémarrage de la machine. Au retour, tout fonctionne bien graphiquement.
  • le pavé numérique ne fonctionne pas. Très étrange. En fait, il faut aller dans les options du clavier et désactiver le contrôle de la souris au clavier. Je n'ai pas cherché le pourquoi de cette option qui apparait sur cette version.

Voilà, je n'ai pas eu d'autres surprises et cette mise à jour est donc un succès.

Notes

[1] ça fait toujours gagner un peu de temps pour une mise à jour.

vendredi 6 juin 2008

Donjons et Dragons, 4ième édition

Aujourd'hui sort Donjons & Dragons 4ième édition. La même année que celle du décès du créateur le plus connu du jeu de rôle, l'un des auteurs de ce jeu.

Lire la suite

dimanche 18 mai 2008

Partage de musique en train

Il y a des gens comme ça qui aiment tellement la musique qu'ils écoutent qu'ils tiennent absolument à la faire découvrir. Je ne suis pas contre, j'aime beaucoup découvrir de nouvelles choses. Le problème intervient lorsque cette découverte n'est pas proposée mais imposée et qui plus est dans des conditions déplorables.

Lire la suite

vendredi 25 avril 2008

Arnaque téléphonique : moi aussi !

J'en avais entendu parlé, ça y est, moi aussi je l'ai reçue : « Salut c moi! J'attends tjr tn appel,a croire que je t'ai laisse mon numero pr rien,rappelle moi au 0899xxxx ».

Peut-être que si j'avais l'habitude de prendre de numéro comme ça juste pour rappeler, peut-être que si j'avais l'habitude de recevoir des SMS de gens qui n'utilisent pas le complètement automatique de leur téléphone portable, peut-être que si je ne me doutais pas qu'un numéro en 0899 ressemblait fortement à un numéro surtaxé, peut-être que pour plein d'autres raisons je me serais rué sur le numéro et aurait appelé pour tomber très probablement (puisque je connais des gens qui se sont fait avoir) sur un répondeur automatique.

Ce n'est pas le cas.

jeudi 17 avril 2008

Passer des contrats avec son langage de programmation.

« je ne fais pas de test car il est impossible que le pointeur soit NULL », « je pourrais vérifier que la valeur est positive avant de faire ma racine carrée, mais ça ferait perdre du temps »,... Une fois encore, je pars de phrases vues et entendues, que ce soit dans l'univers amateur ou professionnel, pour aborder un sujet en programmation.

Lire la suite

mardi 1 avril 2008

Pas de poisson

Traitez-moi de triste sir, mais le 1er avril m'ennuie, particulièrement sur Internet. De nombreux sites se sentent obligés de sortir leur poisson, parfois drôle, mais souvent non. Cela pourrait rester amusant si les blagues ou fausses informations étaient limitées dans le temps à ce seul jour potache. Mais sur Internet, cela n'est pas le cas. Des tas d'internautes vont envoyer les informations, parfois en ne saisissant pas que c'est une blague. D'autres vont recevoir le message le 2 avril ou un peu plus tard, le temps que la diffusion se fasse et, n'étant pas reçu le jour où la vigilance est de rigueur, vont transmettre à leur tour cette blague devenue rumeur.

D'expérience, on en a pour un bon mois, avec des retombées qui vont bien au delà, lorsque tout à coup quelqu'un ressort de sa mémoire cette "information" qu'on lui avait envoyée au printemps de l'année d'avant, avec force "mais j'te jure !".

Je ne pars pas en campagne contre cette tradition, mais il n'y aura pas de poisson d'avril sur ce blog et je m'engage à rester vigilant (ce que nous devrions tous faire devant chaque information et toute l'année de toute façon).

Pas de poisson d'avril ici !

jeudi 27 mars 2008

Mon application exporte en XML

Je reviens sur une partie vue très brièvement dans l'article précédent lorsque je citais le classique « Cette application exporte en XML » au rang de arguments bien placés dans la liste des possibilités d'une application.

Lire la suite

mardi 18 mars 2008

Ceci n'est pas le Graal : XML

« Cette application exporte en XML », « les données sont stockées dans un fichier XML », « pour ton programme, je te conseille d'utiliser XML ». Visiblement, XML est un bon Buzzword. Il sert d'argument commercial autant qu'il semble être la solution miracle dans des discussions de développeurs. Une solution miracle ? Voici un bon candidat au Graal. Examinons donc ce qu'est XML.

Lire la suite

mercredi 5 mars 2008

Ceci n'est pas le Graal : UML

Pour ce deuxième épisode, je prends a nouveau une abréviation se terminant en L. Après la STL, voici venir l'UML. Ces deux abréviations n'ont pas même la signification de leur L en commun.

Lire la suite

mardi 4 mars 2008

Adieu Gary Gygax

Gary Gygax nous a quitté. Il était l'auteur de Donjons et Dragon, le plus célèbre des jeux de rôle. Sans lui, le monde du jeu n'aurait probablement pas été le même.