Le code commenté peut-il être une documentation précieuse?

83

J'ai écrit le code suivant:

if (boutique == null) {
    boutique = new Boutique();

    boutique.setSite(site);
    boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
    boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
    boutique.setNom(fluxBoutique.getNom());
    boutique.setSelected(false);
    boutique.setIdWebSC(fluxBoutique.getId());
    boutique.setDateModification(new Date());

    boutiqueDao.persist(boutique);
} else {
    boutique.setSite(site);
    boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
    boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
    boutique.setNom(fluxBoutique.getNom());
    //boutique.setSelected(false);
    boutique.setIdWebSC(fluxBoutique.getId());
    boutique.setDateModification(new Date());

    boutiqueDao.merge(boutique);
}

Il y a une ligne commentée ici. Mais je pense que cela rend le code plus clair en précisant la différence entre ifet else. La différence est encore plus marquée avec la mise en surbrillance des couleurs.

Commenter un code comme celui-ci peut-il être une bonne idée?

Alexis Dufrenoy
la source

Réponses:

109

La plupart des réponses se concentrent sur la façon de reformuler ce cas spécifique, mais permettez-moi de donner une réponse générale à la raison pour laquelle le code commenté est généralement mauvais:

Tout d'abord, le code commenté n'est pas compilé. C'est évident, mais cela signifie que:

  1. Le code pourrait même ne pas fonctionner.

  2. Lorsque les dépendances du commentaire changent, cela ne va évidemment pas casser.

Le code commenté est très "code mort". Plus il reste assis longtemps, plus il pourrit et fournit de moins en moins de valeur au prochain développeur.

Deuxièmement, l'objectif n'est pas clair. Vous avez vraiment besoin d'un commentaire plus long qui fournisse un contexte expliquant pourquoi il existe des lignes commentées de manière aléatoire. Lorsque je ne vois qu'une ligne de code commentée, je dois chercher comment cela est arrivé pour comprendre pourquoi il est arrivé là. Qui l'a écrit? Quel commit? Quel était le message / contexte de validation? Etc.

Envisager des alternatives:

  • Si l'objectif est de fournir des exemples d'utilisation d'une fonction / API, fournissez un test unitaire. Les tests unitaires sont du code réel et ne fonctionneront plus quand ils ne seront plus corrects.
  • Si le but est de conserver une version précédente du code, utilisez le contrôle de code source. Je préférerais de beaucoup extraire une version précédente, puis basculer les commentaires dans la base de code pour "annuler" un changement.
  • Si le but est de conserver une autre version du même code, utilisez le contrôle de source (à nouveau). C'est à cela que servent les branches, après tout.
  • Si le but est de clarifier la structure, réfléchissez à la manière dont vous pouvez restructurer le code pour le rendre plus évident. La plupart des autres réponses sont de bons exemples de la manière dont vous pourriez le faire.
Chris Pitman
la source
5
Je pense qu'il vous manque une raison importante: Documentation: si le but est de documenter les options de conception alternatives, une explication de la solution de remplacement et en particulier la raison pour laquelle elle a été supprimée doivent être fournies à la place du code d'origine.
Sarien
14
Les options de conception sont mieux expliquées dans un langage humain que dans un langage de programmation.
Mark E. Haase
3
Comment serait-il possible pour les développeurs ultérieurs prenant en charge mon projet de savoir qu’une implémentation alternative / précédente / échouée existe dans le contrôle de code source? Les nouveaux développeurs devraient-ils consulter tous les historiques de versions et les journaux de modifications? Ou est-ce une pratique courante d’utiliser un commentaire pour créer un lien vers le hachage d’un commit précédent pour chaque implémentation alternative utile? Si oui, je n'ai jamais remarqué.
Moobie
Il y a une mise en garde à cela cependant. Parfois, deux approches de code équivalentes peuvent différer en performances et en réactivité d'une manière performante et lisible. Dans un tel cas, il est acceptable d' utiliser la variante performante, mais placez la variante lisible dans des commentaires afin de faciliter la compréhension de l'objectif du code. Parfois, une ligne de code (commentée) peut être plus claire qu'une explication détaillée.
Flater
263

Le plus gros problème avec ce code est que vous avez dupliqué ces 6 lignes. Une fois que vous avez éliminé cette duplication, ce commentaire est inutile.

Si vous créez une boutiqueDao.mergeOrPersistméthode, vous pouvez la réécrire comme suit:

if (boutique == null) {
    boutique = new Boutique();
    boutique.setSelected(false);
}

boutique.setSite(site);
boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
boutique.setNom(fluxBoutique.getNom());
boutique.setIdWebSC(fluxBoutique.getId());
boutique.setDateModification(new Date());

boutiqueDao.mergeOrPersist(boutique);

Le code qui crée ou met à jour un certain objet est commun, vous devez donc le résoudre une fois, par exemple en créant une mergeOrPersistméthode. Vous ne devez certainement pas dupliquer tout le code de mission pour ces deux cas.

De nombreux ORM ont construit un support pour cela d'une certaine manière. Par exemple, ils peuvent créer une nouvelle ligne si la valeur idest zéro et mettre à jour une ligne existante si la valeur idest différente de zéro. La forme exacte dépend de l'ORM en question, et comme je ne connais pas bien la technologie que vous utilisez, je ne peux pas vous aider.


Si vous ne souhaitez pas créer de mergeOrPersistméthode, vous devez éliminer la duplication d'une autre manière, par exemple en introduisant un isNewBoutiqueindicateur. Cela n’est peut-être pas beau, mais c’est quand même bien mieux que de dupliquer toute la logique d’attribution.

bool isNewBoutique = boutique == null;
if (isNewBoutique) {
    boutique = new Boutique();
    boutique.setSelected(false);
}

boutique.setSite(site);
boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE + fluxBoutique.getLogo());
boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE + fluxBoutique.getUrl());
boutique.setNom(fluxBoutique.getNom());
boutique.setIdWebSC(fluxBoutique.getId());
boutique.setDateModification(new Date());

if (isNewBoutique)
    boutiqueDao.persist(boutique);
else
    boutiqueDao.merge(boutique);
CodesInChaos
la source
166

C'est une idée absolument horrible . Cela n'indique pas clairement l'intention. Le développeur a-t-il commenté la ligne par erreur? Pour tester quelque chose? Que se passe-t-il?!

Mis à part le fait que je vois 6 lignes qui sont absolument égales dans les deux cas. Au lieu de cela, vous devriez empêcher cette duplication de code. Il sera alors plus clair que dans un cas, vous appelez en outre setSelected.

JustAnotherUserYouMayKnowOrNot
la source
9
D'accord. Je suppose que voir que la ligne commentée est un ancien comportement qui a été supprimé. Si un commentaire est nécessaire, il doit être en langage naturel et non en code.
Jules
4
Je suis tout à fait d'accord! J'ai récemment passé des heures à essayer de comprendre et de nettoyer certaines applications dont j'ai hérité qui sont presque complètement illisibles à cause de cette pratique. Il inclut également le code qui a été déconnecté de tout autre code mais non supprimé! Je crois que c'est l'un des objectifs principaux des systèmes de contrôle de version. Il contient des commentaires ainsi que les changements qui vont avec. En fin de compte, au moins deux semaines de travail ont été ajoutées à mon assiette, en grande partie à cause de cette pratique.
bsara
point de vue similaire dans ce post: Ne pas polluer le code avec le code commenté
Nick Alexeev
120

Non, c'est une idée terrible. En me basant sur ce code, les pensées suivantes me viennent à l’esprit:

  • Cette ligne est commentée car le développeur la déboguait et a oublié de restaurer la ligne à son état antérieur.
  • Cette ligne est commentée car elle faisait autrefois partie de la logique métier, mais ce n'est plus le cas
  • Cette ligne est commentée car elle posait des problèmes de performances en production et le développeur souhaitait voir quel était son impact sur un système de production.

Après avoir vu des milliers de lignes de code commenté, je fais maintenant la seule chose sensée quand je le vois: je le supprime immédiatement.

Il n'y a aucune raison valable pour archiver le code commenté dans un référentiel.

En outre, votre code utilise beaucoup de duplication. Je vous suggère d’optimiser cela le plus rapidement possible pour la lisibilité humaine.

Dibbeke
la source
1
Cependant, si je me débarrasse du code dupliqué, cela peut difficilement être vu comme une optimisation, je pense.
Alexis Dufrenoy
23
c'est une optimisation pour la lisibilité humaine
jk.
11
@Traroth vous permet d'optimiser la vitesse, l'utilisation de la mémoire, la consommation d'énergie ou toute autre métrique; je ne vois donc pas que vous ne pouvez pas optimiser la lisibilité (même si, en tant que métrique, il est un peu plus complexe)
jk.
3
En effet, je voulais dire la lisibilité humaine. Petit indice ici: votre code le plus important en matière de programmation. Donc, moins est vraiment plus ici.
Dibbeke
4
Les logiciels en tant que passif sont également traités à l' adresse c2.com/cgi/wiki?SoftwareAsLiability De là: "Produire plus de code n'est pas toujours un gain. Le code est coûteux à tester et à maintenir, donc si le même travail peut être fait avec moins de code que C’est un atout. Ne commentez pas le code mort, mais simplement le supprimer. Le code commenté devient vite obsolète et inutile, vous pouvez donc le supprimer le plus tôt possible, pour que l’encombrement disparaisse. Conservez de bonnes sauvegardes pour faciliter les choses. . "
Ninjalj
51

Je voudrais juste ajouter à la réponse de CodesInChaos, en précisant que vous pouvez le reformuler davantage en petites méthodes . Le partage de fonctionnalités communes par composition évite les conditions:

function fill(boutique) {    
  boutique.setSite(site);
  boutique.setUrlLogo(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getLogo());
  boutique.setUrlBoutique(CmsProperties.URL_FLUX_BOUTIQUE+fluxBoutique.getUrl());
  boutique.setNom(fluxBoutique.getNom());
  boutique.setIdWebSC(fluxBoutique.getId());
  boutique.setDateModification(new Date());
}    

function create() {
  boutique = new Boutique();      
  fill(boutique);
  boutique.setSelected(false);
  return boutiqueDao.persist(boutique);
}

function update(boutique) {
  fill(boutiquie);
  return boutiquieDao.merge(boutique); 
}

function createOrUpdate(boutique) {
  if (boutique == null) {
    return create();
  }
  return update(boutique);  
}
Alexander Torstling
la source
6
Je pense que c'est la suggestion la plus propre ici.
Alexis Dufrenoy
+1, et j'ajouterais que plus vous éviterez de faire passer des nullobjets, mieux ce sera (je trouve cette solution un bon exemple).
Nadir Sampaoli
Je passerais boutiqueDaocomme entrées à createet update.
Happy Green Kid Naps
Comment cela peut-il fonctionner? Comment savoir quand appeler et quand appeler la mise à jour? Le code original se réfère à boutique et sait s’il doit être mis à jour ou créé. Cela ne fait rien jusqu'à ce que vous
appeliez
Lyrion: Trivial, je vais ajouter ce code également pour plus de clarté.
Alexander Torstling
27

Bien que ce ne soit clairement pas un cas valable pour un code commenté, il existe une situation qui, à mon avis, le justifie:

// The following code is obvious but does not work because of <x>
// <offending code>
<uglier answer that actually does work>

C'est un avertissement à ceux qui le verront plus tard que l'amélioration évidente ne le soit pas.

Edit: Je parle de quelque chose de petit. Si c'est grand, vous expliquez plutôt.

Loren Pechtel
la source
5
Quel est le problème avec // the following part done like it is because of X? Expliquez pourquoi vous avez fait quelque chose comme vous l'avez fait, pas pourquoi vous ne l'avez pas fait d'une manière particulière . Dans votre exemple particulier, cela élimine le besoin éventuel d'un bloc important de code commenté. (Je n'ai pas voté vers le bas, mais je peux certainement voir pourquoi cela aurait été voté.)
a CVn
13
Michael, parce que cela indique clairement aux autres programmeurs (et à vous-même, jours / semaines / mois plus tard) que vous avez effectivement essayé cette approche plus propre / plus intelligente, mais non, cela n'a pas fonctionné à cause de X, donc ils ne devraient pas la peine d'essayer à nouveau. Je pense que cette approche est tout à fait légitime et que cette réponse tristement enterrée a suscité le vote populaire.
Garrett Albright
1
@ GarrettAlbright: Merci, je suis heureux de voir que quelqu'un l'obtient.
Loren Pechtel
3
@ LorenPechtel: Non seulement cela, je voulais écrire plus ou moins exactement la même chose. Il existe des situations où il est vraiment très utile de savoir rapidement quelles solutions "évidentes" ont déjà été essayées sans succès et pourquoi elles ne fonctionnent pas.
JensG
3
Outre le code défaillant avec explication, je voudrais également commenter les implémentations alternatives du code qui pourraient être plus efficaces dans un environnement de production différent. Par exemple, j'ai codé à la fois une version temporelle exponentielle simple d'un algorithme et une version temporelle polynomiale complexe. Mais dans la production actuelle, nc'est petit, et l'algo exponentielle est beaucoup plus rapide. Si quelque chose nchange par la suite, comment un futur développeur qui suivrait mon projet aurait-il connaissance d'une implémentation différente du code enfoui au cœur des centaines de commits dans le contrôle de source?
Moobie
14

Dans cet exemple spécifique, je trouve le code commenté très ambigu, en grande partie pour les raisons exposées dans la réponse de Dibkke . D'autres ont suggéré des moyens de reformuler le code pour éviter même la tentation de le faire. Toutefois, si cela n'est pas possible pour une raison quelconque (par exemple, les lignes sont similaires, mais pas assez proches), j'apprécierais un commentaire du type:

// Inutile de désélectionner cette boutique, car [WHATEVER]

Cependant, je pense qu'il y a des situations où laisser (ou même ajouter du code commenté) n'est pas répréhensible. Lorsque vous utilisez quelque chose comme MATLAB ou NumPY, on peut souvent écrire un code équivalent qui 1) effectue une itération sur un tableau, en traitant un élément à la fois ou 2) exploite tout le tableau à la fois. Dans certains cas, le dernier est beaucoup plus rapide, mais aussi beaucoup plus difficile à lire. Si je remplace un code par son équivalent vectorisé, j'intègre le code d'origine dans un commentaire proche, comme ceci:

%% Le code vectorisé ci-dessous fait ceci:

% for ii in 1:N
%    for jj in 1:N
%      etc.

% mais la version de la matrice est environ 15 fois plus rapide avec une entrée typique (MK, 03/10/2013)

Évidemment, il faut veiller à ce que les deux versions fassent la même chose et que le commentaire reste synchronisé avec le code réel ou est supprimé si le code change. Évidemment, les mises en garde habituelles concernant l'optimisation prématurée s'appliquent également ...

Matt Krause
la source
"Évidemment, il faut veiller à ce que les deux versions fassent en réalité la même chose et que le commentaire reste synchronisé avec ..." - vous avez expliqué pourquoi ce n'est pas une bonne idée.
Sleske
1
Eh bien, c'est un problème avec tous les commentaires, non? Certains codes vectorisés sont suffisamment opaques pour que les commentaires en valent la peine et il peut être utile de disposer d’une version "déroulée" pour le débogage.
Matt Krause
Vrai. Néanmoins, j'essaierais de garder le commentaire aussi bref que possible, de ne pas utiliser le code source complet. Quoi qu'il en soit, si vous avez un exemple, il serait bon de demander comment le rendre lisible au mieux (ici ou sur codereview.se).
Sleske
1
Dans votre dernier cas, je conserverais les deux variantes de code en tant que code compilable.
CodesInChaos
12

La seule fois où j'ai vu du code de commentaire utile était dans les fichiers de configuration, où le code de chaque option est fourni, mais mis en commentaire, ce qui facilite l'activation des paramètres en supprimant simplement les marqueurs de commentaire:

## Enable support for mouse input:
# enable_mouse = true

Dans ce cas, le code commenté aide à documenter toutes les options disponibles et leur utilisation. Il est également classique d'utiliser les valeurs par défaut dans l'ensemble, de sorte que le code documente également les paramètres par défaut.

Carl Smith
la source
7

De manière générale, le code est auto-documenté uniquement par la personne qui l'a écrit. Si de la documentation est requise, écrivez-la. Il est inacceptable de s'attendre à ce qu'un nouveau développeur dans une base de code source lise des milliers de lignes de code pour tenter de comprendre ce qui se passe à un niveau élevé.

Dans ce cas, la ligne de code commentée a pour but de montrer la différence entre deux instances de code en double. Au lieu d'essayer de documenter subtilement la différence avec un commentaire, réécrivez le code pour le rendre logique. Ensuite, si vous estimez toujours nécessaire de commenter le code, écrivez un commentaire approprié.

Mike Van
la source
2
Cela sonne tout à fait vrai. Beaucoup de gens (moi y compris) pensent que leur code est tellement génial qu'il n'a pas besoin de documentation. Cependant, tout le monde dans le monde le trouve encombrant, à moins qu'il ne soit complètement documenté et commenté.
Ryan Amos
"Le code est auto-documenté par la personne qui l'a écrit " - Choisissez un morceau de code complexe et non commenté que vous avez écrit il y a un an et essayez de le comprendre dans un temps limité. Vous ne pouvez pas? Ooops.
JensG
Je pense que c'est un peu plus nuancé. Beaucoup de code bien écrit est intelligible et peut être compris sans commentaires. Le problème est d’essayer de comprendre la situation dans son ensemble (même à un niveau assez local) lorsque vous n’avez que des détails complexes à traiter. Les commentaires sont utiles pour expliquer des morceaux de code non évidents, mais lorsque vous avez de bonnes docstrings, expliquant à quoi servent réellement chaque fonction, classe et module, vous avez beaucoup moins besoin d'aide pour comprendre la mise en œuvre.
Carl Smith
4

Non, le code commenté devient obsolète et devient vite pire que rien, il est souvent néfaste, car il cimente certains aspects de la mise en œuvre, ainsi que toutes les hypothèses actuelles.

Les commentaires doivent inclure les détails de l'interface et la fonction souhaitée. "fonction souhaitée": peut inclure, nous essayons d'abord, puis nous essayons cela, puis nous échouons de cette façon.

Les programmeurs que j'ai vus essaient de laisser des choses dans les commentaires sont juste en amour avec ce qu'ils ont écrit, ne veulent pas le perdre, même si cela n'ajoute rien au produit fini.

Grady Player
la source
2

Cela peut être très rare, mais pas comme vous l'avez fait. Les autres réponses ont assez bien expliqué les raisons.

L'un des rares cas est une spécification de modèle RPM que nous utilisons dans ma boutique comme point de départ pour tous les nouveaux packages, principalement pour s'assurer que rien d'important n'est laissé de côté. La plupart de nos paquets, mais pas tous, ont une archive contenant des sources qui porte un nom standard et qui est spécifiée par une balise:

Name:           foomatic
Version:        3.14
 ...
Source0:        %{name}-%{version}.tar.gz

Pour les packages sans source, nous commentons la balise et la plaçons au-dessus pour conserver le format standard et indiquer que quelqu'un s'est arrêté et a réfléchi au problème dans le cadre du processus de développement:

Name:           barmatic
Version:        2.71
 ...
# This package has no sources.
# Source0:        %{name}-%{version}.tar.gz

Vous n'ajoutez pas de code dont vous savez qu'il ne sera pas utilisé car, comme d'autres l'ont déjà expliqué, il pourrait être confondu avec quelque chose qui y appartient. Ça peut. Cependant, il serait utile d’ajouter un commentaire expliquant pourquoi le code attendu est manquant:

if ( condition ) {
  foo();
  // Under most other circumstances, we would do a bar() here, but
  // we can't because the quux isn't activated yet.  We might call
  // bletch() later to rectify the situation.
  baz();
}
Blrfl
la source
5
on peut soutenir que ce commentaire n'est pas commenté dans le code.
jk.
1
@jk: Vous avez sans doute raison.
Blrfl
1

Le code commenté n'est pas utilisé par l'application, il doit donc être accompagné de commentaires supplémentaires expliquant pourquoi il n'est pas utilisé. Mais dans ce contexte, il existe des situations où le code commenté peut être utile.

Ce qui me vient à l’esprit est le cas où vous résolvez un problème en utilisant une approche commune et attrayante, mais il s’avère que les exigences de votre problème actuel sont légèrement différentes de ce problème. En particulier, si vos besoins nécessitent considérablement plus de code, les responsables de la maintenance auront la tentation d'optimiser le code en utilisant l'ancienne approche, mais cela ne fera que ramener le bogue. Garder la "mauvaise" implémentation dans les commentaires aidera à dissiper cela, car vous pouvez l'utiliser pour illustrer exactement pourquoi cette approche est erronée dans cette situation.

Ce n'est pas une situation que je peux imaginer arriver très souvent. En général, il devrait suffire d’expliquer les choses sans inclure un exemple de "mauvaise" mise en oeuvre. Mais je peux imaginer un cas où cela ne suffira pas, alors puisque la question est de savoir si cela peut être utile, oui. Juste pas la plupart du temps.

Le Spooniest
la source
1
Désolé, je ne vois aucune valeur du code de commentaire. Le code mis en commentaire n'est pas utilisé, il n'a donc pas sa place dans le code de production.
Vladimir Kocjancic
1
Veuillez définir "utilisé".
JensG
Je pense qu'il voulait dire "exécuté"
Alexis Dufrenoy
-2

Cela ne semble pas bon mon pote.

Le code commenté est ... mais pas du code. Le code est pour la mise en œuvre de la logique. Rendre un code plus lisible en soi est un art. Comme @CodesInChaos a déjà suggéré que les lignes de code répétitives ne sont pas une très bonne implémentation de la logique .

Pensez-vous vraiment qu'un vrai programmeur préférera la lisibilité à une implémentation logique? (en passant, nous avons des commentaires et des «compléments» à mettre dans notre représentation logique).

En ce qui me concerne, on devrait écrire un code pour le compilateur et c'est bien - si "ça" le comprend. Pour la lisibilité humaine Les commentaires sont bons, pour les développeurs (à long terme), pour les personnes réutilisant ce code (par exemple, les testeurs).

Sinon, vous pouvez essayer quelque chose de plus flexible ici, quelque chose comme

boutique.setSite (site) peut être remplacé par

setsiteof.boutique (site). Il existe différents aspects et perspectives de la programmation orientée objet pour améliorer la lisibilité.

Bien que ce code semble être très attrayant au début et qu'on peut penser qu'il a trouvé un moyen de lisibilité humaine, le compilateur fait également son travail à la perfection. Nous commençons tous à suivre cette pratique, ce qui aboutira à un fichier flou qui deviendra moins lisible. dans le temps et plus complexe que cela va se développer.

Aura
la source
15
"En ce qui me concerne, on devrait écrire un code pour le compilateur" Oh, s'il vous plait, ne le faites pas. C'est comme ça que vous vous retrouvez avec des monstruosités qui semblent pouvoir être extraites directement du Concours C Obfuscated et autres. Les ordinateurs sont binaires, alors que les humains utilisent une logique floue (cela revient au double pour les propriétaires d’animaux domestiques, d’ailleurs). Le temps passé sur l’ordinateur est presque libre aujourd’hui (essentiellement l’utilisation d’électricité), alors que le temps consacré aux programmeurs est relativement coûteux. Ecrire du code pour les humains, et le compilateur le comprendra. Écrivez du code pour le compilateur sans égard pour les humains, et vous ne ferez pas beaucoup d'amis dans l'équipe.
un CVn
3
" écrire du code pour un compilateur " - En fait, vous ne le faites pas. La personne à laquelle vous devriez penser est celle qui a confié la tâche de maintenir votre code.
JensG