Developpez.com

Le Club des Développeurs et IT Pro

Programmation : quand faut-il commenter son code ? Google s'invite dans le débat

Et montre que les commentaires peuvent très souvent être évités

Le 2017-07-19 11:43:08, par Michael Guilloux, Chroniqueur Actualités
En apprenant la programmation, votre professeur vous a certainement dit de toujours et bien commenter votre code. Rappelons que les commentaires sont des portions du code source ignorées par le compilateur ou l’interpréteur, car ils ne sont pas nécessaires à l’exécution du programme. Ils sont généralement insérés dans le code afin qu’il soit facile à comprendre et de sorte qu’on puisse le modifier facilement à l’avenir. Mais certains en font peut-être un peu trop avec les commentaires, en essayant de les placer à chaque petit coin du code ; une pratique qui est désapprouvée par beaucoup de développeurs expérimentés.

Pour ces derniers, si le code est tellement compliqué que cela doit être expliqué, il est presque toujours préférable d’améliorer le code que d’ajouter des commentaires. Dans un billet de blog datant de 2013, un développeur .NET du nom de Steve Smith a donc voulu trancher le débat en expliquant que « les commentaires doivent être généralement évités si le code peut dire ce qu’il fait. » Steve Smith pense en effet que « les bons commentaires disent ce que le code ne peut pas exprimer, comme pourquoi une technique particulière a été favorisée ou les dangers de l’optimisation d’un bloc de code. La plupart des autres types de commentaires sont simplement du bruit et leur présence encombre le code. »

Malgré tous les avis sur la question, la manière d’utiliser les commentaires reste une vieille question dans les habitudes de programmation. Google s’invite aujourd’hui dans le débat et montre qu’en réalité les commentaires peuvent très souvent être évités. « En lisant un code, souvent, il n'y a rien de plus utile qu'un commentaire bien placé. Cependant, les commentaires ne sont pas toujours bons. Parfois, le besoin d'un commentaire peut être un signe que le code devrait être refactorisé. Utilisez un commentaire lorsqu'il est impossible de faire en sorte que votre code s'explique par lui-même », expliquent Dori Reuveni et Kevin Bourrillion sur Google Testing Blog.

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
Avec commentaire :
Code :
1
2
3
// Subtract discount from price.
finalPrice = (numItems * itemPrice)
    - min(5, numItems) * itemPrice * 0.1;
Sans commentaire :
Code :
1
2
3
4
price = numItems * itemPrice;
discount =
    min(5, numItems) * itemPrice * 0.1;
finalPrice = price - discount;

2. Extraire une méthode
Avec commentaire :
Code :
1
2
// Filter offensive words.
for (String word : words) { ... }
Sans commentaire :
Code :
filterOffensiveWords(words);

3. Utiliser un nom d'identificateur plus descriptif
Avec commentaire :
Code :
int width = ...; // Width in pixels.
Sans commentaire :
Code :
int widthInPixels = ...;

4. Ajouter un contrôle dans le cas où votre code a des hypothèses
Avec commentaire :
Code :
1
2
// Safe since height is always > 0.
return width / height;
Sans commentaire :
Code :
1
2
checkArgument(height > 0);
return width / height;

Il y a bien sûr des cas où un commentaire peut être utile. C'est le cas par exemple lorsqu'il est nécessaire de révéler votre intention, c'est-à-dire expliquer pourquoi le code fait quelque chose (ce qui est différent d'expliquer ce que fait le code). On peut, entre autres, également utiliser des commentaires pour apporter une clarification à une question qui a été soulevée lors de la revue du code ou que les lecteurs du code pourraient avoir. Dans tous les cas, les ingénieurs de Google pensent qu'il faut éviter les commentaires qui ne font que dire ce que fait le code, car ce n'est que du bruit. Par exemple :
Code :
1
2
3
4
// Get all users.
userService.getAllUsers();
// Check if the name is empty.
if (name.isEmpty()) { ... }
Source : Google Testing Blog

Et vous ?

Qu’en pensez-vous ?
À quelle fréquence pensez-vous utiliser des commentaires ? Rarement, souvent, très souvent ?
Quelles règles observez-vous pour insérer des commentaires dans votre code ?

Voir aussi :

Un code bien écrit a-t-il besoin des commentaires ? Quelle est la place des commentaires dans votre code ?
Linus Torvalds fustige des développeurs du noyau Linux pour des styles de commentaires qu'il qualifie de « dégoûtants » et visuellement déséquilibrés
  Discussion forum
150 commentaires
  • palnap
    Membre averti
    Et vive les CheckStyles qui imposent de mettre des commentaires sur les getters & setters (et pire les langages qui imposent d'avoir des getters & setters ) et de lister tous les paramètres et retours des méthodes :

    Code Java :
    1
    2
    3
    4
    5
    6
    7
    /** 
    * Retourne l'âge du capitaine. 
    * @return âge du capitaine 
    **/ 
    public int getAgeCapitaine() { 
        return ageCapitaine; 
    }
  • BugFactory
    Membre chevronné
    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.
  • transgohan
    Expert éminent
    J'adore vos réactions tellement prévisibles...

    Si c'est complexe c'est forcement que le code est bon à refactoriser...
    Allez bosser sur des gros logiciels embarqués une fois dans votre vie et on en reparlera je pense.
    Je ne vois pas comparer un webservice avec le système de guidage d'un missile ou bien le système de communication d'une navette spatiale.

    Même correctement factorisé un logiciel de plusieurs centaine de millier de lignes reste en partie obscur dans la plupart de son fonctionnement au meilleur expert de la terre.
    Pas le temps de potasser le tout qu'il y a déjà de nouvelles améliorations à apporter.
  • transgohan
    Expert éminent
    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é...
  • el_slapper
    Expert éminent sénior
    Allez, exemple vécu ce matin..... Bon, je dois écrire un script qui agit sur notre client lourd, et notamment rentrer le code 10 dans le type de transport. Alors j'avais ça :

    Code :
    		ActiveX("Transport").Type "10" + micTab
    Et ça ne marche pas, parce-que quand on tape 1 puis 0, même par robot, l'appli va sur le 0, pas sur le 10. Donc j'ai désormais ça :

    Code :
    1
    2
    		'.ActiveX("Transport").Type "10" + micTab - ne marche pas, donne zéro
    		.ActiveX("Transport").Type "9" + micDwn + micTab 'permet de taper 10, en fait
    qui signifie que je tape neuf, je tape sur la flèche en bas, et oh miracle, ça me sélectionne le 10. Et puis ça fait TAB pour continuer sur la case d'après.

    Dans ce genre de cas, le commentaire technique me parait indispensable - parceque la manière de faire qui permettrait de comprendre ne fonctionne pas(et je ne vais pas faire une usine à gaz pour remplacer les fonctions natives de UFT, juste pour ça). En tous cas celui de la deuxième ligne. Garder la première en code mort, ça m'emmerde, j'hésite, par contre. Ce n'est pas inutile(ça permet de voir facilement ce qu'on voulait faire), mais comme tout code mort, c'est moche, par définition.

    Encore une fois, je ne commente pas le micDwn. Quelqu'un qui fait du UFT doit savoir ça, ou le retrouver facilement. Juste l'astuce horrible qui fait que le code est tordu pour un résultat qui paraissait simple à obtenir...
  • bcag2
    Membre actif
    G19 et G20 pages 318 et 319 de «Coder proprement» de Robert C.Martin (ISBN 978-2-7440-2583-9)
    … rien de nouveau
  • Pyramidev
    Expert éminent
    Envoyé par jopopmk
    1. Introduire une variable explicative
    Non, je vais pas rajouter une variable inutile.
    Si vraiment on a besoin d'une explication alors un commentaire va très bien.
    L'inconvénient des commentaires, c'est de risquer de ne pas être à jour par rapport au code.
    En particulier, quand le code est mis à jour par des développeurs trop pressés, on peut se retrouver avec des absurdités du style :
    Code :
    Sleep(3000); // Attendre 2 secondes.
    qui peuvent être évitées avec une variable intermédiaire :
    Code :
    1
    2
    const DWORD durationMilliseconds = 3000;
    Sleep(durationMilliseconds);
    Envoyé par jopopmk
    2. Extraire une méthode
    Toujours non, je vais pas empiler des appels inutiles.
    Si vraiment on a besoin d'une explication alors un commentaire va très bien.
    Nous sommes peut-être d'accord.
    Il est pertinent de créer une sous-fonction dans les deux cas suivants :
    • La sous-fonction est appelée dans plusieurs fonctions différentes. On évite alors les copiés-collés.
    • La fonction appelante devient trop grosse. Pour qu'on puisse la comprendre facilement de manière globale, il faut déplacer une partie de son code dans des sous-fonctions avec un nom parlant.

    Cela dit, si une fonction de taille modeste contient un ou deux bouts de code que je souhaite commenter et que ces bouts de code n'existent pas ailleurs, je ne vais pas les transformer en sous-fonctions seulement pour éviter d'écrire des commentaires !
    L'inconvénient de morceler en sous-fonctions, c'est qu'il faut faire des aller-retours dans le code si on veut voir l'implémentation de ces sous-fonctions.

    Envoyé par jopopmk
    3. Utiliser un nom d'identificateur plus descriptif
    Là c'est assez évident. Maintenant il peut arriver qu'on se retrouve avec des noms sans fin, on peut alors contextualiser les variables avec un petit commentaire (dans l'exemple, en tête d'algo, indiquer "all sizes in pixels" ).
    Je suis d'accord.

    Envoyé par jopopmk
    4. Ajouter un contrôle dans le cas où votre code a des hypothèses
    Gné ? Faire du défensif pour économiser un commentaire ? Là je sais même pas quoi dire ...
    Faire du défensif ne sert pas à éviter les commentaires, mais à détecter les erreurs à l'exécution.
    Cependant, puisqu'une instruction telle que checkArgument(height > 0); indique déjà clairement la précondition de la fonction, il est inutile de rappeler en plus cette précondition sous la forme d'un commentaire.

    Envoyé par Michael Guilloux
    Quelles règles observez-vous pour insérer des commentaires dans votre code ?
    J'écris des commentaires dans les cas suivants :
    • Expliquer un choix, surtout s'il paraît étrange à un lecteur qui ne connaît pas le contexte.
    • Résumer en quelques mots ce que fait une fonction ou ce que représente une classe, sauf si le nom de la fonction ou de la classe est déjà un résumé satisfaisant.
      Le rôle du résumé est d'éviter d'obliger le lecteur à plonger dans le code s'il a besoin d'une information plus précise que le nom de la fonction ou de la classe mais pas forcément aussi précise que le code.
      De même, il m'arrive parfois de résumer sous forme de commentaire ce que fait un bloc de code dans les cas où il n'est pas pertinent de déplacer ce bloc de code dans une sous-fonction (voir ci-avant).
    • Avertir sur les dangers d'une certaine fonction ou classe. Exemple : Attention, le bogue machin du ticket n°XXXX n'a pas encore été corrigé.
    • Écrire parfois quelques "rappels" techniques si le lecteur a des chances de ne pas les avoir. Cela rejoint d'une certaine manière ce que disait BugFactory, mais ça ne s'applique pas qu'aux stagiaires. Cela s'applique aussi si on fait appel à des subtilités d'un langage ou d'une bibliothèque. Par exemple, en C++, il m'arrive d'écrire un commentaire du genre :
      Code :
      1
      2
      3
      4
          // Rappel : propriétés de l'initialisation d'une variable locale statique :
          // - Si l'initialisation lance une exception, elle est considérée comme non faite et
          //   sera retentée au prochain passage.
          // - L'initialisation est thread-safe depuis C++11.
    • Mettre en évidence qu'un certain détail d'implémentation ne fait pas partie de l'interface.
      Par exemple, dans une certaine classe, l'implémentation actuelle utilise un certain type de tableau associatif sous forme d'arbre binaire de recherche qui trie les éléments dans l'ordre des clés, mais l'implémentation future pourrait utiliser une table de hashage sans ce tri. Alors, dans l'interface de la classe, il vaut mieux avertir sous forme de commentaire : attention, ne vous reposez pas sur l'hypothèse que les éléments sont triés dans l'ordre des clés, car ça pourrait changer plus tard.
    • Aider l'utilisateur qui explore le code avec des commentaires de type "voir aussi telle fonction ou telle classe". Par exemple, quand il y a plusieurs fonction similaires (mais différentes), ce genre de commentaire aide l'utilisateur à trouver la bonne fonction à appeler.


    Cela dit, comme je l'ai précisé, je suis conscient que, l'inconvénient des commentaires, c'est de risquer de ne pas être à jour par rapport au code. Du coup, quand une fonction a un code très simple et très petit, je préfère que la doc soit le code.
    Par exemple, en C++, pour éviter d'écrire certaines préconditions et post-conditions sous forme de commentaires, il m'arrive de créer des fonctions en ligne qui ressemblent à :
    Code :
    1
    2
    3
    4
    5
    6
    7
    double my_sqrt(double param) {
        assert(param >= 0);
        double result = my_sqrt_impl(param);
        assert(result >= 0);
        return result;
    }
    // Rq : Dans du vrai code, je ne réimplémente pas sqrt, mais c'est pour l'exemple.
    et, pour décrire les invariants d'une classe, il m'arrive de créer une fonction membre :
    Code :
    1
    2
    3
    bool invariant() const {
        // code qui retourne true si les invariants de la classe sont respectés
    }
    Du coup, je configure l'outil de génération de code (dans mon cas, Doxygen) pour afficher aussi le code des fonctions. L'inconvénient est que l'ensemble des fichiers générés pour la documentation est assez volumineux.
  • Bousk
    Rédacteur/Modérateur
    Envoyé par martopioche
    Sérieux, on est en 2017
    Et ? T'as jamais vu du code vieux de plusieurs dizaines d'années ? Tu peux aller voir ton patron et dire "bon mec, notre code il marche mais il a 30 ans, faut le changer, on est en 2017 !" ? Et il accepte et est prêt à changer un truc qui marche sans broncher parce que tu lui montres un livre ?
    Bienvenue dans le monde réel.
  • Sange844
    Membre du Club
    Une référence additionnelle à celles déjà citées:

    Jeff Atwood: Code Tells You How, Comments Tell You Why
  • Aurelien.Regat-Barrel
    Expert éminent sénior
    Les commentaires qui expliquent ce que font le code sont rarement une bonne chose. Mais sur du code complexe ou ancien (qui a été réécrit / optimisé / débogué plusieurs fois), ils sont très utiles pour clarifier le contexte ou l'historique du code,
    en particulier expliquer ce que le code ne fait pas et pourquoi c'est ainsi.

    Jetez juste un oeil au source de Linux ou Chromium pour vous convaincre.