Clean Code comments vs documentation de classe

83

Je discute avec mes nouveaux collègues au sujet des commentaires. Nous aimons tous les deux Clean Code , et je suis parfaitement d'accord avec le fait que les commentaires de code en ligne doivent être évités et que les noms de classe et de méthode doivent être utilisés pour exprimer ce qu'ils font.

Cependant, je suis un grand partisan de l’ajout de résumés de classe restreinte qui tente d’expliquer l’objectif de la classe et ce qu’elle représente en réalité, principalement pour faciliter le maintien du modèle de principe de responsabilité unique . Je suis également habitué à ajouter des résumés d'une ligne aux méthodes expliquant ce que la méthode est censée faire. Un exemple typique est la méthode simple

public Product GetById(int productId) {...}

J'ajoute le résumé de méthode suivant

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary

Je crois que le fait que la méthode retourne null devrait être documenté. Un développeur qui souhaite appeler une méthode ne devrait pas avoir à ouvrir mon code afin de voir si la méthode renvoie la valeur null ou lève une exception. Parfois, cela fait partie d'une interface, alors le développeur ne sait même pas quel code sous-jacent est en cours d'exécution?

Cependant, mes collègues pensent que ce type de commentaires est " une odeur de code " et que "les commentaires sont toujours des échecs" ( Robert C. Martin ).

Existe-t-il un moyen d’exprimer et de communiquer ces types de connaissances sans ajouter de commentaires? Depuis que je suis un grand fan de Robert C. Martin, je suis un peu confus. Les résumés sont-ils les mêmes que les commentaires et donc toujours des échecs?

Ce n'est pas une question de commentaires en ligne.

Bjorn
la source
38
Robert Martin a déclaré "Les commentaires sont toujours des échecs"? Eh bien, alors il est un extrémiste marginal et devrait être pris avec une pincée de sel. (Oui, je sais qu'il écrit ainsi pour des raisons rhétoriques, afin de faire passer son message. Ce que je veux dire, c'est que vous devriez le faire .)
Kilian Foth
18
Les livres d'oncle Bob devraient venir avec un sac de 1kg de sel ...
AK_
6
Si vous suivez Robert Martin, la documentation pour le cas nul devrait être un test. Autrement dit, vous devriez avoir un test indiquant dans quel cas la méthode peut renvoyer null. Alternativement, puisqu'il s'agit de Java, une annotation @Nullable serait également meilleure que le commentaire.
Martin Epsz
15
@Bjorn Je possède un exemplaire de Clean Code et l'ai lu d'une page à l'autre plus d'une fois. Oui, Oncle Bob préfère que le code soit auto-documenté, mais son propre code contient de multiples exemples de commentaires . Le fait est que si vous vous sentez obligé d'écrire un commentaire, essayez vraiment de changer le code plutôt que d'ajouter le commentaire, mais ne rejetez pas complètement les commentaires (même les commentaires en ligne).
6
La méthode doit s'appeler TryGetById et le commentaire doit être supprimé.
usr

Réponses:

116

Comme d'autres l'ont dit, il existe une différence entre les commentaires documentant l'API et les commentaires en ligne. De mon point de vue, la principale différence est qu'un commentaire en ligne est lu à côté du code , tandis qu'un commentaire de documentation est lu à côté de la signature de tout ce que vous commentez.

Compte tenu de cela, nous pouvons appliquer le même principe DRY . Le commentaire dit-il la même chose que la signature? Regardons votre exemple:

Récupère un produit par son identifiant

Cette partie ne fait que répéter ce que nous voyons déjà du nom GetByIdplus le type de retour Product. Cela soulève également la question de savoir quelle est la différence entre "obtenir" et "récupérer", et quelle est la différence entre le code de support et le commentaire. C'est donc inutile et légèrement déroutant. Si quelque chose se passe, cela va à l’encontre de la deuxième partie du commentaire qui est réellement utile:

renvoie la valeur null si aucun produit n'a été trouvé.

Ah! C'est quelque chose que nous ne pouvons absolument pas savoir avec certitude grâce à la signature et qui fournit des informations utiles.


Maintenant, prenez ceci un peu plus loin. Quand les gens parlent de commentaires car le code a une odeur, la question n'est pas de savoir si le code en tant que tel nécessite un commentaire, mais si le commentaire indique que le code pourrait être mieux écrit, pour exprimer les informations qu'il contient. C'est ce que "odeur de code" signifie - cela ne signifie pas "ne faites pas ceci!", Cela signifie "si vous faites cela, cela pourrait être un signe qu'il y a un problème".

Donc, si vos collègues vous disent que ce commentaire sur null est une odeur de code, vous devez simplement leur demander: "D'accord, comment puis-je l'exprimer alors?" S'ils ont une réponse réalisable, vous avez appris quelque chose. Sinon, ça va probablement tuer leurs plaintes mortes.


En ce qui concerne ce cas particulier, on sait généralement que la question du zéro est difficile. Il y a une raison pour laquelle les bases de code sont jonchées de clauses de garde, pourquoi les contrôles nuls sont une condition préalable populaire pour les contrats de code, pourquoi l'existence de null a été qualifiée d '"erreur d'un milliard de dollars". Il n'y a pas beaucoup d'options viables. Une Try...convention populaire, cependant, trouvée en C # est la convention:

public bool TryGetById(int productId, out Product product);

Dans d'autres langues, il peut être idiomatique d'utiliser un type (souvent appelé quelque chose comme Optionalou Maybe) pour indiquer un résultat qui peut être ou ne pas être là:

public Optional<Product> GetById(int productId);

D'une certaine manière, cette position anti-commentaires nous a permis d'arriver quelque part: nous avons au moins cherché à savoir si ce commentaire représente une odeur et quelles alternatives pourraient exister pour nous.

Que nous fait préférer ces sur la signature originale est un tout autre débat, mais nous au moins avoir des options pour exprimer par le code plutôt que des commentaires ce qui se passe quand aucun produit trouvé. Vous devriez discuter avec vos collègues de l’une des options qu’ils jugent meilleures et pourquoi, et nous espérons pouvoir aider à aller au-delà des déclarations dogmatiques générales sur les commentaires.

Ben Aaronson
la source
9
Ou le Linq-équivalent de Try..., ...OrDefaultqui retourne default(T)si la clause conduirait à un résultat vide.
Bart van Nierop
4
J'apprécie beaucoup votre distinction entre les commentaires de code en ligne et les commentaires de documentation, et les exemples donnés :)
Rachel
2
Les valeurs de retour possibles d'une fonction doivent être évidentes par sa signature. Le TryGetValuemodèle est un moyen raisonnable de faire cela en C #, mais la plupart des langages fonctionnels ont un meilleur moyen de représenter une valeur manquante. Lire plus ici
AlexFoxGill
2
@BenAaronson: Si on veut avoir une interface générique pouvant supporter la covariance, on peut l'utiliser T TryGetValue(params, ref bool success)pour tout type T ou T TryGetValue(params), avec null indiquant l'échec, pour le type T contraint par la classe, mais le TryGetXXmodèle renvoyé boolest incompatible avec la covariance.
Supercat
6
En Java 8, vous pouvez renvoyer an Optional<Product>pour indiquer qu'il est possible qu'aucun produit ne soit renvoyé par la méthode.
Wim Deblauwe
102

La citation de Robert C. Martin est sortie de son contexte. Voici la citation avec un peu plus de contexte:

Rien ne peut être aussi utile qu'un commentaire bien placé. Rien ne peut encombrer un module plus que des commentaires dogmatiques frivoles. Rien ne peut être aussi préjudiciable qu’un vieux commentaire cruel qui propage des mensonges et de la désinformation.

Les commentaires ne ressemblent pas à la liste de Schindler. Ils ne sont pas "pur bien". En effet, les commentaires sont, au mieux, un mal nécessaire. Si nos langages de programmation étaient suffisamment expressifs, ou si nous avions le talent de les utiliser subtilement pour exprimer notre intention, nous n'aurions pas beaucoup besoin de commentaires - peut-être même pas du tout.

L'utilisation appropriée des commentaires doit compenser notre incapacité à nous exprimer en code. Notez que j'ai utilisé le mot échec. C'est ce que je voulais dire. Les commentaires sont toujours des échecs. Nous devons les avoir car nous ne pouvons pas toujours comprendre comment nous exprimer sans eux, mais leur utilisation n’est pas un motif de célébration.

Ainsi, lorsque vous vous trouvez dans une position où vous devez écrire un commentaire, réfléchissez-y et voyez s'il n'y a pas de moyen de renverser la situation et de vous exprimer en code. Chaque fois que vous vous exprimez en code, vous devriez vous féliciter. Chaque fois que vous écrivez un commentaire, vous devriez faire la grimace et ressentir l’échec de votre capacité d’expression.

(Copié à partir d'ici , mais la citation originale provient de Clean Code: Un manuel de l'artisanat logiciel agile )

Comment cette citation est réduite à "Les commentaires sont toujours des échecs" est un bon exemple de la façon dont certaines personnes vont prendre une citation raisonnable hors de son contexte et la transformer en dogme stupide.


La documentation de l'API (comme javadoc) est censée documenter l'API afin que l'utilisateur puisse l'utiliser sans avoir à lire le code source . Donc, dans ce cas, la documentation devrait expliquer ce que fait la méthode. Vous pouvez maintenant affirmer que "Récupérer un produit par son identifiant" est redondant car il est déjà indiqué par le nom de la méthode, mais les informations nullpouvant être renvoyées sont définitivement importantes pour la documentation, car elles ne sont en aucun cas évidentes.

Si vous souhaitez éviter la nécessité du commentaire, vous devez supprimer le problème sous-jacent (l'utilisation de nullcomme valeur de retour valide) en rendant l'API plus explicite. Par exemple, vous pouvez renvoyer un type de Option<Product>type, de sorte que la signature de type elle-même communique clairement ce qui sera renvoyé au cas où le produit ne serait pas trouvé.

Toutefois, dans tous les cas, il n'est pas réaliste de documenter une API de manière complète uniquement par le biais de noms de méthodes et de signatures de types. Utilisez doc-comments pour toute information supplémentaire non évidente que l'utilisateur devrait connaître. Prenez par exemple la documentation de l'API DateTime.AddMonths()dans la BCL:

La méthode AddMonths calcule le mois et l'année obtenus en tenant compte des années bissextiles et du nombre de jours d'un mois, puis ajuste la partie jour de l'objet DateTime obtenu. Si le jour résultant n'est pas un jour valide du mois résultant, le dernier jour valide du mois résultant est utilisé. Par exemple, 31 mars + 1 mois = 30 avril. La partie heure de l'objet DateTime résultant reste la même que cette instance.

Il est impossible d'exprimer cela en utilisant uniquement le nom de la méthode et sa signature! Bien entendu, la documentation de votre classe n’exigera peut-être pas ce niveau de détail, ce n’est qu’un exemple.


Les commentaires en ligne ne sont pas mauvais non plus.

Les mauvais commentaires sont mauvais. Par exemple, des commentaires qui n'expliquent que ce que l'on peut déduire du code, l'exemple classique étant:

// increment x by one
x++;

Les commentaires qui expliquent quelque chose qui pourrait être clarifié en renommant une variable ou une méthode ou en restructurant le code, constituent une odeur de code:

// data1 is the collection of tasks which failed during execution
var data1 = getData1();

C’est le genre de commentaires que Martin a critiqués. Le commentaire est le symptôme d'une incapacité à écrire du code clair - dans ce cas, utiliser des noms explicites pour les variables et les méthodes. Le commentaire lui-même n’est bien sûr pas le problème, c’est que nous avons besoin du commentaire pour comprendre le code.

Mais les commentaires doivent être utilisés pour expliquer tout ce qui n’est pas évident dans le code, par exemple pourquoi le code est écrit d’une certaine manière non évidente:

// need to reset foo before calling bar due to a bug in the foo component.
foo.reset()
foo.bar();

Les commentaires qui expliquent ce qu'une partie de code trop compliquée fait aussi, c'est une odeur, mais le correctif n'est pas d'interdire les commentaires, le correctif est le correctif du code! Dans le vrai mot, le code compliqué arrive (espérons-le seulement temporairement jusqu'à ce qu'un refactor), mais aucun développeur ordinaire n'écrit du code parfaitement propre la première fois. Lorsque du code compliqué arrive, il est bien mieux d'écrire un commentaire expliquant ce qu'il fait que de ne pas écrire un commentaire. Ce commentaire facilitera également la refactorisation ultérieure.

Parfois, le code est inévitablement complexe. Il peut s’agir d’un algorithme compliqué ou d’un code qui sacrifie la clarté pour des raisons de performances. Encore une fois, les commentaires sont nécessaires.

JacquesB
la source
13
Il y a aussi le cas où votre code gère une situation qui vient est compliquée, et pas de code simple peut manipuler.
gnasher729
6
Bon point, gnasher. Cela semble se produire souvent lorsque vous devez optimiser un élément de code en termes de performances.
JacquesB
9
Même un commentaire x++peut être bon s'il s'agit de quelque chose comme "incrémenter x de un, encapsulant s'il s'agit de UINT32_MAX"; tous ceux qui connaissent les spécifications de langue saura que incrémenter un uint32_tenveloppera, mais sans le commentaire ne peut pas savoir si cette enveloppe était attendue partie de l'algorithme mis en œuvre.
Supercat
5
@ l0b0: J'espère que tu plaisantes!
JacquesB
9
@ l0b0 Il n'existe pas de code temporaire. Le code ne fait jamais l'objet d'une refonte, car l'entreprise était satisfaite du résultat et n'approuvera pas le financement pour y remédier. Dans cinq ans, certains développeurs débutants verront ce code. Vous n’utilisez même plus WizBug 4.0 depuis que vous l’avez remplacé par Bugtrocity v9. "Bug123" ne signifie rien pour lui. Il pense maintenant que c'est ce que le code permanent est censé être, et passe pour devenir un terrible développeur tout au long de sa carrière. Pense aux enfants. N'écris pas de code temporaire.
CorsiKa
36

Il existe une différence entre commenter votre code et documenter votre code .

  • Des commentaires sont nécessaires pour maintenir le code ultérieurement, c'est-à-dire changer le code lui-même.

    Les commentaires peuvent en effet être perçus comme problématiques. Le point extrême serait de dire qu'ils indiquent toujours un problème, que ce soit dans votre code (code trop difficile à comprendre) ou dans le langage (langage incapable d'être assez expressif; par exemple, le fait que la méthode ne retourne jamais nullpeut être exprimé) via des contrats de code en C #, mais il n’existe aucun moyen de l’exprimer par le code, disons PHP).

  • La documentation est nécessaire pour pouvoir utiliser les objets (classes, interfaces) que vous avez développés. Le public cible est différent: ce ne sont pas les personnes qui entretiendront votre code et le modifier dont nous parlons ici, mais les personnes qui ont à peine besoin de l' utiliser .

    Supprimer de la documentation parce que le code est suffisamment clair est insensé, car la documentation est spécifiquement conçue pour permettre l'utilisation de classes et d'interfaces sans avoir à lire des milliers de lignes de code .

Arseni Mourzenko
la source
Oui, mais au moins une partie du point de vue de Martin est qu'avec les pratiques de développement modernes, les tests sont la documentation, pas le code lui-même. En supposant que le code soit testé avec un système de test de style BDD, par exemple, specflow, les tests eux-mêmes sont une description directement lisible du comportement de la méthode ("étant donné une base de données de produits lorsque GetById est appelé avec l'identifiant d'un produit valide, puis l'objet Product approprié est renvoyé [...] lorsque GetById est appelé avec un ID de produit non valide, puis null est renvoyé "ou quelque chose comme cela).
Jules
13

Eh bien, il semblerait que votre collègue lise des livres, prenne ce qu’ils disent et applique ce qu’il a appris sans réfléchir et sans tenir compte du contexte.

Votre commentaire sur le fonctionnement de la fonction doit être tel que vous puissiez jeter le code d’implémentation. J'ai lu le commentaire de la fonction et je peux écrire le remplacement pour l’implémentation, sans que rien ne se passe mal.

Si le commentaire ne me dit pas si une exception est levée ou si la valeur null est renvoyée, je ne peux pas le faire. De plus, si le commentaire ne vous indique pas si une exception est générée ou si la valeur nil est renvoyée, vous devez vous assurer que votre code fonctionne correctement, qu'une exception soit renvoyée ou que la fonction soit renvoyée.

Votre collègue a donc totalement tort. Et allez-y, lisez tous les livres, mais pensez par vous-même.

PS J'ai vu votre ligne "parfois, elle fait partie d'une interface, de sorte que vous ne savez même pas quel code est en cours d'exécution." Même avec les fonctions virtuelles, vous ne savez pas quel code est en cours d'exécution. Pire, si vous écriviez une classe abstraite, il n'y aurait même pas de code! Donc, si vous avez une classe abstraite avec une fonction abstraite, les commentaires que vous ajoutez à la fonction abstraite sont la seule chose qu'un implémenteur d'une classe concrète doit les guider. Ces commentaires peuvent également être la seule chose qui puisse guider un utilisateur de la classe, par exemple si tout ce que vous avez est une classe abstraite et une fabrique renvoyant une implémentation concrète, mais que vous ne voyez jamais le code source de cette implémentation. (Et bien sûr, je ne devrais pas regarder le code source d' une implémentation).

gnasher729
la source
Je n'ai pas commenté le code depuis 10 ans. Les commentaires sont bloat, garbage. Personne ne commente le code ces jours-ci. Nous nous concentrons sur le code bien formé et nommé, les petits modules, le découplage, etc. CELA rend votre code lisible, pas de commentaires. Les tests garantissent que si vous jetez du code, rien ne se passe mal, pas de commentaires. Les tests vous indiquent comment vous utilisez le code que vous écrivez, comment vous les appelez et pourquoi ils sont là. Tu es bien trop vieille école, tu dois apprendre à tester et à nettoyer le code, mon ami.
PositiveGuy
12

Il existe deux types de commentaires à prendre en compte: ceux visibles par les personnes utilisant le code et ceux utilisés pour générer de la documentation.

Le type de commentaire auquel fait référence Oncle Bob est celui qui n'est visible que par les personnes possédant le code. Ce qu’il préconise, c’est une forme de SEC . Pour une personne qui consulte le code source, le code source doit correspondre à la documentation dont elle a besoin. Même dans le cas où les gens ont accès au code source, les commentaires ne sont pas toujours mauvais. Parfois, les algorithmes sont compliqués ou vous devez comprendre pourquoi vous adoptez une approche non évidente pour que les autres ne cassent pas votre code s'ils tentent de corriger un bogue ou d'ajouter une nouvelle fonctionnalité.

Les commentaires que vous décrivez sont la documentation de l'API. Ce sont des choses visibles par les utilisateurs de votre implémentation, mais qui n'ont peut-être pas accès à votre code source. Même s'ils ont accès à votre code source, ils travaillent peut-être sur d'autres modules et ne consultent pas votre code source. Ces personnes trouveraient utile de disposer de cette documentation dans leur IDE au moment de la rédaction de leur code.

Thomas Owens
la source
Honnêtement, je n’avais jamais pensé à DRY s’appliquant à code + commentaires, mais c’est parfaitement logique. Un peu comme l'exemple "incrément X" dans la réponse de @ JacquesB.
7

La valeur d'un commentaire est mesurée en valeur des informations qu'il donne moins l'effort nécessaire pour le lire et / ou l'ignorer. Donc si on analyse le commentaire

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary>

pour la valeur et le coût, nous voyons trois choses:

  1. Retrieves a product by its idrépète ce que le nom de la fonction dit, donc c'est un coût sans valeur. Il devrait être supprimé.

  2. returns null if no product was foundest une information très précieuse. Cela réduira probablement le temps nécessaire aux autres codeurs pour examiner la mise en œuvre de la fonction. Je suis tout à fait certain que cela économise plus de lecture que le coût de lecture présenté. Ça devrait rester.

  3. Les lignes

    /// <summary>
    /// </summary>
    

    porter aucune information que ce soit. Ce sont des coûts purs pour le lecteur du commentaire. Ils peuvent être justifiés si votre générateur de documentation en a besoin, mais dans ce cas, vous devriez probablement envisager un autre générateur de documentation.

    C’est la raison pour laquelle l’utilisation de générateurs de documentation est une idée discutable: ils nécessitent généralement un grand nombre de commentaires supplémentaires ne contenant aucune information ou ne répétant pas la même chose évidente, uniquement dans l’intérêt d’un document soigné.


Une observation que je n'ai trouvée dans aucune des autres réponses:

Même les commentaires qui ne sont pas nécessaires pour comprendre / utiliser le code peuvent être très précieux. Voici un exemple:

//XXX: The obvious way to do this would have been ...
//     However, since we need this functionality primarily for ...
//     doing this the non-obvious way of ...
//     gives us the advantage of ...

Probablement beaucoup de texte, complètement inutile de comprendre / utiliser le code. Cependant, cela explique pourquoi le code a cette apparence. Cela empêchera les gens de regarder le code, se demander pourquoi cela n'a pas été fait de façon évidente, et commencerait à le refactoriser jusqu'à ce qu'ils sachent pourquoi le code a été écrit comme ceci au départ. Et même si le lecteur est assez intelligent pour ne pas passer directement à la refactorisation, il lui reste à comprendre pourquoi le code a la même apparence avant de se rendre compte qu'il devrait au mieux rester tel qu'il est. Ce commentaire pourrait littéralement économiser des heures de travail. Ainsi, la valeur est supérieure au coût.

De même, les commentaires peuvent communiquer les intentions d'un code, plutôt que son fonctionnement. Et ils peuvent peindre la grande image qui est généralement perdue dans les moindres détails du code lui-même. En tant que tel, vous avez raison d’être en faveur des commentaires de classe. J'apprécie le plus les commentaires de classe s'ils expliquent l'intention de la classe, comment elle interagit avec d'autres classes, comment elle est censée être utilisée, etc. Hélas, je ne suis pas un grand auteur de tels commentaires ...

cmaster
la source
2
Wow - changez votre générateur de documents car il nécessite quelques lignes supplémentaires de HTML pour l'analyse? Il ne faut pas.
CorsiKa
2
@corsiKa YMMV, mais je préférerais un générateur de documentation qui réduise au minimum les coûts en commentaires. Bien sûr, je préférerais aussi lire un fichier d’entête bien écrit plutôt qu’une documentation doxygen qui n’est pas synchronisée avec le code réel. Mais, comme je l'ai dit, YMMV.
cmaster
4
Même si le nom d'une méthode décrit son objectif de manière brillante, le répéter en utilisant un langage naturel peut permettre à une personne lisant plus facilement d'associer cet objectif aux mises en garde qui suivent. Une reformulation de ce qui est décrit dans le nom sera suffisamment brève pour que même si la valeur est basse, le coût le sera également. Je suis donc en désaccord avec la première partie de votre post. +1, cependant, pour la deuxième partie. La documentation des approches alternatives qui ont été évaluées et rejetées peut être extrêmement utile, mais cette information reçoit rarement l'attention qu'elle mérite.
Supercat
GetByIdsoulève la question, quelle est id, et aussi, obtenir quoi d'où. Les commentaires sur la documentation doivent permettre à l’environnement de développement d’afficher les réponses à ces questions. À moins que cela ne soit expliqué ailleurs dans les commentaires de module doc, ce serait également un endroit pour dire pourquoi on obtiendrait l'identifiant de toute façon.
Hyde
Commentaires soufflent, code propre (auto-description), TDD (obtenant souvent des commentaires et obtenant des commentaires sur votre conception) et testant des règles (vous donnant confiance et documentant le comportement)! TESTS personnes TESTS. Personne ici ne parle de ça. Réveillez-vous
PositiveGuy
4

Le code non commenté est un mauvais code. C'est un mythe répandu (sinon universel) que le code peut être lu de la même manière qu'en anglais, par exemple. Il doit être interprété, et pour tout code, sauf le plus trivial, qui prend du temps et des efforts. De plus, tout le monde a un niveau de capacité différent en lecture et en écriture dans une langue donnée. Les différences entre les styles et les capacités de codage de l'auteur et du lecteur constituent des obstacles importants à une interprétation précise. C'est également un mythe que vous pouvez déduire l'intention de l'auteur de la mise en œuvre du code. D'après mon expérience, il est rarement erroné d'ajouter des commentaires supplémentaires.

Robert Martin et al. considérez cela comme une "mauvaise odeur" car il se peut que le code soit modifié et que les commentaires ne le soient pas. Je dis que c'est une bonne chose (exactement de la même manière qu'une "mauvaise odeur" est ajoutée au gaz domestique pour alerter l'utilisateur des fuites). La lecture des commentaires vous fournit un point de départ utile pour interpréter le code réel. S'ils concordent, vous aurez une confiance accrue dans le code. S'ils diffèrent, vous avez détecté une odeur d'avertissement et devez poursuivre vos recherches. Le remède à une "mauvaise odeur" ne consiste pas à éliminer l'odeur mais à colmater la fuite.

Vince O'Sullivan
la source
2
Étant donné que vous êtes un auteur intelligent et que le texte est destiné à un public intelligent, Vous tracez la ligne en utilisant le bon sens. Évidemment, en l'état actuel, l'exemple est stupide, mais cela ne veut pas dire qu'il n'y a peut-être pas une très bonne raison de clarifier avec un commentaire pourquoi le code inclut un i ++ à ce moment-là.
Vince O'Sullivan
8
i++; // Adjust for leap years.
Vince O'Sullivan
5
"Robert Martin et al. Considèrent cela comme une" mauvaise odeur "car il se peut que le code soit modifié et que les commentaires ne le soient pas." Ce n'est qu'une partie de l'odeur. Le pire de l’odeur provient de l’idée que le programmeur a décidé de ne pas essayer d’écrire le code de manière plus descriptive et a plutôt choisi de "sceller la fuite" avec un commentaire. Son assertion est que plutôt que de gifler un commentaire "// ajuster pour les années bissextiles", on devrait probablement avoir une méthode "adjustForLeapYears ()" dans le code lui-même (ou quelque chose de similaire). La documentation se présente sous la forme de tests utilisant la logique des années bissextiles.
Eric King
3
J'envisagerais d'ajouter un appel de méthode pour remplacer une seule ligne de code par un commentaire excessif, d'autant plus que le nom de la méthode est en fait un commentaire qui marque un morceau de code et ne garantit pas une meilleure précision de la documentation. (Si cette ligne se produisait à deux endroits ou plus, l'introduction d'une méthode serait évidemment la solution idéale.)
Vince O'Sullivan
1
@ Jay La raison en est que rendre la règle explicite (en introduisant par exemple des méthodes) est la règle. Ne pas le faire parce que vous pourriez vous retrouver avec une méthode qui a une ligne est l'exception. Permettez - moi de paraphraser la vraie règle arbitraire: « Utilisez votre structures de langage de programmation (généralement des méthodes et des classes) d'introduire des abstractions, à moins que la mise en œuvre de cette abstraction peut être exprimée en une ligne de code, dans ce cas , préciser l'abstraction en langage naturel en ajoutant un commentaire."
Eric
3

Dans certaines langues (F # par exemple), l’ensemble du commentaire / de la documentation peut en réalité être exprimé dans la signature de la méthode. En effet, dans F #, null n'est généralement pas une valeur autorisée, sauf autorisation spécifique.

Ce qui est courant dans F # (et dans plusieurs autres langages fonctionnels), c’est qu’au lieu de null, vous utilisez un type d’option Option<T>qui pourrait être Noneou Some(T). Le langage le comprendrait alors et vous obligerait (ou vous avertir si vous ne le faites pas) à correspondre dans les deux cas lorsque vous essayez de l'utiliser.

Ainsi, par exemple, en F #, vous pourriez avoir une signature qui ressemble à ceci

val GetProductById: int -> Option<Product>

Et puis ce serait une fonction qui prend un paramètre (un int) et retourne ensuite un produit ou la valeur Aucun.

Et alors vous pourriez l'utiliser comme ça

let product = GetProduct 42
match product with
| None -> printfn "No product found!"
| Some p -> DoThingWithProduct p

Et vous obtiendrez des avertissements du compilateur si vous ne correspondez pas aux deux cas possibles. Il n’ya donc aucun moyen d’obtenir des exceptions de référence null (sauf si vous ignorez les avertissements du compilateur), et vous savez tout ce dont vous avez besoin simplement en regardant la signature de la fonction.

Bien entendu, cela nécessite que votre langage soit conçu de cette manière - ce que de nombreux langages courants tels que C #, Java, C ++, etc. ne le sont pas. Cela peut donc ne pas vous être utile dans votre situation actuelle. Mais il est bon (heureusement) de savoir qu’il existe des langages qui vous permettent d’exprimer ce type d’informations de manière statique, sans commentaires, etc. :)

wasatz
la source
1

Il y a d'excellentes réponses ici et je ne veux pas répéter ce qu'elles disent. Mais laissez-moi ajouter quelques commentaires. (Sans jeu de mots.)

Les gens intelligents font beaucoup de déclarations - sur le développement de logiciels et de nombreux autres sujets, je suppose - qui sont de très bons conseils quand ils sont compris dans le contexte, mais que les personnes idiotes prennent hors contexte extrêmes ridicules.

L'idée que le code devrait s'auto-documenter est une excellente idée. Mais dans la vraie vie, il y a des limites à l'aspect pratique de cette idée.

L'un des inconvénients est que le langage peut ne pas fournir des fonctionnalités permettant de documenter ce qui doit être documenté de manière claire et concise. À mesure que les langages informatiques s'améliorent, cela devient de moins en moins un problème. Mais je ne pense pas qu'il soit complètement parti. À l'époque où j’écrivais dans assembler, il était logique d’inclure un commentaire du type "prix total = prix des articles non taxables plus le prix des articles taxables plus le prix des articles taxables * taux de taxe". Exactement ce qui était dans un registre à un moment donné n'était pas nécessairement évident. Il a fallu plusieurs étapes pour effectuer une opération simple. Etc. Mais si vous écrivez dans une langue moderne, un tel commentaire serait simplement une reformulation d'une ligne de code.

Je suis toujours ennuyé quand je vois des commentaires du type "x = x + 7; // ajoute 7 à x". Par exemple, wow, merci, si j'avais oublié la signification d'un signe plus qui aurait pu être très utile. Là où je pourrais vraiment être dérouté, c'est de savoir ce qu'est "x" ou pourquoi il était nécessaire d'ajouter 7 à ce moment-là. Ce code peut être auto-documenté en donnant un nom plus significatif à "x" et en utilisant une constante symbolique au lieu de 7. Comme si vous aviez écrit "total_price = total_price + MEMBERSHIP_FEE;", aucun commentaire n'est probablement nécessaire du tout. .

Cela semble bien de dire qu'un nom de fonction devrait vous dire exactement ce que fait une fonction pour que tout commentaire supplémentaire soit redondant. Je garde de bons souvenirs de l'époque où j'ai écrit une fonction qui vérifiait si un numéro d'article se trouvait dans notre table de base de données, renvoyant la valeur true ou false, et que j'avais appelée "ValidateItemNumber". Semblé comme un nom décent. Ensuite, quelqu'un d'autre est arrivé et a modifié cette fonction pour créer également une commande pour l'élément et mettre à jour la base de données, mais n'a jamais changé le nom. Maintenant, le nom était très trompeur. Cela ressemblait à une petite chose, alors qu'en réalité, il en faisait beaucoup plus. Plus tard, quelqu'un a même supprimé la partie sur la validation du numéro d'article et l'a fait ailleurs, mais n'a toujours pas changé le nom. Donc, même si la fonction n’a plus rien à voir avec la validation des numéros d’article,

Mais dans la pratique, il est souvent impossible pour un nom de fonction de décrire complètement ce que la fonction fait sans que le nom de la fonction soit aussi long que le code qui la compose. Est-ce que le nom va nous dire exactement quelles validations sont effectuées sur tous les paramètres? Que se passe-t-il dans des conditions exceptionnelles? Épeler toutes les ambiguïtés possibles? À un moment donné, le nom deviendrait si long qu'il deviendrait confus. J'accepterais String BuildFullName (String name, String lastname) comme signature de fonction décente. Même si cela n’indique pas si le nom est exprimé par "premier dernier" ou "dernier, premier" ou une autre variante, que fait-il si une partie ou les deux parties du nom sont vierges, si elle impose des limites à la longueur combinée et ce qu'il fait si c'est dépassé,

Geai
la source