Code de fantaisie court commenté par rapport à un code plus long et facile à comprendre non commenté - lequel est préféré?

18

Parfois, un algorithme peut être écrit de deux manières:

  • La manière courte et sophistiquée; ou
  • La manière la plus longue et la plus facile à comprendre.

Par exemple, voici une plus longue, plus facile de copier une chaîne sourceà destC:

*dest = *source;
while (*source != '\0') {
    source++;
    dest++;
    *dest = *source;
} (true);

Et voici une manière courte et fantaisiste.

// Copy string source to dest
while (*dest++ = *source++);

J'ai toujours entendu et lu que le code de fantaisie devrait être évité, et j'ai tendance à être d'accord. Mais que faire si nous tenons compte des commentaires? Supposons que, comme dans les exemples ci-dessus, nous avons un code non commenté, plus long et soi-disant plus facile à comprendre, et un code court et bien commenté? Le code non sophistiqué est-il toujours préféré?

EDIT: Beaucoup ont commenté les noms de variables, j'ai donc modifié l'exemple de code pour ne pas en faire un facteur lors de la préférence sur l'autre. J'ai essayé de supprimer la double affectation dans le premier exemple, mais cela n'a fait que rendre le code moins lisible.

Peut-être que ce n'était pas le meilleur des exemples parce que beaucoup trouvent le code «fantaisie» plus lisible et compréhensible que le code plus long. L'idée était d'avoir un code plus long qui était beaucoup plus facile à comprendre qu'un code très court mais compliqué.

EDIT2: Voici un nouvel exemple que j'ai obtenu de SO :

Version fantaisie commentée:

//direct formula for xoring all numbers from 1 to N
int Sum = (N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ) );

Version longue non commentée:

int Sum = 0;
for (int i = 1; i < N; ++i)
{
   Sum ^= i; //or Sum = Sum ^ i;
}
gablin
la source
2
@gablin: "bien" est un mot, mais c'est un adjectif avec une signification quelque peu différente de "bien", et n'est plus largement utilisé (au moins aux États-Unis). La forme adverbe de "bien" est "bien". comme dans "code bien commenté".
John M Gant
@John: Ah oui, bien sûr. J'ai mis à jour la question en conséquence. Merci.
gablin
2
En quoi le court trajet est-il «fantaisiste»? C'est un morceau de code C de manuel que toute personne qui prétend connaître C devrait pouvoir lire sans aucun problème. La concision ne signifie pas «fantaisie».
JBRWilkinson
@JBRWilkinson: Comme je l'ai dit dans la partie modifiée de la question, cet exemple n'est pas bon car la version "fantaisie" n'est apparemment pas si élégante. L'objectif était d'avoir un moyen court mais incompréhensible avec commentaire, puis un moyen plus long mais beaucoup plus lisible sans commentaire.
gablin
@gablin: Votre modification compromet les réponses actuelles.
Maniero

Réponses:

28

Je préfère généralement extraire le code fantaisie dans sa propre méthode ..

Plutôt que de commenter le code fantaisie, son nom de méthode devrait être tout ce dont il a besoin pour clarifier les choses.

char *copy_string(char *s, const char *t) {    
    while (*s++ = *t++); 
    return s;
}
Mongus Pong
la source
3
Bon point. La prise en compte du code autonome est bien meilleure que les commentaires. Le compilateur sait comment l'intégrer si nécessaire.
dbkk
Ah ouais, c'est un excellent moyen de rendre le commentaire obsolète. Mais malgré cela, préféreriez-vous toujours le code fantaisie au code plus long?
gablin
En général, oui. Je pense que les méthodes courtes et bien nommées facilitent la lecture et la maintenance du code. La complexité prise en compte dans ses propres méthodes rend la réutilisation plus accessible et apparente. Il y a toujours des exceptions, finalement cela dépend toujours du code.
Mongus Pong
Votre fonction devrait sûrement être nommée 'strcpy'?
JBRWilkinson
Il y a une erreur dans ce morceau de code. Qu'est-ce qui est retourné? Que devait-on retourner? Il suffit d'en faire une méthode nulle et d'en finir;)
Christian Mann
10

Je suis pour la version longue. Le problème avec la version courte du code, en plus d'être plus difficile à lire pour certains programmeurs, est que la plupart du temps, il est plus difficile de repérer les erreurs en les regardant simplement.

J'ai un exemple réel. Dans notre produit, nous avions l'extrait de code suivant:

if (++someCounter < MAX_VALUE) {
    // Do something that has to be done only MAX_VALUE times
}

Ce code semble parfaitement raisonnable à première vue, mais après une longue période de temps, ce compteur déborde et brise la condition (dans le scénario réel, nous avons écrasé le système de production de notre client avec un MOO). Ce code est un peu moins "sophistiqué", mais il est clair qu'il fait ce qu'il est censé faire:

if (someCounter < MAX_VALUE) {
    ++someCounter;
    // Do whatever it is we came here for
}

Et vous pouvez dire que le développeur qui a écrit ce code n'était tout simplement pas assez bon (ce qui n'est pas vrai, il était un gars plutôt brillant), mais je pense que si votre technique de codage vous oblige à être super-duper en programmation DIEU Pour obtenir le bon code, vous faites quelque chose de mal. Votre code doit être aussi infaillible que possible pour vous et pour quiconque doit le conserver après vous (qui n'est peut-être pas aussi intelligent que vous).

Donc - je suis tout pour la simplicité et la clarté.

Edit: Oh, et en ce qui concerne les commentaires - cela n'a pas d'importance. Beaucoup de gens ne liront pas les commentaires de toute façon ( http://www.javaspecialists.co.za/archive/Issue039.html ) et ceux qui ne comprendront pas votre code sans commentaires, ne le comprendront pas assez bien avec eux pour qu'ils peut le maintenir. Le but est d'aider les gens à voir qu'un certain code est "correct", les commentaires ne peuvent pas aider avec ça.

Hila
la source
1
"écrasé le système de production de notre client" - ce qui est assez mauvais: -S
"Le problème avec la version courte du code, à part qu'il est plus difficile à lire pour certains programmeurs" - n'importe quel morceau de code peut être difficile "à lire pour certains programmeurs". Vous avez juste besoin de trouver des programmeurs assez stupides. Ne réduisez pas le code au plus petit dénominateur.
quant_dev
@quant_dev: à l'inverse, "Le débogage est deux fois plus difficile que d'écrire le code en premier lieu. Par conséquent, si vous écrivez le code aussi intelligemment que possible, vous n'êtes, par définition, pas assez intelligent pour le déboguer." - Brian W. Kernighan
Michael Borgwardt
@MichaelBorgwardt Je n'appliquerais pas aveuglément le dicton de Kernighan à toutes les situations possibles. L'exemple OPs est une fonction écrite "aussi intelligemment que possible" (ou proche d'elle) et pourtant elle devrait être assez facile à déboguer, si un débogage est nécessaire. D'un autre côté, les oneliners compliqués à manipuler les bits peuvent être très intelligents, mais seront certainement encore plus difficiles à déboguer. (Aussi: Kernighan suppose que les compétences de codage = compétences de débogage. Cela ne doit pas être le cas. J'ai réussi à déboguer du code que je n'aurais pas pu écrire.)
quant_dev
6

Je préfère généralement la version plus longue. Deux raisons principales viennent à l'esprit:

  • Plus de gens sont susceptibles de le comprendre avec moins d'effort (en supposant que ce n'est pas un exemple "standard" comme cette copie de chaîne).
  • Il est possible de mettre des points d'arrêt sur des instructions individuelles et de progresser avec un débogueur.

Pour le meilleur des deux mondes, enveloppez le code dans une fonction, dont le nom fait le commentaire pour vous:

void copy_string(char *s, char *t)
{
    *s = *t;
    while (*t != '\0') {
        t++;
        s++;
        *s = *t;
    }
}

La seule raison de ne pas le faire serait que les performances soient un problème et que le profilage montre véritablement que la surcharge de fonction était importante.

Paul Stephenson
la source
1
N'est-ce pas à cela que sert l'inline?
Antsan
En effet, bien que l'inlining comporte son propre lot de problèmes, comme devoir exposer le corps de la fonction dans les fichiers d'en-tête. Les compilateurs modernes n'incluent-ils pas automatiquement des choses pour vous là où c'est raisonnable de toute façon?
Paul Stephenson
4

Tout ce qui est le plus clair. Souvent, c'est un extrait de code compact et facile à comprendre qui ne nécessite pas de commentaire ... comme votre deuxième exemple.

Les extraits de code généralement plus courts sont plus faciles à comprendre car le lecteur a moins à garder dans sa tête à la fois. De toute évidence, il y a une limite lorsque le code est trop obscurci et je ne veux pas dire que l'espace blanc améliorant la clarté doit être coupé.

Les commentaires ne doivent jamais indiquer quoi que ce soit qui soit évident dans le code, qui fait simplement lire deux fois la même chose au lecteur. Pour moi, le premier extrait doit être clarifié. Pourquoi le développeur n'a-t-il pas utilisé une do...whileboucle pour supprimer le doublon de l' *s = *t;affectation? Je dois analyser plus de code pour réaliser qu'il implémente une copie de chaîne. Un commentaire serait plus utile sur ce code plus long que sur le code plus court.

Le commentaire sur le deuxième extrait est presque redondant car cette boucle while est pratiquement idiomatique, mais elle indique ce que le code fait à un niveau supérieur à celui du code lui-même, ce qui en fait un commentaire utile.

CB Bailey
la source
Le développeur (moi) n'a pas utilisé do ... whilesimplement parce que je n'y avais pas pensé quand j'ai écrit la question. Merci d'avoir fait remarquer cela. ^^ Le deuxième extrait peut être évident pour vous, mais ce n'est certainement pas pour moi.
gablin
4

Le problème est qu'il n'y a pas de définition claire short fancy codecar cela dépend beaucoup du niveau du programmeur. Alors que certaines personnes n'ont aucun problème à comprendre une while(*s++ = *t++);expression, d'autres le feront.

Personnellement, je trouve le plus while(*s++ = *t++);parfaitement lisible et le plus long plus difficile à lire. D'autres pourraient ne pas être d'accord cependant.

Quoi qu'il en soit, c'est juste une question de bon sens. La lisibilité devrait certainement être une priorité, mais il y a un point où un code plus long devient moins lisible lorsqu'il s'allonge. La verbosité réduit souvent la lisibilité de mon expérience.

Wolph
la source
Cela me rend triste qu'un thème de beaucoup de ces réponses soit "les développeurs peuvent ne pas reconnaître la manière standard d'écrire strcpy () en C"
AShelly
Cela ne devrait pas - cela ne signifie pas qu'il n'y a plus de bons programmeurs, mais plutôt a) que nous n'enseignons plus beaucoup C et b) que la force de C est aussi sa faiblesse - en ce que cette boucle est compréhensible pour un pratiquant en C c'est aussi assez mystérieux et dans un monde qui essaie d'écrire du code sécurisé assez effrayant pour ce qu'il implique sur ce que vous pouvez faire en C
Murph
Nous nous retrouvons donc avec un autre défi pour nos tâches quotidiennes. Besoin de deviner le niveau général de compréhension de la langue de nos pairs directs afin que nos révisions de code restent constructives. Ne pas tomber dans des batailles dont l'expression «correcte» et plus propre de l'intention.
frogstarr78
2

Je dois être en désaccord avec la plupart des autres réponses ici - je pense (au moins dans ce cas) que le code plus court est meilleur. Contrairement à votre affirmation, le code plus long n'est pas "plus facile", du moins pour un lecteur. Si quoi que ce soit, vous semblez être sorti de votre désir de l'allonger, même si cela rend le code plus difficile à comprendre et / ou à être assuré d'un fonctionnement correct.

En particulier, avoir l'affectation du premier octet de la chaîne en dehors de la boucle, distinct de l'affectation pour les autres octets, signifie qu'il faut être beaucoup plus prudent en lecture pour être sûr que tous les octets sont copiés correctement. La séquence de base des actions dans la version courte est beaucoup plus facile à vérifier. Son seul vrai problème est dans le formatage - lorsque vous avez un corps de boucle intentionnellement vide, il est préférable de le clarifier, quelque chose comme:

while (*dest++ = *source++)
    ;

ou même:

while (*dest++ = *source++)
    ; /* no body */

Certaines personnes préfèrent utiliser des accolades à la place:

while (*dest++ = *source++)
    {}

Quelle que soit la mise en forme exacte que vous préférez, suffisamment d'erreurs ont été commises avec des choses comme:

if (x>y);
     x = z;

... qu'il est important d'être sûr que 1) c'est évident ce qui est réellement contrôlé par n'importe quel contrôle de flux, et 2) il est évident que le code a été écrit en sachant ce qui était contrôlé par lui, donc quelqu'un qui le lit ne perd pas de temps à essayer pour savoir s'ils viennent de trouver un bug.

Jerry Coffin
la source
Oui, rétrospectivement de cet exemple particulier, la version «fantaisie» est probablement plus lisible que la version plus longue. Si je pouvais penser à un meilleur exemple, je le ferais, mais je n'y parviens pas pour le moment. Mais je n'ai pas «fait tout mon possible» pour l'allonger - c'est ainsi que j'écrirais une copie de chaîne, du moins au début. Ce n'est peut-être pas la meilleure approche, mais elle n'a pas été faite plus longtemps que nécessaire par intention.
gablin
2
Keep it simple, stupid!

Assurez-vous que tout autre programmeur peut comprendre ce que fait votre code - et encore mieux s'il est en un coup d'œil (c'est là que les bons noms et commentaires entrent en jeu).

Le kung-fu et l'assemblage en ligne fantaisistes sont tous excellents au nom de l'optimisation (peut-être inutile et prématurée), mais quand même vous ne pouvez pas comprendre le code que vous avez écrit lorsque vous rencontrez un bogue deux mois plus tard .. Quel était le point? Vous vous coûterez du temps et des efforts.

Je fais souvent référence au Zen de Python dans ces situations. En particulier:

Explicit is better than implicit.
Simple is better than complex.
Humphrey bogart
la source
1

N'écrivez pas de code sophistiqué dans un logiciel de production. Je sais que ça fait du bien de pouvoir réellement écrire ça, et c'est plus court. L'écriture de code fantaisie augmente considérablement la valeur "WTF / minute", en d'autres termes, diminue la qualité.

texte alternatif

Tamás Szelei
la source
1

Cela dépend bien sûr entièrement des circonstances. mais en général, je trouve que c'est une bonne règle d'or:

Le débogage est deux fois plus difficile que d'écrire le code en premier lieu. Par conséquent, si vous écrivez le code aussi intelligemment que possible, vous n'êtes, par définition, pas assez intelligent pour le déboguer.

~ Brian Kernighan

violet313
la source
plus long mais plus significatif, même élégant , que l' acronyme KISS plus compact ~ j'espère que l'ironie n'y est pas perdue; p
violet313
0

D'après mon expérience, la plus grande victoire en termes de code fantaisie court a tendance à utiliser la récursivité plutôt que l'itération. C'est aussi l'une des choses les plus difficiles à comprendre en un coup d'œil sur le code, à moins que vous ne travailliez dans le genre de langage où tout est récursif de toute façon. Je le préférerais toujours pour l'élégance et la rapidité de développement qu'il offre, mais j'essaie de m'assurer qu'il a des commentaires détaillés s'il semble qu'il sera opaque pour les futurs mainteneurs ou mon futur moi-même.

glénatron
la source
0

Je commence à ne jamais faire confiance aux commentaires. Trop souvent, les commentaires ne sont pas mis à jour lorsque le code est mis à jour et sont largement obsolètes ou représentent des règles de clients / de gestion qui ne sont plus pertinentes.

Il en est arrivé au point dans certains cas où les commentaires ne correspondent même plus au code qu'ils décrivent.

Si je dois choisir entre court / fantaisie et plus long / plus facile à comprendre, je choisis toujours ce dernier sauf s'il y a une très bonne raison.

Steven Evers
la source
0

La lisibilité et la maintenabilité sont essentielles, et votre deuxième exemple (c'est-à-dire le plus long) est bien plus des deux. Mais pourquoi vous limiter à deux options? Même le code plus long est trop complexe (à mon humble avis) pour ne pas le noter davantage. Je le mettrais dans sa propre méthode avec Javadoc approprié (ou autre) et un nom de méthode approprié.

Chris Knight
la source