Kaizen
C'est le bruit de mon poing frappant la table qui attira l'attention de M. K. Je fus surpris et gêné de le voir entrer dans l'open space, car à cette heure tardive je me croyais seul depuis longtemps.
Il me demanda d'une voix posée:
- Tout va bien ?
Tout n'allait pas bien. Pour la quinzième fois, la longue et fastidieuse manip de création d'un abonnement se soldait par un plantage : alias inconnu: alias1. Nous avions commencé le matin même une action corrective et l'avions terminée vers 17 heures. A 18 heures l'application était à nouveau prête, mais j'avais eu la mauvaise idée d'emprunter pour mon dernier test un chemin différent dans l'IHM. Clairement, notre action correctrice avait amené une régression dans ce module.
- C'est juste une méthode un peu récalcitrante...
- Je peux peut être aider ? Parfois, un regard extérieur.. J'acceptais en me disant "au point où j'en suis de mes élucubrations à propos de ce code, pourquoi ne pas y joindre celles d'un nouveau venu complet comme cet énigmatique M. K. ?"
M. K tira une chaise et s'assit à ma droite. Il était très calme, ce qui m'était déjà d'un grand secours. Depuis 18 heures ma vie commençait à ressembler à un tourbillon de plus en plus rapide et puissant, tourbillon dont le centre tenait dans une centaine de lignes de code, devenues illisibles à force de scrutations répétées.
M. K ne maîtrisait pas vraiment les outils et le langage de programmation du projet, mais il posait des questions intéressantes. En lui expliquant ce que j'avais fait pour en arriver là où j'étais, je finis enfin par découvrir mon erreur.
- OK ! C'est très clair !
- Qu'est-ce qui est très clair ?
- Ici : j'appelle une fonction de recherche de l'adresse IP, en lui donnant l'alias du compte client, qui est dans cette variable alias_compte.
- Oui ?
- Je récupère l'adresse IP dans cette autre variable ip_compte. Mais plus bas, au moment de faire la connexion, c'est la variable alias_compte que j'utilise au lieu de ip_compte. C'est tellement évident! Quel crétin je suis!
Je remplaçai alors alias_compte par ip_compte, compilai et relançai l'application. La connexion fonctionna sans plantage. Enfin libre !
- OK ! Ca marche, je vais re-déployer le code.
M. K leva la main :
- Non, je ne sais pas si on peut...
Il y eut une pause de quelques secondes. Mr K était un nouveau venu, mais il faisait partie du management. Comment lui expliquer le plus respectueusement possible que je n'avais plus besoin de son aide ?
- Je crois que si. Le reste du programme n'a pas changé. Vous pensez que j'ai pu introduire une régression quelque part ? Ca m'étonnerait. Enfin...
M. K m'observait avec un silence ironique. Ne venais-je pas de passer trois heures sur une stupide régression ? Il ne releva pas cette incohérence, mais déclara poliment :
- Non, ce n'est pas ce que je pense.
- Alors, pourquoi ne pas relivrer ?
- Parce ce que le problème n'est pas corrigé.
- Mais la connexion marche ! Je viens de la tester.
- Le programme marche, mais le problème n'est pas corrigé.
- Je ne comprend pas...
M. K. observa un instant à travers la fenêtre la nuit qui tombait sur la terrasse du 5ème étage. Il se tourna vers moi.
- Pourquoi le programme ne marchait-il pas jusqu'à maintenant ?
Je soutenais son regard en m'efforçant de rester calme.
- Parce que la connexion échouait dans le cas d'une création d'alias.
- Pourquoi échouait-elle ?
- Erreur de logique : une variable était utilisée à la place d'une autre lors de l'appel à la méthode de connexion.
- Pourquoi cette confusion a-t'elle eu lieu ?
- D'abord, parce que ce code est un peu touffu; et que j'étais fatigué aujourd'hui, sans doute. Vous allez me demander pourquoi j'étais fatigué ?
Si ma question l'offensa, M. K. n'en montra rien.
- Non. Ce n'est probablement pas le bon "pourquoi".
- Et pour nettoyer ce code il m'aurait fallu plus de temps.
- Oui. Ce serait une grande amélioration de nettoyer ce code. Mais cette amélioration est hors de portée pour ce soir.
Il se tut un moment. Ma soirée de vendredi s'enfuyait doucement. Je me demandais avec mauvaise foi si M. K. me laisserait conclure cette maintenance, remballer puis redéployer ce code avant que la dernière rame ne passe sur la ligne 1.
Il reprit:
- Peut être la question est-elle: puisque la confusion a eu lieu, pourquoi cette confusion est elle restée dans le code jusqu'à son exécution, au lieu de se manifester ?
- Je sais: parce que je n'ai pas écrit de tests automatisés. Mais la connexion ne peut pas se tester automatiquement de cette manière, il faut lancer le serveur. C'est compliqué.
- Oui. C'est également hors de portée ce soir.
- Alors quoi ?
- Réfléchissons. Qu'est-ce qui pourrait nous empêcher d'exécuter un code contenant une erreur ?
- A part les tests automatisés, je ne vois rien. Et je ne comprends pas votre question, dans la mesure où le problème est résolu!
M. K considéra le bout de ses chaussures impeccables. J'avais l'impression que plus je m'énervais, plus au contraire il se calmait, ralentissait, même.
- Si l'on sait comment le défaut aurait pu être évité, alors on sait comment l'éviter à l'avenir, n'est-ce pas ? Demanda t'il.
- D'accord. Et alors ?
- On peut toujours corriger un défaut présent dans le code, et relivrer ce code en production. Dans ce cas le problème est contourné, mais il n'est pas résolu. C'est quand on sait comment éviter le défaut à l'avenir, et dans ce cas là seulement, que le problème est vraiment résolu.
Il levait doctement l'index pour souligner ce principe, et souriait comme pour attenuer la sévérité de son ton.
- Je crois que je commence à comprendre votre philosophie.
- Dans ce cas, pourriez-vous revenir au code d'avant la correction ?
J'annulai mes modifications, tandis que M. K concentrait toute son attention sur l'écran. Je suggérai:
- Peut être avec de meilleurs noms de variable ?
- Je ne sais pas. alias_compte et ip_compte son plutôt clairs, je trouve. Bien sûr, si le compilateur pouvait comprendre qu'un alias est différent d'une adresse..
- Mais bien sûr !
- Oui ?
- La fonction de recherche de l'adresse IP : regardez son argument.
- Une variable de type String.
- Et ce qu'elle rend en retour.
- Une valeur de type String..
- Et plus loin, la fonction de connexion prend également une String en entrée.
- Oui. C'est ce qui rend la confusion possible entre les deux variables! Alors est-ce qu'on ne pourrait pas donner à ces deux variables un type différent ?
- Si! ip_compte sera du type StringIP et alias_compte du type StringAlias. Et ces deux types seront équivalents au type String.
Je modifiais le code source, tout en expliquant:
- Ensuite je change la signature de la fonction connexion : il lui faudra une variable de type StringIP en entrée. Je compile..
Le compilateur signala instantanément une erreur de type. M. K observait l'écran avec satisfaction. Il dit :
- Désormais la confusion est manifeste; et nous ne pouvons pas exécuter le code tant que cette confusion persiste. Bravo !
Je plaçai à nouveau la bonne variable et recompilai, puis je lançai pour la dernière fois l'abonnement, et la connexion eut bien lieu. Tout en préparant le déploiement du module, je remerciai M. K pour son aide si précieuse. Il protesta, puis se leva en déclarant :
- Vous avez corrigé le défaut, et vous avez trouvé une solution à portée de main pour éviter ce genre de défaut à l'avenir. Le problème est résolu. Vous pouvez attaquer maintenant le problème suivant !
La dessus, M. K me salua poliment et quitta l'open space aussi silencieusement qu'il était apparu.