web-dev-qa-db-fra.com

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

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 rendant évidente la différence entre if et else. La différence est encore plus notable avec la mise en évidence des couleurs.

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

83
Alexis Dufrenoy

La plupart des réponses se concentrent sur la façon de refactoriser ce cas spécifique, mais permettez-moi de proposer 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, il ne se cassera évidemment pas.

Le code commenté est tout à fait un "code mort". Plus il reste longtemps, plus il pourrit et fournit de moins en moins de valeur au développeur suivant.

Deuxièmement, l'objectif n'est pas clair. Vous avez vraiment besoin d'un commentaire plus long qui fournit un contexte pour expliquer pourquoi il y a des lignes commentées au hasard. Quand je vois juste une ligne de code commentée, je dois rechercher comment elle est arrivée juste pour comprendre pourquoi elle y est arrivée. Qui l'a écrit? Quel engagement? Quel était le message/contexte de validation? Etc.

Envisagez 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 vrai code et se cassent lorsqu'ils ne sont 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ère de loin extraire une version précédente, puis basculer les commentaires dans la base de code pour "annuler" une modification.
  • Si le but est de conserver une version alternative du même code, utilisez le contrôle de code 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 de restructurer le code pour le rendre plus évident. La plupart des autres réponses sont de bons exemples de la façon dont vous pourriez procéder.
109
Chris Pitman

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

Si vous créez un boutiqueDao.mergeOrPersist méthode, vous pouvez réécrire ceci comme:

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 courant, vous devez donc le résoudre une fois, par exemple en créant une méthode mergeOrPersist. Vous ne devez certainement pas dupliquer tout le code d'affectation pour ces deux cas.

De nombreux ORM ont intégré le support de cette manière. Par exemple, ils peuvent créer une nouvelle ligne si le id est nul et mettre à jour une ligne existante si le id n'est pas nul. La forme exacte dépend de l'ORM en question, et comme je ne connais pas la technologie que vous utilisez, je ne peux pas vous aider.


Si vous ne souhaitez pas créer une méthode mergeOrPersist, vous devez éliminer la duplication d'une autre manière, par exemple en introduisant un indicateur isNewBoutique. Ce n'est peut-être pas joli, mais c'est toujours bien mieux que de dupliquer toute la logique d'affectation.

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);
263
CodesInChaos

C'est une idée absolument horrible. Il ne précise pas quelle est 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. Vous devez plutôt empêcher cette duplication de code. Ensuite, il sera plus clair que dans un cas, vous appelez également setSelected.

Non, c'est une terrible idée. Sur la base de ce morceau de code, les pensées suivantes me viennent à l'esprit:

  • Cette ligne est mise en commentaire car le développeur la déboguait et a oublié de restaurer la ligne à son ancien état
  • 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 a causé des problèmes de performances sur la production et le développeur voulait voir quel était l'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 raisonnable de consigner du code commenté dans un référentiel.

De plus, votre code utilise beaucoup de duplication. Je vous suggère d'optimiser cela loin pour la lisibilité humaine dès que possible.

120
Dibbeke

Je voudrais juste ajouter à la réponse de CodesInChaos, en soulignant que vous pouvez refactoriser 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);  
}
51

Bien que ce ne soit clairement pas un bon argument pour du code commenté, il y a une situation qui, je pense, 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 à quiconque le verra plus tard que l'amélioration évidente ne l'est pas.

Edit: je parle de quelque chose de petit. Si c'est gros, vous expliquez à la place.

27
Loren Pechtel

Dans cet exemple spécifique, je trouve le code commenté très ambigu, en grande partie pour les raisons décrites dans réponse de Dibkke . D'autres ont suggéré des moyens de refactoriser le code pour éviter même la tentation de le faire, cependant, 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 comme:

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

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

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

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

% mais la version matricielle s'exécute 15 fois plus vite sur une entrée standard (MK, 10/03/2013)

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

14
Matt Krause

La seule fois où j'ai vu du code commenté qui était utile était dans les fichiers de configuration, où le code pour chaque option est fourni, mais commenté, 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é permet de documenter toutes les options disponibles et comment les utiliser. Il est également classique d'utiliser les valeurs par défaut tout au long, de sorte que le code documente également les paramètres par défaut.

12
Carl Smith

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

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 qu'il ait du sens. Ensuite, si vous pensez toujours qu'il est nécessaire de commenter le code, écrivez un commentaire approprié.

7
Mike Van

Non, le code commenté devient obsolète, et est bientôt pire que sans valeur, il est souvent nocif, 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 prévue; "fonction prévue": peut inclure, d'abord nous essayons ceci, ensuite nous essayons cela, puis nous échouons de cette façon.

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

4
Grady Player

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

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

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

Pour les packages sans sources, nous commentons la balise et mettons un autre commentaire au-dessus pour conserver le format standard et indiquer que quelqu'un s'est arrêté et a pensé 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é parce que, comme d'autres l'ont couvert, il pourrait être confondu avec quelque chose qui y appartient. Ça peut. cependant, il est utile d'ajouter un commentaire expliquant pourquoi le code auquel on pourrait s'attendre 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();
}
2
Blrfl

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

Ce qui me vient à l'esprit est un 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 réel sont légèrement différent de ce problème. Surtout si vos besoins s'avèrent nécessiter considérablement plus de code, la tentation pour les responsables de "l'optimisation" du code en utilisant l'ancienne approche sera probablement forte, 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 incorrecte dans cette situation .

Ce n'est pas une situation que je peux imaginer se produire très souvent. Habituellement, cela devrait être suffisant pour expliquer les choses sans inclure un exemple de "mauvaise" implémentation. Mais je peux imaginer un cas où cela ne suffit pas, donc puisque la question est de savoir si cela peut être utile, oui, c'est possible. Mais pas la plupart du temps.

1
The Spooniest