Je souhaiterais partager avec vous dans ce billet quelques petites choses qui relèvent plus de l'anecdote personnelle que de l'article sérieux. J'espère que vous ne m'en voudrez pas si je prends le risque de baisser un peu le niveau de ce blog, mais ça fait un moment que le sujet me trottait en tête.
Les commentaires sont nos amis, il faut les aimer aussi
Il y a quelques temps, j'ai eu un petit débat de fin de journée avec un collègue qui a un bagage très informatique. Je me suis vite rendue compte que nos manières de « penser informatique » étaient radicalement différentes, à plusieurs niveaux. Parmi nos divergences d'opinion, il y avait la question des commentaires, dont nous avons beaucoup débattu.
Permettez-moi d'abord de rappeler, en gros, ce qu'est un commentaire. Il s'agit d'une partie du texte d'un programme qui sera ignoré à la compilation ou l'interprétation. Le texte est précédé ou entouré de symboles particuliers qui vont signaler à la machine qu'elle doit passer son chemin. En général, comme leur nom l'indique, on y écrit des commentaires sur le programme ou une partie de son code.
Selon mon collègue sus-cité, les commentaires sont inutiles si le code lui-même est bien fait. La topologie du code, son aération, ses noms de variables et fonctions, etc., devraient être suffisants pour en déduire facilement son fonctionnement détaillé.
Il est vrai que la plupart du temps, un code illisible est trop compliqué, comporte trop de boucles imbriquées, des noms de variables qui ne donnent aucune indication sur ce qu'elles contiennent, des choses inutiles, est trop tassé, mal construit (comprendre ici un manque de logique et/ou de cohérence dans la subdivision de ses différentes parties), trop répété, pas modulaire, et relève massivement du bricolage et/ou du temporaire.
Néanmoins, de là à en déduire que l'inverse est vrai, qu'un code « bien écrit » est limpide comme de l'eau de (code) source, il y a un pas un peu vite franchi. Les commentaires existent pour une bonne raison.
Lire du code est un exercice difficile et demande une certaine habitude. Il est d'autant plus difficile de lire le code de quelqu'un d'autre, car il y a à peu près autant de manières d'écrire du code que de manières de formuler une réponse à une question. Et si l'auteur ne voit pas du tout les choses comme vous, il est bien difficile de lire son code, car rien n'est là où vous l'attendrez. Et il ne s'agit là que d'un problème secondaire.
Le vrai, le grand méchant problème est d'ordre beaucoup plus pragmatique. Le code toujours bien écrit relève de l'Utopie la plus extravagante. Ou du monde des Bisounours, je vous laisse le choix de la destination. Dans la vraie vie, tout le monde fait des compromis entre temps disponible et qualité du code, car écrire du code suffisamment propre pour qu'on se voie dedans est généralement incompatible avec les notions de deadline et de progrès technique. Si on souhaite rester dans des délais raisonnables afin de rester à jour dans l'environnement technique dans lequel on évolue, on ne peut pas éternellement courir après l'asymptote de la perfection. Il faut se poser des limites.
À cela s'ajoute le problème des modes et des canons, qui ont une influence considérable dans le domaine de la programmation. Les design patterns en sont un bon exemple. Il y a toujours des gens pour vous dire « c'est comme ça qu'il faut programmer X, et pas autrement », et ils ne sont parfois pas du tout d'accord entre eux. Pourtant, toutes les approches sont intéressantes, mais c'est un autre sujet. Ce que cela implique en revanche, c'est que malgré tout le soin qu'on puisse apporter à la rédaction de son code, on ne pourra pas plaire à tout le monde, non seulement à cause des différentes manières de penser, mais également du fait des différentes écoles qui s'opposent et qui viennent souvent complexifier le code.
Et la bioinfo dans tout ça ?
En bioinformatique, nous héritons de tous ces écueils, mais nous ne nous en contentons pas. Le sujet y prend une toute autre dimension. Comme il fallait en rajouter une couche, il se trouve qu'une bonne partie du code que nous produisons est constitué de scripts et de petits programmes destinés à la recherche et l'analyse de données. Souvent, il s'agit de code « jetable », « provisoire » ou « à mettre au propre » tapé sur un coin de table qui finit par être utilisé sur le long terme car il répond aux besoins du laboratoire pour un ou plusieurs projets. Puis arrive le moment où on souhaite modifier ledit code pour le faire évoluer. Pour peu que le code soit trop vite fait, peu ou pas commenté, il arrive régulièrement qu'il soit plus intéressant de tout réécrire à partir de zéro, au risque de perdre des fonctionnalités intéressantes en route. Que de temps perdu !
Du coup, à plus forte raison dans ce domaine, il est important de commenter son code pour permettre son évolution et sa réutilisation. Malheureusement, tous ceux qui ont eu l'occasion de mettre le nez dans les entrailles d'un petit programme « in-house » ou dans l'implémentation un peu rapide de l'algorithme d'une publication scientifique intéressante (quand il en existe une) se sont forcément cassé les dents quelque part au moins une fois dans leur carrière.
À titre illustration, et pour vous mettre un peu dans le contexte de ce qui m'a inspiré cet article, voici un extrait du code source d'un programme avec lequel je travaille actuellement, dans le cadre d'un projet de métagénomique :
1 2 3 4 5 6 7 |
if(Long_Range) {<br> z[0].lr.r = z[m].rl.r = 1 ;<br> z[0].lr.c = z[m].rl.c = 0 ;<br> } // end if<br> else {<br> z[0].lr.r = z[m].rl.r = 1 ;<br> } // end else |
Il s'agit d'un bel exemple de ce qu'il ne faut pas faire. Le code est obscur, et les commentaires n'expliquent rien et enfoncent des portes ouvertes. Si je vous dis que la totalité du code a à peu près la même allure, vous aurez une idée de l'étendue de ma frustration lorsque j'ai dû modifier de nombreux éléments pour qu'il accepte d'être compilé sur une machine très différente de celle qui l'a vu naître, tout en m'assurant de ne pas modifier son comportement.
En revanche, même s'il y a de très bons exemples de code bien commenté, tout est une affaire de préférences. Je ne m'étendrai donc pas sur l'analyse des méthodes qui font plus ou moins consensus parmi les développeurs. À mon humble avis, il revient à chacun de trouver une manière intelligente, élégante et raisonnable de commenter son code, en fonction de sa morphologie, de sa logique, de sa difficulté, du contexte, du sens du vent et de l’âge du capitaine. Il faut juste ne pas perdre de vue les erreurs à ne pas commettre, et tâcher de les éviter au maximum.
Chers amis bioinformaticiens, commentez-donc votre code ! Il pourrait ainsi rendre service à quelqu'un d'autre à l'avenir, et peut-être même à vous-même. Car soyons honnêtes, nous avons tous un jour ré-ouvert un de nos vieux programmes en nous disant : « Mais kesskejaivoulufaire ??? » Et je terminerai cette enclume par un petit recueil de commentaires et bouts de code qui valent leur pesant de cacahuètes, car donner le sourire à celui qui relit votre code, ce n'est pas interdit pour autant.
1 2 |
Exception up = new Exception("Something is really wrong.");<br> throw up ; //ha ha |
1 |
stop(); // Hammertime ! |
1 |
long long ago ; /* in a galaxy far far away */ |
1 |
options.BatchSize = 300 ; //Madness ? THIS IS SPARTA ! |
1 2 |
// Replaces with spaces the braces in cases where braces in places cause stasis<br> $str = str_replace(array("\{","\}")," ",$str); |
1 2 3 |
// Any maintenance developer who can't quote entire Monty Python<br> // movies from memory has no business being a developer.<br> const string LancelotsFavoriteColor = "$0204FB" |
1 |
doRun.run(); // ... "a doo run run". |
1 2 3 4 5 6 7 |
#Christmas tree initializer<br> toConnect = []<br> toRead = [ ]<br> toWrite = [ ]<br> primes = [ ]<br> responses = {}<br> remaining = {} |
Extrait du code du noyau Linux, driver de la carte réseau succédant à la carte "Big MAC":
1 |
static void happy_meal_tcvr_write(struct happy_meal *hp,<br><br> void __iomem *tregs, int reg,<br><br> unsigned short value)<br><br>{<br><br> int tries = TCVR_WRITE_TRIES ;<br>ASD(("happy_meal_tcvr_write : reg=0x%02x value=%04x\n", reg, value));<br><br>/* Welcome to Sun Microsystems, can I take your order please ? */<br>if (!(hp->happy_flags & ; HFLAG_FENABLE)) {<br>happy_meal_bb_write(hp, tregs, reg, value);<br>return ;<br>}<br><br>/* Would you like fries with that ? */<br>hme_write32(hp, tregs + TCVR_FRAME,<br>(FRAME_WRITE | (hp->paddr < ;< ; 23) | ((reg & ; 0xff) < ;< ; 18) | (value & ; 0xffff))); while (!(hme_read32(hp, tregs + TCVR_FRAME) & ; 0x10000) & ;& ; –tries) udelay(20); /* Anything else ? */ if (!tries) printk(KERN_ERR "happy meal : Aieee, transceiver MIF write bolixed\n"); /* Fifty-two cents is your change, have a nice day. */ |
Trouvés sur le sondage suivant sur StackOverflow :
Un grand merci à Yoann M., Estel, Hautbit, tadaima et Guillaume Collet pour leur relecture, corrections et remarques constructives !
Laisser un commentaire