Envoyé par
Michael Guilloux
Si vous pensez avoir besoin d'un commentaire pour expliquer ce qu'est un code, ils proposent alors de procéder d'abord à l'une des opérations suivantes :
1. Introduire une variable explicative
[...]
2. Extraire une méthode
[...]
3. Utiliser un nom d'identificateur plus descriptif
[...]
4. Ajouter un contrôle dans le cas où votre code a des hypothèses
[...]
Perso, j'utilise souvent les méthodes 1-3 pour éviter les commentaires. La 4 en revanche pour moi n'a rien à voir : c'est obligatoire pour tout paramètre de fonction publique ne pouvant être garanti valide, de façon à générer des exceptions claires le cas échéant. Pour éviter d'en mettre trop, je minimise les cas invalides : soit en exploitant toutes les valeurs possibles (e.g. null = paramètre facultatif non fournit), soit en faisant des classes dédiées ne pouvant générer que des valeurs valides, type énumérations et leurs compositions.
Une autre technique est d'insérer non pas un commentaire mais un TODO (oui, c'est un commentaire, mais l'EDI en gère l'affichage et facilite l'accès). Le message mentionne alors les défauts du code et si possible suggère des améliorations. L'idée part du principe que tout commentaire expliquant ce que le code fait indique par définition un code mal fait, ce qui ne devrait arriver que quand on ne prend pas le temps de concevoir correctement ledit code. Ça peut se justifier en cas d'urgence, mais ça veut dire qu'il est nécessaire d'y revenir, d'où le TODO pour indiquer qu'il y a encore quelque chose à faire ici.
Envoyé par
bcag2
G19 et G20 pages 318 et 319 de «Coder proprement» de Robert C.Martin (ISBN 978-2-7440-2583-9)
… rien de nouveau
Merci pour la référence. Ajouté à la bibliothèque. {^_^}
Envoyé par
transgohan
Je serai mitigé pour ma part...
J'aurai tendance à dire que mettre des commentaires partout est inutile mais à côté de cela je travaille sur du code très gros et très complexe et sans les commentaires inutiles cela devient une galère monstrueuse pour trouver rapidement ce que l'on cherche par simple méconnaissance du code concerné...
L'architecture est la première à montrer qu'un code est mal fait : si tu ne t'y retrouves pas, c'est que la conception a été bâclée. Je dis pas que les auteurs sont des neuneus, juste que la conception n'a pas été poussée aussi loin qu'il aurait fallu. De là, soit on décide enfin de s'y mettre et on prend le taureau par les cornes, soit on dit amen et on fait avec. Après, faut assumer, faut pas se dire que les codes comme ça, on n'y peut rien.
Et je maintiens malgré ses réponses
[1][2] : soit on prend le temps nécessaire pour concevoir, soit on met ce temps sur autre chose, ça ne veut pas dire que le problème est complexe "par nature" et qu'on n'y peut rien. Ce sont des choix, il faut les assumer en disant "on met des commentaires parce qu'on n'a pas le temps de faire du refactoring" et non "on met des commentaires parce que c'est complexe". Les commentaires ne sont naturellement utiles que là où c'est optimisé, c'est à dire là où on préfère augmenter les performances au détriment de la simplicité du code, et donc de sa maintenabilité. Ce genre de choix se justifie, mais ne devrait intervenir que dans certains blocs de code où le performance se fait désirer. Si la majeure partie du code doit être optimisée, c'est soit que tu as mal choisit ton architecture ou ton algo (cf.
l'anecdote de CodeurPlusPlus), soit que tu essayes de faire rentrer un Windows 7 sur une carte à puce, et donc que tu as mal calibré ton matériel pour les fonctionnalités que tu souhaites y mettre. Comme les glaces à 2 boules où tu essayes d'en forcer une 3e : s'il y en a une qui tombe, ça n'étonnera personne, et on ne rejettera pas la faute sur le cornet trop petit, mais sur celui qui aura voulu mettre 3 boules dans une contenance pour 2. Quoi qu'il en soit, ce sont des problèmes de choix, et non de nature. Donc soit on fait et on prend ses responsabilités, soit on fait pas.
J'adresse tout de suite les arguments "vieux code" : on parle là de pratique, ça ne sert à rien de parler de vieux code. Est-ce qu'on irait dire que Newton n'a pas fait une bonne théorie avec sa mécanique classique parce qu'il parle de la gravité comme d'une force plutôt que comme d'une déformation de l'espace-temps, comme Einstein et sa relativité ? Les recommandations d'aujourd'hui s'appliquent aux pratiques d'aujourd'hui avec les outils d'aujourd'hui. Si on suggère de donner des noms explicites aux fonctions, c'est parce qu'on part du principe qu'on a des fonctions, qu'on peut leur donner un nom, et que celui-ci n'est pas limité à quelques caractères. Dire qu'on ne peut pas faire cela avec du code d'il y a 30 ans ne remet pas en cause la recommandation, car aujourd'hui vous ne feriez pas du code d'il y a 30 ans. Une antiquité, on la prend avec soin pour ne pas la casser, et on fait ce qu'on peut avec jusqu'à ce qu'on ait du neuf. Ça ne remet pas en cause les nouvelles normes pour le neuf.
C'est d'ailleurs généralisable aux "codes où c'est pas possible". Si je ne m'abuse, la
programmation fonctionnelle pure et dure n'a pas de variable au sens usuel car pas d'affectation, donc introduire une variable intermédiaire n'a juste pas de sens. Ça ne remet pas en cause la recommandation 1, celle-ci n'est juste pas applicable dans ce cas et il faudra donc trouver autre chose si la lisibilité n'est pas terrible (e.g. introduire une fonction intermédiaire, si je ne me trompe pas, autrement dit la recommandation 2).
Envoyé par
BugFactory
Un autre conseil : penser à son public. Mon code est souvent lu par des stagiaires. Dans ce cas, le conseil d'éviter les commentaires évident n'est pas valable : pour un débutant, rien n'est évident. Je profite des commentaires pour signaler les designs pattern, etc. Ça évite qu'ils ne saccagent l'architecture pour résoudre un ticket.
Et si tu as oublié de mettre un commentaire ici ou là ? Si le dév est débutant, soit on le forme, soit on introduit un intermédiaire, soit (vive les forks !) on lui fait faire des pull requests, de façon à s'assurer que toutes ses modifs soient validées avant de les intégrer. Le cas échéant, on lui fournit un feedback pour qu'il corrige. Le jour où il est jugé apte au combat, on lui donne les droits de pousser directement sur le dépôt, pas avant.
On ne donne pas le volant à une personne qui passe tout juste son code. Un débutant, on le traite comme tel, sinon on est soi-même responsable des bourdes du nouveau pour lui avoir mis une arme chargée entre les mains.
Envoyé par
aepli
Il peut y avoir des commentaires inutiles, mais la plus part du temps ce n'est pas le cas.
En fait j'utilise les fonctions de certains scripts de création d'aide en ligne à l'aide de commentaires.
Du coup, je décrit de manière intelligible ce que fait tel ou tel fonction, les paramètres, les entrée, les sortie, etc.
Par contre à l'intérieur du code, il y a très peu de commentaires, seul les cas particuliers sont expliqués ou les manières d'utiliser tel ou tel API, lorsque j'ai croché pour l'implémentation.
Si j'ai bien compris, tu parles de documenter la fonction, pas de la commenter. La documentation est faite
par l'implémenteur de la fonction pour indiquer comment l'utiliser. Le commentaire est fait
par l'utilisateur pour indiquer comment il l'a utilisé. On peut dire aussi que la documentation vient
avant l'implémentation (c'est parce que tu veux faire une fonction pour faire telle chose que tu décides de l'implémenter de telle manière), alors que le commentaire vient
après (tu ajoutes un commentaire pour parler du code que tu viens d'écrire). Ce n'est pas la même chose.
Du coup, mention spéciale à gagache :
Envoyé par
gagaches
Et oui, le commentaire est fiable dans ce cas. Et bien sûr que j'ai gagné du temps.
Le dev a indiqué ce qu'il voulait faire ...
Si ça vient avant, alors c'est ce que tu devrais voir dans la doc, et non en commentaire. Pour rappel, les bonnes pratiques actuelles recommandent l'
inversion de dépendance, tu devrais donc avoir une abstraction/interface qui indique la fonction et la documente. Ajouté à cela, tu dois avoir une implémentation de cette interface avec un choix d'algo particulier. Auquel cas, l'algo que tu utilises sera décrit dans la doc de cette implémentation et non en tant que commentaire dans le code, car l'objectif même de l'implémentation est d'utiliser cet algo. Si tu veux en changer, tu ne modifiera pas le code, tu utiliseras une nouvelle implémentation basée sur un autre algo, mais remplissant toujours la même fonction.
Comme dit par d'autres, la documentation il la faut tout le temps, que la méthode soit complexe ou non. Elle indique ce qu'un éventuel utilisateur de la fonction doit savoir pour l'utiliser correctement. Celui-là ne doit alors
pas avoir besoin de lire le code de la fonction pour pouvoir l'utiliser sereinement. Dans le cas de l'interface, il l'utiliseras quand il aura besoin de la fonctionnalité. Dans le cas de l'implémentation, il l'utiliseras quand il jugera que son contexte justifie de favoriser cette implémentation là plutôt qu'une autre. Les commentaires, eux, se trouvent au coeur d'une implémentation, et ne sont voués à être lus si le code correspondant ne l'est pas non plus. D'où mon opposition à Bryce de Mouriès, qui dit que :
Envoyé par
Bryce de Mouriès
je préfère largement lire les commentaires jusqu'à trouver l'endroit qui m'intéresse plutôt que lire le code
Dans ce cas, ce que tu cherches c'est la documentation : si le code ne t'intéresse pas, fout ça dans une fonction bien nommée. Pas besoin de surcharger ta lecture avec un commentaire + un code, alors qu'un appel de fonction, typiquement équivalent au commentaire, suffit. C'est d'autant plus vrai avec les
fluent interfaces.
Au passage :
Envoyé par
Bryce de Mouriès
lire le code c'est comme lire une langue étrangère, on aura beau la connaître il y a toujours un travail de traduction dans la tête. Alors que lire un texte se fait naturellement.
Tant qu'il est dans la même langue. En contexte international, je suis pas convaincu que l'argument tienne longtemps, chacun ayant son "anglais".
Pour ce qui est des "non, non et non" de
jopopmk, je suis du même avis que
Cincinnatus : ne pas confondre le boulot du développeur à celui du compilateur. L'optimisation de la
syntaxe (e.g. moins de lignes, moins d'appels), c'est le boulot du compilateur. Le dév doit optimiser la
sémantique (e.g. identifier les bons concepts et leurs relations, choisir la bonne architecture, le bon algo).
Quant à
l'argument de Pyramidev comme quoi qu'il faut faire des aller-retour pour voir l'implémentation des sous fonctions ce n'est pas un bon argument :
- soit on s'intéresse à la fonction appelante, et dans ce cas la fonction appelée on se contente de comprendre ce qu'elle apporte à celle-ci par son nom et sa doc, je rejoins donc martopioche sur ce point là, et le contre argument n'y change rien car on change de problème (ce n'est pas que le commentaire est nécessaire, mais que la doc est absente ou incomplète, l'un n'excusant pas l'autre) ;
- soit on s'intéresse à la fonction appelée et dans ce cas la fonction appelante on n'en a rien à faire, si tant est que la fonction appelée est faite proprement ;
- soit on s'intéresse aux deux, alors sous-fonction ou pas, il faudra lire les deux.
Si tu parles de l'effort à fournir pour jongler car il faut se déplacer dans le code, alors ce n'est encore une fois pas un bon argument : utilise un EDI. Sous Eclipse, j'arrive sur un appel de fonction, je fais F3 (ou CTRL+clic pour ceux qui sont plus souris) et j'accède à la fonction appelée, quand à alt+gauche il me fait revenir à la fonction appelante. Ce genre d'argument, c'est le même que se plaindre que le binaire est pas super lisible : on a évolué depuis, il faudrait peut-être se mettre à jour. Pareil pour le code mort d'un autre intervenant : on ne le met pas en commentaire, on le supprime. Et si on veut pouvoir le récupérer, on s'assure d'utiliser un système de gestion de version. À chaque besoin sa solution.
Envoyé par
clementmarcotte
je dirais qu'il y a au moins trois occasions où des commentaires sont pratiquement obligatoires, ne serait-ce que par respect pour lecteurs.
1) Quand on veut déposer le programme-source sur un site où de parfaits débutants pourraient l'utiliser
2) Quand on est obligé, pour des raisons d'optimisation, ou d'autres raisons techniques, d'utiliser une sorte de "passe croche" inédite ou inconnue. (Ne serait-ce que parce que la mémoire est une faculté qui oublie)
3) Quand on sait que le programme peut être utilisé très longtemps. (Comme les antiques programmes en COBOL avec des années à juste deux chiffres qui étaient encore là en 1999.)
1) Si c'est pour les débutants, c'est un code de tuto, ça n'a pas vocation à être utilisé tel quel dans un projet. Ce n'est pas une question de respect, mais de cible, un code de tuto sera aussi simplifié pour se concentrer sur certains aspects, sinon ce ne sera pas un bon code de tuto. Si tu développes une lib dont tu fournis les sources pour être réutilisée par des devs, c'est le code qui les intéressera avant tout, les commentaires éventuellement après. Justement parce que l'objectif est d'intégrer le code, pas les commentaires.
2) Optimisation, OK.
3) Peu pertinent : Si le code ne permet pas de représenter le métier fidèlement, tu mets des commentaires pour pallier les limites du code, c'est bon tout de suite, pas pour plus tard. S'il le permet, mettre des commentaires n'y changera rien, car si le code n'est plus clair dans 30 ans, c'est que le métier aura changé, donc tes commentaires écrits avec la logique métier de l'époque ne seront pas plus clairs. Le seul avantage devient alors les infos supplémentaires que fournissent ton commentaire, de là la question fondamentale : c'est du commentaire ou de la doc ?
Envoyé par
gagaches
Les commentaires ont pour but de rendre le code compréhensible.
Là, c'est subtil, mais c'est faux : les commentaires ont pour but d'ajouter des informations au code, quelles qu'elles soient. Elles n'ont pas vocation à le rendre plus compréhensible, bien que ce soit un usage possible. En l'occurrence, si on part de ce principe, alors par définition un code non commenté n'est pas compréhensible... alors comment le gars a fait pour créer ce code si c'est incompréhensible ? Il ne faut pas les réduire à un seul usage. Surtout quand cet usage survient justement par un manque de qualité du code : ça devient une excuse pour ne pas coder mieux.
Envoyé par
martopioche
La présence des getters/setters a un grand intérêt : elle permet de déterminer qu'un code "orienté objet" a été écrit par des développeurs qui n'ont aucune notion de POO.
Objection ! Les getters sont à peu près toujours nécessaires en POO, sous une forme ou sous une autre : un objet dispose généralement de propriétés, un getter ne fait qu'y donner accès, autrement l'objet on n'en fait pas grand chose. Quant aux setters, la POO ne se limite pas à des objets immutables : si tu crées un conteneur, par exemple un singleton de configuration ou un builder, les setters sont nécessaires pour affecter les valeurs.
Envoyé par
deuz59
Un exemple tout bête : préciser l'unité de mesure dans une variable métrique (temps, distance, etc...).
Si j'ai une API qui me met demande un paramètre "time" (passons sur le fait que "time" reste hyper générique et pourrait être plus précis quand à la signification de la variable) et que je dois lire la doc pour savoir que c'est en secondes, pourquoi ne pas directement indiquer "timeInSeconds" !
Parce que "seconds" est encore mieux ? Si la fonction c'est "wait(...)", ça me semble suffisant, pas besoin de faire des noms à rallonge non plus. Utiliser d'abord un terme (seconds), et si on a besoin de nommer plus d'une variable de la même manière, ajouter en plus leurs usages respectifs (secondsToWait + secondsToRun).
Partager