Java sans joie
|Il y a quelques années, j’ai suivi un cursus en informatique, plus particulièrement orienté vers la programmation. J’ai bifurqué ensuite et ne touche plus à un code que très épisodiquement (genre pour modifier le présent blog) mais, du coup, quand j’ai besoin d’un morceau de logiciel particulier et que j’ai les outils pour le développer, je peux me pencher sur la question et voir si je peux obtenir moi-même le résultat voulu en un temps raisonnable. Et aussi, du coup, j’aime bien quand j’en ai l’occasion jeter un œil au code d’un programme, par curiosité — c’est un peu comme quand on a des notions de mécanique et qu’on aime jeter un œil sous le capot d’une voiture pour voir comment c’est foutu.
Récemment, j’ai donc téléchargé et survolé les sources de Photoshop 1.0.1, gracieusement mises à disposition par le Computer History Museum. Je vais pas refaire l’article, d’autres qui y ont passé plus de temps que moi l’ont déjà dit, mais en bref : c’est propre. C’est principalement du Pascal, langage que je n’ai que très indirectement fréquenté (il a des bouts de syntaxe communs avec Ada, qu’on nous a fait bouffer dès notre entrée à l’IUT), mais à première vue, le code est bien structuré, les différents fichiers bien identifiés, l’interface est séparée du cœur, chaque bout de programme a ses propres variables avec un nommage constant et seules les variables qui ont besoin d’être globales le sont.
Il se trouve que, depuis quelque temps, je suis amené à adapter à mon usage un plug-in open source pour ImageJ (un outil de traitement d’images), qui pourrait bien me simplifier la vie. Et je rêverais qu’il soit écrit par les frères Knoll.
Voyez plutôt le début, juste après les appels de librairies. Note : c’est du Java.
Ce que vous voyez, c’est les (premières) déclarations de variables globales. Là-dedans, il y a des variables qui ont effectivement de bonnes raisons d’être globales, parce qu’elles sont utilisées un peu partout dans différentes fonctions ; par exemple, les tableaux qui vont contenir les valeurs de pixels à traiter.
Mais il y a là des variables qui ne servent que très ponctuellement, dans quelques fonctions bien identifiées.
Par exemple, il n’y a qu’une seule et unique fonction qui affiche des fenêtres : pourquoi donc la chaîne ‘title’, qui n’est utilisée que dans celle-ci, est-elle globale ? Ah oui : parce qu’elle est initialisée dans une autre fonction, au début du traitement de l’image, mélangeant ainsi moteur et carrosserie… Et je vous rassure : la fonction qui affiche les fenêtres a bien accès à tous les éléments pour calculer elle-même le titre à leur donner.
Pis, deux autres fonctions reçoivent une chaîne de même nom dans leurs paramètres : dans celles-ci, un programmeur distrait pourrait donc confondre la variable locale avec son homonyme globale.
Et vous savez ce que fait le booléen ‘cancel’ ? Et bien, comme son nom l’indique, il est là pour marquer qu’il faut interrompre le programme, soit parce que l’utilisateur l’a demandé, soit parce qu’une condition d’exécution n’est pas remplie. Il y a donc une série de fonctions qui vérifient que tout va bien et, si elles trouvent un problème, font un petit ‘cancel = true; return;’, en laissant le soin au reste du programme de vérifier s’il faut continuer. Était-il compliqué de faire comme tout le monde : utiliser la valeur de retour de la fonction (elles sont toutes de type ‘void’, donc elles pourraient être ‘int’ ou ‘boolean’ sans gêner leur conception) pour tester la bonne exécution d’un bout de code ? Plus lisible, plus simple, je ne vois pas quel inconvénient ça pourrait avoir…
Et je ne parlerai pas du fait que j’ai dû créer moi-même une fonction pour lancer les calculs : les commandes nécessaires étaient intégrées au constructeur du plug-in et au gestionnaire d’événements, les programmeurs initiaux n’ayant manifestement pas eu l’idée qu’un jour quelqu’un voudrait automatiser une série d’opérations successives.
Je ne suis pas un grand programmeur. En fait, il me faut souvent un bon moment pour comprendre ce que mes prédécesseurs ont voulu faire, parce que je n’ai pas (ou plus) une vision globale et instantanée de ce qu’il se passe. J’apprécie donc particulièrement un code lisible, clair, qui n’utilise pas n’importe où une variable déclarée 500 lignes plus haut juste parce que le programmeur a eu la flemme de se demander si elle servirait ailleurs, et qui ne prépare pas l’affichage d’une fenêtre au fil de vingt opérations disséminées dans douze bouts de “back-end” au milieu de calculs vectoriels.
L’open source, c’est bien, ça évite de ré-inventer la roue. Mais pitié : si vous faites de l’open source, c’est que vous pensez que certains auront envie de réutiliser votre code. Pourquoi leur compliquer la vie ? Les bases sont simples : donner un nom clair à vos variables et vos fonctions, éviter les homonymes, faire une chose à la fois dans une fonction donnée et séparer ce qui est du programme proprement dit de ce qui est de l’affichage et du contrôle d’exécution.
/*Ah, et un petit commentaire de temps en temps pour expliquer ce qu’on a voulu faire, c’est pas mal non plus.*/
Et même vous, quand vous voudrez faire évoluer votre programme quelques années plus tard, vous vous rendrez compte que ça vous facilitera la vie.