lundi 19 septembre 2011

Tirons vers le haut

C'est la rentrée. Ça n'aura échappé à personne. Et la rentrée, ça implique tout un tas de réunions d'information aux parents, comme ils disent. Ce soir, j'ai assisté à celle des 4èmes. Le blabla habituel, pour l'essentiel. Les profs que je n'aurais probablement pas aimé avoir (et que je n'aime toujours pas, je crois), les profs sympathiques, ceux qui font juste leur boulot, et ceux qui sortent de l'ordinaire.

Et grâce à un de ces dernier, ee soir j'ai également assisté à quelque chose que je trouve très intéressant, et que je me sens obligé de partager.

Cela s'est produit pendant l'intervention du prof de physique/chimie. Il explique un peu ce qu'il vont faire, et comment il procède. En particulier, pour les parties pratiques, il répartit les élèves par groupes de 4. Tout le monde acquiesce. Puis il explique que pour évaluer les travaux réalisés en groupe, il prend un travail au hasard dans chaque groupe et que tous les élèves du groupe seront notés sur ce dernier.

Pendant les quelques secondes que je prenais pour réfléchir à cette méthode peu courante, une ou deux mamans commençaient à s'agiter. Puis finissent par exprimer leur malaise : "mais c'est injuste !".

Le prof feint un air surpris. Les mamans enchaînent pour essayer d'expliquer leurs craintes que des éléments qui ont des difficultés (forcément minoritaires, à les écouter) ne viennent pénaliser les bons élèves (lourdement sous-entendu : leurs enfants). Il ne faudrait pas que les mauvais élèves ne "tirent vers le bas" les bons.

J'ai beaucoup aimé la réaction de l'enseignant, qui, de toute évidence, pratique cette manière de faire depuis des années.

Avec un grand sourire, il explique posément que non, les "mauvais" ne tiraient pas les bons vers le bas, mais qu'on assistait plutôt à l'inverse. De plus, cette sorte de solidarité imposée poussait finalement les enfants à coopérer, s'organiser et à faire pression sur les perturbateurs pour qu'ils jouent le jeu. Bien entendu, en cas de comportement extrême de certains, le prof intervient.

Il a fini, toujours avec un grand sourire, sur le fait que tout "allait bien se passer", en enterrant en quelques minutes le mythe de la traction vers le bas des meilleurs par les moins bons si on les mélange.

Je précise que je vis dans une ville que l'on qualifie de "favorisée", loin des Zone d'Éducation Prioritaires et autres Zones Sensibles. La réaction de ces parents, est, à mon sens, assez emblématique d'une certaine façon de penser que certains aimerait bien voir se généraliser.

Mais j'ai pu constater ce soir avec plaisir qu'il y a encore des profs qui apprennent à nos enfants que ce n'est pas forcément la seule voie, et qu'il est possible de travailler ensemble, de coopérer pour l'intérêt du groupe.

mercredi 8 décembre 2010

Le temps

Je n'ai pas assez de temps ! Les journées ne sont pas assez longues pour tout caser. Il y a tellement de choses à apprendre, essayer, découvrir ! Et en parallèle, tellement d'autres à faire pour faire avancer le quotidien. Et il y a toujours trop d'imprévus pour pouvoir espérer planifier quoi que ce soit. Mener de front une vie familiale active, un travail et une vie de geek me paraît plus tenir de l'exploit qu'autre chose.

Bien entendu, il y a des méthodes pour mieux gérer son temps (GTD, Pomodoro, et j'en passe), mais je trouve qu'elles ne résistent pas bien aux aléas de la vie. Et, autant je trouve possible de limiter l'inattendu au niveau professionnel, en tous cas de le circonscrire, autant il est difficile à éviter dans la vie familiale quotidienne. De plus, elles demandent toutes une certaine rigueur que je n'arrive pas à tenir dans ma vie privée. Je ne sais pas pour vous, mais les listes de choses à faire qui s'allongent jusqu'à ce qu'on décide de ne plus les regarder pour éviter la dépression ne me réussissent pas. Les emplois du temps fixes et bien régulier sont trop tristes. La vie ne manquerait-elle d'ailleurs pas un peu de piquant si elle était trop strictement réglée.

Et encore, j'ai réussi à joindre l'utile à l'agréable en travaillant dans ce qui me passionne. En plus, mon boulot a pris une orientation qui me permet presque de geeker en travaillant. Ou de travailler en geekant. Je ne sais plus trop :-).

Pour le reste, cette soif, ce besoin proche de l'addiction de découvrir, d'apprendre, il me reste les nuits. Mais dormir n'est pas désagréable non plus, finalement.

Voilà. Un constat, une réflexion plus qu'autre chose. Des choses qui me trottent dans la tête et qui doivent sortir. Peut-être aussi une sorte d'appel aux trois lecteurs de ce blog : y a t'il des papas geeks dans la salle ?

C'est moi, ou bien il y a comme de l'écho par ici ?

mardi 18 mai 2010

Netbeans et CMake

Nombreux sont ceux qui demandent le support de Netbeans dans CMake. Je me demandais également comment intégrer CMake dans un développement utilisant Netbeans. En fait, la réponse est simple : CMake n'est pas capable de créer des projets Netbeans, mais ce dernier est capable d'importer des projets CMake. Il suffisait de se poser la question différemment, comme souvent, pour obtenir la réponse.

Pour importer un projet CMake, il suffit de créer un nouveau projet en choisissant d'importer un projet à partir de sources existantes, puis de sélectionner le mode de configuration automatique (en ayant bien pensé à supprimer les éventuels Makefiles qui auraient pu être générés). Un Makefile et un projet sont créés.

Par la suite, si des modifications sont faites dans CMakeLists.txt (ajout de fichier, de librairies, etc), il suffit d'aller faire un clic droit sur le projet dans Netbeans, puis de choisir Reparse Project dans Code Assistance (oui,  j'ai laissé mon environnement en anglais). Le projet est alors mis à jour en conséquence.

Plutôt simple, non ?

mardi 20 avril 2010

Tests unitaires et C++

Jusqu'à récemment, j'utilisais CppUnit pour implémenter mes tests unitaires en C++. Le choix avait été plus ou moins dicté par le fait qu'il était l'héritier direct de JUnit et qu'il proposait (enfin était sensé proposer) une méthode simple pour pouvoir afficher les résultats dans une fenêtre graphique (la liste des points verts ou rouges qui donne un aperçu rapide de l'état des tests).

Mais, à l'usage, CppUnit m'a semblé de plus en plus lourd à mettre en œuvre et à utiliser. Je passais trop de temps, à mon goût, sur l'écriture des tests (définition et implémentation des classes, principalement) par rapport au temps que je passais à réfléchir à l'essentiel, à savoir le code sur lequel je travaille. Je me suis donc mis en quête d'une infrastructure de tests unitaires plus lègère. Et je l'ai trouvée !

Il s'agit de UnitTest++. Ce que j'apprécie dans ce framework, c'est son extrème simplicité. Un test est de la forme :

TEST(MonTest)
{
    MaClasse monObjet;
    monObject.FaitUnTruc();
    CHECK(monObject.AFaitUntruc());
}


Et le main ressemble à :

int main()
{
    return UnitTest::RunAllTests();
}


Ici, donc, pas de classe à écrire, on entre tout de suite dans le vif du sujet. Bien entendu, il est possible d'aller un peu plus loin, en testant, par exemple, qu'une exception a bien été levée, ou en introduisant une classe permettant d'implémenter des tests avec fixture (je n'ai toujours pas trouvé de traduction valable pour ce terme... si quelqu'un en a une, je suis preneur). Il est même possible de vérifier que l'exécution d'un test ne dépasse pas une durée donnée. On peut utiliser une version surchargée de RunAllTests() si on veut utiliser une méthode particulière pour faire les rapports de tests, par exemple.

La documentation est un peu succinte mais suffisante pour une utilisation directe. Pour une utilisation avancée, une étude des sources (fournis) sera probablement nécessaire.

Pour le moment, je suis plutôt satisfait par UnitTest++. Je pense me plonger un peu plus dedans pour écrire un rapporteur de tests en xml. Ainsi, on pourra lancer automatiquement les tests unitaires sur un serveur, et afficher les résultats dans une page web avec un peu de mise en forme. On verra si c'est aussi simple que d'écrire un test unitaire :)

samedi 6 mars 2010

Réflexions sur le refactoring

Après avoir passé quelques semaines à remettre en état du code truffé de duplications et de problèmes de conception, j'en suis arrivé à quelques conclusions.

Celle qui me paraît la plus importante fait écho à un twit de Kent Beck : "if you want to eliminate duplication first make the similar code exactly identical, then eliminating duplication is trivial". J'en ai fait l'expérience : si des portions de code se ressemblent, il est aisé de les rendre les plus identiques possible et il devient effectivement trivial de faire disparaître la duplication. La première étape peut se faire à l'aide de méthodes simples de refactoring comme le renommage de variables ou de méthodes, ou en déplaçant des lignes de codes. Le risque est donc très faible.

Ensuite, un simple outil de diff (vim, par exemple :)) permet d'extraire les parties communes ou, tout simplement, de constater l'égalité de deux portions de code (voire de fichiers). À partir de là, les méthodes habituelles de refactoring s'appliquent le plus simplement du monde.

Il est inutile de vouloir reprendre l'intégralité du code en une seule fois. Il est plus facile de travailler par étapes, classe par classe, par exemple. Refactorer une classe, la valider, l'intégrer, et passer soit à la suivante, soit à une autre tâche. Il est toujours temps de revenir sur celles qui restent à faire.

Certaines améliorations impliquent des modifications en profondeur. Là encore, il est plus sûr et plus aisé de procéder par étapes. Par exemple, la factorisation de code au sein d'un ensemble de classes peut faire apparaître un nouveau niveau de factorisation ou mettre en évidence une nouvelle architecture de classes. Il est préférable d'aller au bout de la première factorisation avant de se lancer dans le second niveau. Sinon, le travail à effectuer sur le code peut devenir complexe et, finalement, difficile à maîtriser.

Voilà pour cette fois, j'espère que mon expérience pourra vous être utile.

samedi 6 février 2010

3 ordinateurs, 4 écrans et...


... un élevage de souris. Et je ne parle même pas de l'enclos des claviers !

Bref, pour ceux qui, comme moi, sont parfois amenés à travailler en parallèle sur plusieurs machines, éventuellement avec des systèmes d'exploitation différents, la multiplication des périphériques d'entrée peut rapidement devenir problématique. Pour ne pas dire autre chose...

Eh bien il y a une solution : synergy+. Tout est expliqué sur la page du projet : un serveur sur lequel on utilise le clavier et la souris et des clients qui deviennent des sortes d'extensions du bureau du serveur. L'installation et le paramétrage sont simples, je ne m'étendrai pas là-dessus. On donne la liste des machines possibles et leur position relative. Il faut juste ne pas oublier de bien situer toutes les machines. Si A est à droite de B, il ne faut pas oublier d'indiquer que B est à gauche de A.

Ah, j'ai failli oublier de mentionner que ce merveilleux petit logiciel fonctionne sur Mac OS, Linux, Windows et probablement sur tous les BSD après compilation.



mercredi 27 janvier 2010

Suite des aventures avec mon Mac

Étant plutôt habitué à utiliser Linux sur mon PC personnel et Windows sur mon PC professionnel, il y a quelques habitudes que j'ai du mal à perdre. Surtout concernant les fonctionnalités dont j'ai besoin. Sous linux, un coup d'œil dans les dépôts, un petit "apt-get install" et le tour est joué ! Sous Windows, un coup de Google, et 3 heures de recherches et de tri plus tard, on a éventuellement l'application qu'il nous faut.

Sous Mac, comme il n'y a pas de dépôts centralisé de logiciels, mon premier réflexe est de faire comme sous Windows : mon pote Google, recherche, téléchargement, tout ça. Mais en fait, je me rends de plus en plus compte que ce que je cherche est déjà fourni.

Par exemple, j'étais à la recherche d'un moyen d'enregistrer des screencasts. Il y a effectivement des applications, les plus intéressantes étant payantes. Mais Quicktime X permet de le faire. Il prend forcément tout l'écran, mais iMovie permet de retailler le film pour ne garder que la partie qui nous intéresse.

Au boulot, des collègues pas habitués au Mac ont eu besoin d'en contrôler un à distance via le réseau. Leur premier réflexe : télécharger un serveur VNC. En fait le partage d'écran intégré au système en est un, tout à fait standard.

Je suppose qu'il y a encore pas mal d'autres exemples comme ça.

Il va falloir que je m'habitue à chercher d'abord sur mon Mac ce dont j'ai besoin avant d'aller voir ailleurs.

dimanche 10 janvier 2010

J'ai testé 7 !

J'ai été obligé d'installer et de tester 7 (c'est dingue, mais ça me fait systématiquement penser au film homonyme) pour mon boulot. Et, comment dire ? C'est... ce n'est pas... enfin... c'est Windows, quoi ! Je ne comprends pas trop tout le bruit qu'on fait autour de cette version. C'est toujours Windows. Les fans seront sûrement conquis, ceux qui n'aiment pas n'aimeront toujours pas, et les indécis se le verront imposé avec leur nouvelle machine. Pas de révolution, pas de réelle inovation, comme d'hab'. Tous les gadgets qui sont censés nous épater existent depuis des années. Quant à la simplicité, si cela correspond au fait de pouvoir cacher les menus dans lesquels on passe notre temps à se perdre, ou à une énième refonte du menu démarrer je ne vois pas trop non plus ce que ça apporte.

Bref, n'attendez pas un test complet ici. Juste le point de vue tout à fait subjectif d'un utilisateur de linux converti au Mac. 7 n'est que Windows. Même Microsoft n'y croit pas, si on en juge par la campagne de publicité la plus pourrie qu'on ait jamais vue pour un produit de cette firme. Même les vendeurs de lessive font mieux.

Oui, je sais, un article pour pas grand chose. Juste envie de donner mon sentiment. Surtout qu'il va falloir que j'aille plus loin avec ce nouveau venu. Alors il y aura peut-être une suite...

mardi 15 décembre 2009

Parce que ça commence à m'énerver !

Extraits du cours de technologie de mon fils aîné en 6ème :
  • Où range t'on les programmes ? Dans le dossier Program Files
  • Qu'est-ce qui permet de parcourir l'arborescence des fichiers ? L'explorateur Windows
Je passe sur les imprécisions et inexactitudes (en particulier la distinction faite entre fichier et programme). Pas un mot sur de possibles alternatives, sur, par exemple le Finder (et je ne parle même pas de citer Nautilus, Gnome et autre KDE). Cela fait partie de ce qu'ils appellent, en gros, le brevet d'aptitude en informatique.

Ce n'est pas la peine de faire passer des lois anti-monopole, de sanctionner Microsoft : nos enfants sont préparés à l'utilisation de leurs produits. Je ne dis pas qu'il faut banir cette marque de nos écoles (je n'en demande pas tant !). J'aimerais tellement qu'on explique des principes à nos enfants et que l'utilisation d'un système ou d'un autre ne soit qu'une application, un travail pratique.

Imaginez juste 2 secondes un énoncé de problème du genre :
"Jean prend sa Grenault et parcourt 800Km. Sachant que sa voiture consomme 8l au 100, et que son réservoir contient 40l, combien de fois devra t'il s'arrêter dans des stations Potal pour faire le plein ?"
Je vois déjà les réactions indignées des parents, des associations de consommateurs, et de je ne sais qui encore.

Oui, je sais, je simplifie. Mais pas forcément plus que ceux qui estiment que tout ça est normal.

mercredi 9 décembre 2009

Un peu de lecture

Je viens de finir Propaganda : Comment manipuler l'opinion en démocratie de Edward Bernays et Normand Baillargeon. Un livre fort intéressant qui, malgré qu'il ait été écrit en 1928, reste fortement d'actualité. On est assez surpris d'y découvrir que la propagande, bien qu'elle ait acquis une bien triste réputation sous de nombreux régimes totalitaires, est bien née en démocratie.

À vrai dire, la propagande décrite dans cet ouvrage est ce que l'on qualifie aujourd'hui de "Relations publiques". Mais ne nous y trompons pas : les relations publiques utilisent bien des techniques de la propagande. Et je pense que nous le savons tous. Mais la lecture de ce livre ouvre une nouvelle perspective, une autre façon de voir le fonctionnement de nos démocraties.

Bref, je vous le conseille. En plus, ça se lit plutôt vite et bien. On aurait tort de se priver !

Bon, maintenant, j'attaque le Petit cours d'autodéfense intellectuelle de Normand Baillargeon (qui a préfacé Propaganda) et Charb. Je vous tiens au courant.

mardi 8 décembre 2009

10 jours avec un MacBook

10 jours déjà, et la première impression tend à se confirmer : c'est une très bonne machine, confortable malgré sa petite taille, endurante, avec un bon système, même s'il demande de s'y habituer.

Le touchpad multi-point, en particulier, est un vrai plaisir. J'en suis à ne pas vraiment avoir envie de brancher une souris et je me surprend à vouloir utiliser le PC du boulot de la même manière.

J'ai un peu plus de mal avec la disposition du clavier Apple, qui est un peu déroutante quand on vient du monde du PC. Question d'habitude, je suppose.

Je trouve qu'il manque également un témoin d'activité de disque. Cela me perturbe de ne pas pouvoir savoir d'un coup d'œil si ma machine travaille ou pas lorsque le temps de réponse est un peu long. Mais là encore, il ne s'agit que d'un défaut mineur.

Donc, côté matériel et même logiciel, je suis vraiment satisfait de mon choix. En revanche, j'ai été très déçu par le projet MacPorts. Je pensais avoir au bout des doigts un équivalent du système de ports BSD, et je me retrouve avec un projet inachevé, avec de nombreux paquets qui ne peuvent s'installer. Au premier échec d'installation, on se dit qu'on va essayer de contribuer au projet en essayer d'apporter une correction. Mais on se rend rapidement compte que, finalement, il y en a beaucoup. C'est vraiment dommage. Je n'ai pas vraiment le temps de me consacrer à ce type de projet, et j'ai donc abandonné MacPorts au profit de Fink.

Fink est une sorte d'apt, mais en plus ouvert. Les principes sont globalement les mêmes : des dépôts de paquets et un système simple et centralisé pour les installer, supprimer et mettre à jour. Je viens de l'installer et je ne l'ai pas encore vraiment testé, mais les premières impressions sont bonnes.

En résumé, si vous cherchez à acheter un portable et que vous avez le budget, n'hésitez pas : ces portables sont vraiment excellents. (Bon, maintenant, je vais négocier avec Apple combien ils vont me filer pour ce coup de pub :-) )

samedi 28 novembre 2009

Des manchots aux pommes

Jusqu'à présent, j'étais plutôt adepte des PCs sous Linux. Depuis peu, cela est en train de changer grâce à l'acquisition d'un MacBook.

J'ai toujours considéré les Mac comme des machines de qualité, mais trop chères pour ce qu'elles étaient, malgré tout. La dernière gamme de MacBook est venue à bout de cette idée : ce sont d'excellentes machines pour un excellent rapport qualité/prix. Et qui fonctionne sous Unix. N'oublions pas que le cœur de Mac OS est un Free BSD, remanié par Apple, mais la base est là. Vous avez toujours accès au terminal, avec l'ensemble des commandes Unix. X11 est là, lui aussi. Il y a quelques années de ça, un ami avait acheté l'iMac Tournesol. Un des arguments qu'il avait donné pour expliquer son choix était, entre autres : "je peux lancer un terminal et utiliser vi". Je le comprends très bien aujourd'hui et le rejoins complètement. C'est un peu le meilleur des deux mondes.

Et les logiciels libres dans tout ça ? Le projet Macports mets plus de 6300 paquets logiciels à disposition, façon apt sous Debian ou Ubuntu ou plutôt à la manière des ports sous BSD.

Voici donc le début de mes aventures sur les ordinateurs à la pomme. Je ne renie pas pour autant les manchots et, d'ailleurs, si je ne suis pas totalement satisfait, je reviendrai vers Linux qui reste, pour moi, une valeur sûre.

mercredi 18 novembre 2009

Cachez cette erreur que je ne saurais voir !

Qu'y a-t-il de plus agaçant qu'une application qui plante lamentablement sans le moindre message ? Qu'y a-t-il de plus compliqué pour le développeur à déboguer que ce type d'application ?

Ça fait assez longtemps que j'observe cette tendance qu'il y a chez de nombreux développeurs (y compris moi-même à une certaine époque) à cacher les erreurs, les exceptions, à tout faire pour que l'application ne quitte pas inopinément, au risque de mettre en péril la fiabilité des résultats obtenus. On essaie de faire croire à l'utilisateur/client qu'il n'y a jamais de problème. Mais tout développeur sait que cela est illusoire. Une sorte Graal qu'il est impossible d'atteindre. On a beau utiliser des tests unitaires, essayer de prévoir tous les cas d'erreurs, il y a toujours une situation qu'on n'a pas anticipée et qui plante notre application qu'on croyait pourtant si robuste.

J'ai pu également observer qu'on a l'air beaucoup plus crédible et professionnel lorsqu'on a une trace ou un code d'erreur lorsqu'il y a plantage. L'idéal est de pouvoir produire une image de la pile dans un fichier au moment de l'erreur, et de la demander au client : vous gagnez en crédibilité car vous avez envisagé l'improbable. De plus, vous récupérez des informations précieuses qui vous permettent de comprendre et de corriger rapidement le bug. Un code d'erreur est souvent suffisant.

Les assertions (assert), par exemple, peuvent être un outil précieux. Lorsque je débutais, on m'a appris, comme une sorte de dogme, que les assertions ne devaient être utilisées que dans du code compilé en version debug, mais ne devaient pas apparaître dans la version compilée en release. Je me rends compte maintenant, pour avoir violé cette règle, combien cela est une erreur. Une assertion sur un pointeur NULL à un endroit où on ne s'y attend pas et qu'on ne sait pas rattraper, par exemple, évite une erreur anonyme. Un assert indique la ligne de code et la condition qui a provoqué l'arrêt. Une information des plus précieuse pour corriger rapidement une erreur grave.

À mon sens, le plus important est la maîtrise de l'erreur. Avoir le contrôle et le montrer, pour gagner la confiance du client ou de l'utilisateur. Bien entendu, aucune erreur, c'est mieux !

mardi 17 novembre 2009

Le code jetable

On a tous eu un jour à écrire un bout de programme pour tester une idée, une librairie, un concept ou pour faire une "maquette". En général, on se dit que, de toutes manières, on ne gardera pas ce qu'on est en train d'écrire. Alors on met de côté la qualité.

Avez-vous remarqué que ce code destiné à être oublié finit très souvent en production ? La maquette évolue pour devenir le produit final. La partie utile du petit programme de test est intégrée telle quelle dans une application. Avec un impact sensible sur la qualité de l'ensemble.

Et lorsque ce code n'est pas directement utilisé, il sert souvent d'exemple, voire de documentation pour les nouveaux arrivants ou les collègues. Et il est pénible de passer beaucoup plus de temps qu'il n'en faut sur un exemple parce qu'il est incompréhensible ou qu'il est impossible de le faire fonctionner.

Ce qui m'amène à la pensée du jour : lorsque vous écrivez un bout de programme, essayez d'imaginer ce qui se passera lorsque vous devrez le reprendre dans 1 mois, 3 mois, 6 mois, 5 ans.

lundi 16 novembre 2009

Un peu de Vim

Si comme moi vous développez en C++ sous Vim (le meilleur éditeur de la Terre, il faut bien le dire), et que vous avez la chance d'avoir un écran large avec une résolution suffisante pour ouvrir deux fichiers sources côte à côte, alors ces petits raccourcis vont vous plaire :


noremap :exe "vert sfind ".substitute(expand("%:t"),
expand("%:e")."$", "cpp", "")
noremap :exe "vert sfind ".substitute(expand("%:t"),
expand("%:e")."$", "h", "")


Le premier permet d'ouvrir le fichier cpp correspondant au fichier h que vous êtes en train d'éditer. Je vous laisse deviner ce que fait le second. La fenêtre sera coupée en deux verticalement, ce qui permet d'avoir les deux sous les yeux.

Combiné avec les excellents scripts cvim et taglist, le développement en C sous vim, c'est que du bonheur !

samedi 14 novembre 2009

Copier-coller, c'est mal !

On nous l'a souvent dit, la duplication de code est une mauvaise chose. Les raisons les plus souvent invoquées sont également les plus évidentes :
  • elle rend la maintenance et l'évolution du code beaucoup plus difficile,
  • elle alourdit et complexifie inutilement ce même code
Mais nombreux sont les développeurs qui ne prennent pas réellement ces défauts au sérieux, voire qui ne les comprennent pas. "Pourquoi se compliquer la vie ? Mon code fonctionne". Pire encore certains pensent qu'il est bon de dupliquer le code plutôt que de le factoriser dans des fonctions ou des méthodes pour des raisons de performances. Combien de fois avez-vous entendu à propos d'un bug enfin expliqué : "ça vient d'un copier-coller" ? Ou encore : "Oh ! Ça, ça devrait aller vite, c'est copier-coller de telle autre méthode" ?

J'ai été amené à intervenir sur de nombreux styles de code différents, dans pas mal de langages différents. J'ai vu du bon code, et du mauvais, aussi. Mais je crois que ce qui m'a posé le plus de problème, c'est bien le code dupliqué, le "copier-coller". J'ai eu de plus l'occasion d'observer ses méfaits sur des applications ayant plusieurs années de développement derrière elles.

J'aimerais essayer ici de partager cette expérience.

Il y a plusieurs niveaux de duplication :
  • au sein d'une fonction/procédure/méthode (appelons cela une fonction, pour faire simple),
  • dans un module/une classe,
  • dans un projet qui comprend plusieurs modules.
Au sein d'une méthode ou d'une classe, le code dupliqué est facile à voir. C'est également, à mon sens, son principal défaut : il transforme une fonction qui devrait, conceptuellement, faire une vingtaine de lignes en un monstre de parfois plusieurs centaines de lignes. Il noie l'information. Il est lors très difficile pour quelqu'un qui ne l'a pas écrit de se plonger dans ce type de source. Souvent, même son auteur a du mal à revenir dessus. Et si il y a une modification à apporter, même mineure, l'effort que cela demande est souvent disproportionné du fait qu'il faut la reporter autant de fois que le bloc de code à modifier a été dupliqué. J'ai vu des bugs qui résultaient clairement d'un oubli lors du report d'une modification sur des blocs dupliqués. Un des cas extrêmes que j'ai pu rencontrer est l'utilisation d'une dizaine de variables de type a_0_1, a_0_2, ... , a_5_1, a_5_2 à la place d'un simple tableau à deux dimensions. Je vous laisse imaginer l'allure des fonctions qui ont la charge de l'initialisation et de la mise à jour de ces variables.

J'ai encore du mal à comprendre ce qui peut pousser un développeur abuser du copier-coller dans une fonction.

Il semblerait que certains pensent que leur code sera plus efficace sans appel de fonction. Dans l'absolu, cela est probablement vrai. Et cela est une réelle contrainte dans certains systèmes embarqués dans lesquels la profondeur de la pile d'appels est limitée. Mais soyons raisonnables : les machines actuelles sont performantes. Nous ne sommes plus à l'ère des machines 8 bits pour lesquels il fallait grappiller des cycles de processeur partout où cela était possible. Les quelques nanosecondes supplémentaires que coûte un appel de fonction n'aura pas d'impact sur les performances de votre application. Et si vous developpez en C++, les méthodes inline sont là pour ça. L'optimisation des performances passera plus certainement par un travail sur les algorithmes utilisés.

Si c'est pour éviter de taper au clavier, alors je pense qu'il faut penser soit à changer d'éditeur de texte, soit à apprendre à taper (ce n'est pas si dur et il est facile de faire des progrès), soit à changer de métier. Mais j'ai du mal à croire que la flemme d'utiliser son clavier puisse réellement motiver l'abus de copie.

Bien pire que la duplication au sein d'une méthode ou même d'un fichier, il y a la copie de blocs dans divers fichiers sources, qui peuvent être répartis dans plusieurs modules (ou librairies, ou packages, ou ce que vous voudrez). C'est là que les choses se compliquent. On retrouve le problème de la répercussions des modifications sur un des blocs de code. Cela est d'autant plus vrai si on travaille en équipe et que la personne qui fait la modification n'est pas consciente de la duplication. On voit alors des bugs que l'on croyait corrigés resurgir là où on ne les attendait pas : la correction a bien été faite, mais pas partout. Une nouvelle correction est alors apportée, souvent différente de celle qui a été faite sur l'autre portion de code, celle qui a servi de modèle. Et on se retrouve avec des lignes de programme qui ont l'air bien différentes mais qui font, au final, la même chose. Et avec un programme dont les sources sont bien trop lourdes par rapport à ce qu'elles devraient être. La maintenance devient pénible et les évolutions trop difficiles. Alors on se dit qu'il faut tout refaire et on recommence un cycle.

Il est beaucoup plus simple de créer des librairies ou des classes qui contiennent ce code commun. Et ce n'est pas réellement beaucoup plus long. Dans la plupart des cas l'argument du temps n'en est pas un.

Mais bien au delà des conséquences sur le code, je pense que l'abus de copier-coller a également un impact sur le développeur lui-même, qui perd peu à peu l'habitude d'innover et de chercher des solutions. Combien de fois, face à un nouveau problème, le premier réflexe est de voir si quelqu'un d'autre n'a pas déjà écrit un programme pour le résoudre, et de le copier sans même réellement chercher à savoir si cette solution est la bonne dans ce contexte. Chercher à ne pas réinventer la roue en permanence est une bonne chose. Réutiliser ce que d'autres ont déjà fait n'est pas mauvais en soit, c'est le principe même des librairies. Mais tenter de développer en mettant bout à bout des portions de programmes piochées à droite et à gauche est une mauvaise idée. J'ai vu un stagiaire échouer en s'y prenant comme ça, par tâtonnement, sans vraiment comprendre ce qu'il faisait. Alors qu'il aurait certainement réussi en prenant le temps de chercher et de comprendre. Son responsable lui a fait confiance et ne s'en est pas aperçu à temps. Une fois le stage terminé, il s'est avéré que ce qu'il avait annoncé comme impossible était en fait faisable, et même plutôt simple.

Il y aurait encore beaucoup à écrire sur le sujet. Mais j'espère que la lecture de ce billet vous fera réfléchir avant de copier un bout de code pour le recoller quelque part.