Bonjour à tous,
les questions de style donnent souvent lieu à des échanges plus ou moins passionnés, qui pour intéressants qu'ils puissent être, finissent par parasiter les fils où ils prennent naissance. J'espère que vous ne m'en voudrez pas de déplacer ici une discussion de ce type, que je trouve effectivement intéressante, mais qui s'appuie sur plusieurs fils dans lesquels elle est selon moi hors sujet.
Dans mon esprit cette discussion est ouverte à tous, et pourraît être un forum de débat et d'analyse, notamment de formes que certains jugent bizarres ou dangereuses alors que d'autres les trouvent au contraire parfaitement banales et légitimes. N'hésitez pas à intervenir, poser des questions, demander des éclaircissements, faire part de votre expérience et de vos anecdotes (heureuses ou tragiques...).
En attendant, poursuite de la discussion (Pour rétablir le contexte, le plus simple est sans doute de partir d'ici pour le fil principal, et de suivre les liens donnés dans le texte ci-dessous pour retrouver les échanges annexes) :
Sur la concision, l'intelligibilité et l'appropriation
J'entends bien. Mais il me semble que c'est peut-être un mauvais service à leur rendre que de leur donner d'entrée une solution parfaite qu'ils peuvent utiliser par copier/coller. Le risque alors est qu'ils ne la comprennent pas complètement et que cela leur pose des difficultés plus tard s'ils doivent intervenir dessus.
Je pars du principe que ceux qui posent des questions sur ce forum ne le font pas dans le cadre du choix d'un langage pour résoudre leur problème : Perl a déjà été choisi. Et mes réponses ne devraient pas les faire fuir si, comme je le fais systématiquement, je démontre qu'elles fonctionnent, d'une manière qu'ils peuvent reproduire et expérimenter tranquillement chez eux. Au contraire, elles devraient éveiller leur curiosité.
Il est important que le demandeur s'approprie la solution proposée, et en particulier comprenne l'algorithme sous-jacent et les mécanismes mis en œuvre pour l'implémenter. Lors de ce travail d'appropriation, si la solution est présentée de manière trop concise pour lui dans un premier temps, il va devoir la décomposer, peut être introduire des variables intermédiaires qui vont dénommer d'une manière qui a un sens pour lui à ce stade de sa propre réflexion certains éléments ou concepts manipulés. C'est très bien comme cela.
Et tu noteras par ailleurs j'espère que je ne rechigne pas à accompagner les demandeurs dans ce travail d'appropriation lorsqu'ils ont des difficultés.
Sur le nommage des variables
Je n'aime effectivement pas les variables 'documentaires' triviales, ni celles qui semblent l'être mais ne le sont pas. Pour illustrer cette seconde catégorie, reprenons ton exemple
Pour moi hors contexte c'est incompréhensible. Pourquoi $nb_prestas et pas $nb_b ? Qu'est-ce qu'il y a dans @b ? C'est le tableau des prestas ? Alors, surement il devrait s'appeler @prestas, non ? Ou bien est-ce qu'on découvre incidemment que la taille de @b est identique au nombre de prestas, et c'est cela qu'on commente ? Est-ce qu'on se sert de $nb_prestas ailleurs dans le bloc ? Etc.
De manière plus fondamentale, et pour répondre de manière peut être plus argumentée que je ne l'ai fait précédemment à Philou67430, je trouve que nommer explicitement la variable de boucle dans un while (<...>) ou un foreach tend non seulement à parasiter la lecture plutôt qu'apporter du sens (à l'exception notable de certaines boucles imbriquées), mais peut également s'avérer dangereux. Je le démontre sur ce code extrait d'un autre fil:
J'ai déjà dit dans le fil en question tout le bien que je pensais de l'initialisation de @level_list en ligne 2, et de la boucle en ligne 17, tu as répondu, je n'y reviendrai pas. Intéressons-nous ici à la variable $inter. Comme tu le sais puisque tu le rappelle obligeamment dans ton tutoriel, c'est (je cite) un alias sur chaque élément successif du tableau ou de la liste ; en modifiant $item, on modifie bien le contenu du tableau. En ligne 15 tu modifies @sommaire. Est-ce délibéré ? Il semble que non, puisque tu produits @new_sommaire, et que par ailleurs cette modification ne sert pas dans l'algorithme. Aurais tu codé cette ligne 15 comme suitet utilisé $_ dans le push de la ligne 16, si tu n'avais pas déclaré $inter ? Probablement pas, car dans ce cas une myriade de signaux d'alarme auraient retenti dans ta tête, même à 1h30 du matin. En l'occurrence, rien n'a retenti, et quand tu as repris ton programme le lendemain à tête reposée tu n'as rien vu de bizarre. CQFD. (Tu me diras que ce n'est pas un bug, que le programme fonctionne quand même, que tu l'aurais corrigé dans une version de production, bla bla bla. Pour moi il reste que ça fait mauvais effet.)
Code : Sélectionner tout - Visualiser dans une fenêtre à part $_ = join '-', @out[0..$level];
Tant qu'on est dans le nommage, ta déclaration de $level en ligne 7 me fait plus que tiquer. Pas parce que tu introduits une variable, mais parce que tu l'appelles $level, et que ça frotte sévèrement avec @level_list. Le level de $level, c'est la profondeur de l'entrée courante sur laquelle on travaille (entre 0 et 2). Les level de @level_list, ce sont les index numériques maximaux atteints à ce stade pour chaque niveau de profondeur dans le sommaire (de 1 au nombre de sections rencontrées jusqu'à présent à chaque niveau de profondeur). Franchement, c'est extrêmement perturbant pour quelqu'un qui lit ton code, et prétendre qu'il y gagne en clarté me semble pour le moins capillotracté.
Ne crois pas que je cherche à te prendre comme tête de turc, ce n'est vraiment pas le cas (ou peut-être un petit peu, mais uniquement parce qu'en tant que 'Membre Expert' il me semble que tu aurais vocation à être exemplaire : n'y vois donc rien de personnel). En particulier je suis parfaitement conscient que le code ci-dessus a été écrit à la va-vite à une heure tardive, a été publié dans une discussion qui ne s'adressait pas à des débutants, et n'est dans tous les cas certainement pas représentatif de ta production habituelle.
Mais je cherche effectivement à montrer, en particulier aux débutants qui nous lisent, que tes préconisations et celles de Philou67430 demandent en fait beaucoup plus de travail et de discipline qu'il n'y paraît au premier abord, et peuvent même s'avérer piégeuses. Et qu'elles ne sont clairement pas une garantie de qualité, ni même un garde-fou pouvant préserver de certaines erreurs. Et que du coup mes propres recommandations, bien que provenant d'un rédacteur nettement moins étoilé dans la marge, ne sont pas forcément complètement dépourvues de substance.
Sur la maintenabilité du code
C'est moi qui mets en gras le contenu entre parenthèses ci-dessous :
Je ne sais pas ce qu'il en est pour toi, mais en ce qui me concerne, la personne qui a écrit le code que j'ai pondu il y a trois mois est un étranger complet. On partage sans doute une certaine culture mais il y a de grandes chances que le concept de level qu'il utilisait à l'époque quand l'algorithme était tout chaud dans son crâne soit différent de celui que je vais plaquer maintenant sur la variable $level que j'y trouve. Parce qu'entre temps, j'ai travaillé sur autre chose, d'autres structures de données, avec un level tout aussi pertinent mais différent de celui là.
Ca n'est pas différent de la situation dans laquelle se trouverait un autre programmeur qui aurait à comprendre et à intervenir sur ce code.
Quand j'en arrive au point où un code semble fonctionner, j'ai tendance à réduire le nombre de variables (en particulier toute variable qui n'est utilisée qu'une fois est sauf rare exception condamnée à disparaître, exemple ici), et je m'assure que celles qui restent sont vraiment essentielles. J'essaie ensuite de généraliser le code autant que possible, ce qui va déporter un certain nombre de variables à leur vraie place, à savoir des paramètres ou des options, qui sont documentés. Il est rare que je donne un nom très significatif aux variables qui restent à ce stade. Par contre je peux leur associer un commentaire explicatif.
Résultat : la personne qui aura à intervenir sur ce code, que ce soit moi ou un autre, devra se le réapproprier comme je l'évoquais au début de ce post. Elle ne sera pas distraite ou fourvoyée par une dénomination étrangère ou nébuleuse. Et c'est une bonne chose.
Cette méthode ne m'est pas venue par hasard. C'est le résultat de 30+ années d'expérience de programmeur dans des langages variés. Mes priorités sont que mon code soit 1) correct 2) maintenable. Si pour les assurer je dois sacrifier une prétendue intelligibilité qui ne serait de toute façon que de facade, je le fais sans remords. Ca ne veut pas dire que je produis du code délibérément obscur. Mais du code concis, oui. Et c'est une vertu.
Pour qu'on puisse partager une même compréhension d'un code, le plus important est qu'on en ait la même lecture. C'est pourquoi je considère qu'une des premières choses que les débutants doivent maîtriser est la différence entre contexte scalaire et contexte de liste, et la lecture correcte des indexations et tranchages. Cela n'est pas difficile, et évite de s'embarrasser de règles nuisibles, comme l'affirmation "$a[@b] n'a pas vraiment de sens" ou "est un exemple de ce qu'il ne faut pas faire", qui reposent en fait selon moi sur un processus de lecture approximatif, et sont rendues caduques par cette maîtrise. Et pour le coup je reconnais que je t'en veux de propager ce type de "règles" et surtout de persister. Aucune "règle" de ce type ne figure dans les perlfaqs, et ce pour de bonnes raisons.
Cela ne signifie pas que les conventions de codage soient à jeter. Mais selon moi elles servent plus à faciliter la collaboration au sein d'une équipe qu'à garantir une quelconque qualité. Et en fait, en dehors de conventions de formatage (pour lesquelles le plus simple est de s'aligner sur perlstyle) et peut-être de quelques patrons de codage ou conventions de passage de paramètres, il n'y a pas grand chose à convenir pour peu qu'on lise Perl de la même manière...
Il reste vrai qu'un programmeur ou un groupe de programmeurs peut bénéficier de garde-fous. Mais pour moi et depuis des années ces garde-fous sont assurés par une politique très agressive de test, que ce soit pour des modules ou pour des scripts. J'en ai donné des exemples dans ce fil. C'est beaucoup de travail. Mais en fin de compte c'est ça qui donne au final le plus confiance quand je dois reprendre mon code. Et si je dois reprendre celui des autres, et que la base de test est inexistante ou me paraît insuffisante, je commence par la créer ou l'étoffer avant même de toucher au code lui même.
Bon, j'espère ne pas avoir été trop toxique... J'ai probablement tendance à réagir violemment face à certaines recommandations, pour les avoir en fait respectées à un certain stade de mon évolution de programmeur, et pour avoir réalisé plus tard à quel point elles m'avaient nui en réalité... Mais chacun élève sa statue intérieure, et contribue à l'édifice collectif, à sa manière. Ce que j'ai décrit fonctionne pour moi. Que chacun prenne ses responsabilités .
Et je reste bien entendu ouvert à la discussion
Partager