Muda (II)

le 14/02/2008 par Christophe Thibaut
Tags: Product & Design

Une semaine s'était écoulée depuis notre premier entretien avec M. K, quand je reçus un coup de fil de Baptiste:

- Je déjeune avec M. K demain. Tu peux te joindre à nous si tu veux.
- Avec plaisir! Je me demandais justement..
- En fait, nous avons un peu échangé par mail. Il voulait revenir sur la conclusion de notre dernière discussion, et il m'a proposé un nouveau déjeuner. Il m'a aussi suggéré d'amener une fiche d'anomalie corrigée.
- C'est prometteur !
- Oui, mais je ne comprends pas bien pourquoi il s'intéresse aux bugs déjà corrigés. Ce sont plutôt les non-résolus qui posent problème !
- Tu as pris une fiche classée "critique" au moins ?
- J'en ai pris une au hasard. On verra bien..
Nous avions choisi le coin le moins bruyant de la cantine, et le déjeuner se déroulait cordialement. M. K lut la fiche de Baptiste, puis l'invita à exposer le problème.
- Simple: on lance l'impression du bilan annuel pour l'année 2007. Jusque là tout va bien. On reste dans la boite de paramétrage, on choisit une autre année, par exemple 2006, et on lance l'impression. Et là, catastrophe: les montants du bilan 2006 sont faux; plus précisément, le programme ajoute tous les montants de 2007 à ceux de 2006!
- Je vois.
- Pour imprimer un bilan correct, on doit quitter la boîte de paramétrage et y revenir par le menu principal.
- Intéressant, fit M. K. Quelle est l'origine du problème ?

Baptiste répondit sans hésiter :
- Le conteneur qui récupérait les données depuis la base n'était pas refermé après l'impression. Donc il accumulait les données lues pour chaque impression.
- Pourquoi le conteneur n'était-il pas refermé ?
- Le développeur a oublié cette étape dans la méthode d'impression.
- Pourquoi a t'il oublié ?
Baptiste marqua une pause.
- Aucune idée ! Je n'ai pas pensé à le lui demander.

M. K réfléchit un instant, puis il reprit:
- Dans le reste de l'application, les conteneurs comme celui-ci sont toujours refermés après usage ?
- En général, oui, et même si on oublie de le faire, un conteneur sera automatiquement refermé avant destruction.
- Intéressant. Le programmeur a donc également oublié de détruire le conteneur ?
- Pas du tout : celui-ci ne doit pas être détruit, parce qu'il ressert à l'impression suivante; c'est une variable globale.
- Pourquoi le même conteneur ressert-il à chaque impression ?
- Pour éviter d'avoir à l'instancier à nouveau, je suppose. L'instanciation peu prendre un peu de temps, et...

Baptiste s'interrompit, secoua la tête, et soupira. M. K demanda:
- Qu'est-ce qui ne va pas ?
- En fait, l'impression n'est demandée qu'une fois par an. Le temps gagné est totalement négligeable !
- Mais le développeur a dû penser que c'était quand même un gain important ?
- Allez savoir !

M. K resta un moment attentif au passage des plateaux sur leur tapis roulant. Bastiste finit par lui demander :
- Qu'en pensez-vous ?
- Je pense qu'il y a encore quelques questions que nous pouvons nous poser, mais le mieux serait de discuter avec l'auteur du code.

Notre pause déjeuner touchait à sa fin. Baptiste s'éclaircit la gorge et demanda:
- Est-ce que vous voyez ce qui permettrait d'éviter le gaspillage, dans ce type de cas ?
- Pas encore précisément, mais nous pouvons chercher si vous voulez.
- Avec plaisir !

M. K rangea poussa son plateau sur le côté comme pour faire place nette avant sa prochaine question:
- Supposez un instant que nous soyons les auteurs du programme. Qu'est-ce qui nous aurait automatiquement contraint à refermer le conteneur ?
- Je ne sais pas. Je crois que je l'aurais oublié, moi aussi.
- Qu'est-ce qui pourrait nous le rappeler, ou bien même le fermer à notre place ?
- Eh bien ce que je disais tout à l'heure : utiliser une variable locale. De cette manière le conteneur est détruit à la fin de la méthode, et à chaque nouvel appel on a un conteneur tout neuf, sans données résiduelles.
- Qu'est-ce qui pourrait nous inciter ou nous forcer à utiliser une variable locale ?

Je me permis d'intervenir:
- Peut être une règle de programmation, assez générale, en fait: toutes les variables sont locales sauf si elles doivent absolument être globales.

M. K reprit:
- Bien. Est-ce que cette règle est affichée quelque part ?
- Euh, non...
- Et si dans notre cas la variable devait absolument être globale, qu'est-ce ce qui permettrait de le signaler ?
- Un commentaire approprié. Mieux : une convention de nom avec un préfixe inhabituel!

La conversation s'animait. Je sortis un papier et un crayon, et commençais à noter. M. K. reprit :
- Pensez-vous que nous avons là de quoi éliminer le gaspillage ?
- Je crois que oui. Merci beaucoup.
- Ce n'est peut être pas tout. Supposons qu'en dépit de ces règles, l'erreur reste quand même dans le code. Comment pourrions-nous éviter qu'elle parvienne jusqu'au Maître d'Ouvrage ?
- Je ne sais pas. On a pourtant testé l'impression du bilan avant de lui livrer l'application.
- Avez-vous produit le même défaut ?
- Non, bien sûr !
- Pourquoi ?
- Euh.. Nous avons imprimé plusieurs bilans différents, mais à chaque fois depuis le menu général. Nous ne sommes pas passé par les mêmes chemins que lui..
- Pourquoi ?
- D'abord, nous ne disposions pas de ses tests..

M. K regarda sa montre, puis se leva :
- Je vous prie de m'excuser, mais le temps a passé plus vite que je ne pensais. D'ailleurs je crois que vous commencez à saisir le principe, n'est-ce pas ?

Il nous salua en s'excusant encore, pris son plateau et se dirigea vers la sortie.

Je relus mon papier :

  • toutes les variables sont locales sauf nécessité absolue
  • documenter la raison d'être d'une variable globale
  • préfixer les variables globales
  • afficher au mur les règles de programmation
  • tester l'impression par tous les chemins possibles
  • avoir une copie des tests prévus par le Maître d'Ouvrage

et le tendis à Baptiste.
- Tu crois que tu pourras en tirer quelque chose ?