Dois-je sacrifier des noms de variable plus courts pour un code «à colonnes» plus long?

17

Je suis un programmeur amateur dans une classe CS essayant d'apprendre des compétences de programmation appropriées. Voici à quoi ressemble mon code, les bords de celui-ci s'étendent à 103 colonnes.

int extractMessage(char keyWord[25], char cipherText[17424],
                   int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);


    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }

Avant d'avoir ces noms de variables super longs, j'avais des choses comme i, j, k, mais mon professeur insiste sur le fait que nous ne devons pas utiliser des variables comme ça dans le "monde professionnel" et que même des variables raccourcies comme lenWord sont insuffisantes parce que les gens pourraient supposer il signifie "Lennard's World Literature". Il dit de choisir des noms de variables significatifs, mais ce faisant, j'ai l'impression d'avoir enfreint la règle d'or du codage pour la maintenir sous 80 colonnes. Comment puis-je contourner cela?

RaulT
la source
26
Continue; ajoutez des noms plus utiles. Pouvez - vous penser à une façon de décrire cipherColumn + (rowSize*nextWord) + nextWordqui fait clairement ce que le calcul est pour , par exemple? Je parie que ce nom est plus court que le calcul, donc vous obtenez un avantage de lisibilité et une longueur de ligne réduite. N'alignez pas non plus les affectations, ou vous devez toutes les déplacer si vous renommez la variable la plus longue.
jonrsharpe
2
Hmm .. alors dites-vous que je devrais créer une nouvelle variable et stocker le résultat de cipherColumn + (rowSize * nextWord) + nextWord dedans pour que je puisse l'utiliser plus loin? C'est ce que font les pros? Je demande vraiment
RaulT
8
Oui, c'est ma suggestion. Je suis un pro et c'est ce que je ferais, donc ... certains au moins.
jonrsharpe
11
la règle d'or est d'écrire du code qui peut être lu et compris. nous écrivons du code pour d'autres personnes (!) pas pour des machines. pour les machines, il existe un code machine. pour certains, le code qui ressemble à ce que vous avez décrit (noms à une seule lettre, etc.) est un manque de respect pour les autres programmeurs (et pour vous - parce que vous oublierez dans les semaines ou les mois à venir). il n'y a aucune raison de s'en tenir à 80 colonnes, ce n'est pas MS DOS dans les années 80.
rsm
3
@stijn oui, mais c'est la dernière fois que nous en avons besoin. tout comme je ne compile pas mon code c pour un processeur 8086 8 bits au cas où je devrais le stocker sur des cartes perforées, je ne pense pas non plus que le standard doré de 80 colonnes ait une signification au 21 siècle. nous devons étirer cette technologie, ne pas nous asseoir dans les années 80 et penser qu'elle fait de nous des hackers intelligents. intelligent est la simplicité, la lisibilité et la technologie de poussée à son maximum. nous avons des moniteurs Full HD, il est temps de l'utiliser.
rsm

Réponses:

24

Normalement, quand je vois du code affiché ici comme le vôtre, je le modifie, car nous détestons le défilement horizontal. Mais puisque cela fait partie de votre question, je vais vous montrer le montage ici:

int extractMessage(char keyWord[25], char cipherText[17424],
                   int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);


    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }
}

Cette pause peut surprendre, mais il est plus lisible que la version avec défilement horizontal, et il vaut mieux que raccourcir les noms i, jet k.

Ce n'est pas que vous ne devez jamais utiliser i, jet k. Ce sont de bons noms lors de l'indexation de 3 forboucles imbriquées . Mais ici, les noms sont vraiment mon seul indice sur ce que vous attendiez. D'autant plus que ce code ne fait rien.

La meilleure règle à suivre sur la longueur du nom de variable est la portée. Plus une variable vit longtemps, plus il y a de variables avec lesquelles son nom doit rivaliser. Le nom CandiedOrange est unique sur l'échange de pile. Si nous étions en discussion, tu pourrais juste m'appeler "Candy". Mais en ce moment, vous êtes dans une perspective où ce nom pourrait être confondu avec Candide , Candy Chiu ou Candyfloss . Donc, plus la portée est longue, plus le nom doit être long. Plus la portée est courte, plus le nom peut être court.

La longueur de ligne ne doit jamais dicter la longueur du nom. Si vous en avez envie, trouvez une autre façon de présenter votre code. Nous avons de nombreux outils pour vous y aider.

L'une des premières choses que je recherche, c'est le bruit inutile pour s'en débarrasser. Malheureusement, cet exemple ne fait rien, donc tout ce bruit inutile. J'ai besoin de quelque chose avec lequel travailler alors commençons par faire quelque chose.

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    int lengthOfWord   = 0;
    int lengthOfCipher = 0;

    lengthOfWord = length(keyWord);
    lengthOfCipher = length(cipherText);

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
            continue;
        }
    }
    return cipherColumn;
}

Là, maintenant ça fait quelque chose.

Maintenant qu'il fait quelque chose, je peux voir de quoi je peux me débarrasser. Ce truc de longueur n'est même pas utilisé. Cela continuene fait rien non plus.

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn    = 0;
    int cipherColumn = 0;
    int offset       = 1;
    int nextWord     = 1;

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

Faisons quelques ajustements mineurs dans les espaces blancs, car nous vivons dans un monde de contrôle de source et c'est bien quand la seule raison pour laquelle une ligne est signalée comme modifiée est parce qu'elle fait quelque chose de différent, pas parce qu'une partie de celle-ci devait s'aligner dans une colonne.

int calcCipherColumn(char keyWord[25], char cipherText[17424],
                     int rowSize, char message[388]) 
{
    int keyColumn = 0;
    int cipherColumn = 0;
    int offset = 1;
    int nextWord = 1;

    while (keyWord[keyColumn] != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyWord[keyColumn + offset] 
        != cipherText[cipherColumn + (rowSize*nextWord) + nextWord]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

Oui, je sais que c'est un peu moins lisible, mais sinon, vous rendrez fou les gens qui utilisent les outils vdiff pour détecter les changements.

Maintenant, corrigeons ces sauts de ligne stupides que nous avons parce que nous essayons de rester sous les limites de longueur de ligne.

int calcCipherColumn(
        char keyWord[25], 
        char cipherText[17424],
        int rowSize, 
        char message[388]
) {
    int keyColumn = 0;
    int keyOffset = 1;

    int nextWord = 1;
    int cipherColumn = 0;
    int cipherOffset = (rowSize * nextWord) + nextWord;

    char key = keyWord[keyColumn];
    char keyNext = keyWord[keyColumn + keyOffset];

    while (key != cipherText[cipherColumn]) {
        cipherColumn++;
        if (keyNext != cipherText[cipherColumn + cipherOffset]) {
            cipherColumn++;
        }
    }
    return cipherColumn;
}

Là, maintenant la logique dans la boucle se concentre sur ce qui change dans la boucle. En fait, tout sauf cipherColumnpourrait être marqué final. Et bon! Regarde ça. Nous avons maintenant de la place pour le faire.

Tout ce que j'ai fait, c'est ajouter 3 variables supplémentaires, renommer une et les réorganiser un peu. Et le résultat est arrivé à rendre les lignes suffisamment courtes pour s'adapter sans un saut de ligne idiot !=.

Bien sûr , les noms keyet keyNextne sont pas que descriptive, mais chacun ne s'utilisé qu'une seule fois, ne pas vivre longtemps, et surtout ne font pas tout ce qui intéressant dans la boucle. Ils n'ont donc pas besoin de l'être. En introduisant des variables supplémentaires, nous avons maintenant de la place pour rendre leurs noms longs si nous en avons besoin. Les choses changent, nous devrons donc éventuellement le faire. Si nous le faisons, c'est bien que nous ayons de la respiration.

J'ai également pris la liberté de vous montrer le style de variante de la forme 6 de Jeff Grigg de présentation des paramètres d'entrée pour respecter les restrictions de longueur de ligne.

candied_orange
la source
Wow c'est descriptif! Oui, je sais que le code ne fait vraiment rien, j'aurais probablement dû en publier plus qu'un petit extrait, mais je suppose que j'essayais d'avoir une idée générale de ce que les pros font en ce qui concerne la longueur de la colonne de code et les noms de variables, mais votre réponse a montré des changements très doux que je vais certainement implémenter dans mes codes à partir de maintenant! Une autre question que j'ai est: où trouvez-vous approprié de faire des sauts de ligne? Avant les opérateurs? Existe-t-il une "norme" acceptée?
RaulT
1
@RaulT passe du temps à lire la base de code dans laquelle vous travaillez. Cela vous donnera une idée de ce que vous pouvez utiliser qui ne surprendra pas les autres codeurs. Suivez un document de normes si vous en avez un. Mais le mieux est de demander à d'autres programmeurs et de leur demander à quel point vos contenus sont lisibles. Oh et consultez codereview.stackexchange.com
candied_orange
J'ajouterais un commentaire ci-dessous cipherOffset et expliquerais le calcul car cette formule n'est pas évidente. Vous OUBLIEREZ pourquoi dans trois semaines.
Nelson
15

D'autres ont déjà fait quelques suggestions utiles, permettez-moi de résumer:

  • 80 caractères par ligne auraient pu être une règle d'or dans les années 80. De nos jours, la plupart des gens conviennent que 100 à 130 caractères conviennent.
  • Utilisez des sauts de ligne dans vos expressions.
  • Séparez les expressions longues en introduisant des résultats intermédiaires.

J'aime ajouter une autre recommandation: ne soyez pas dogmatique à propos des noms longs! Plus la portée d'une variable est grande, plus il faut mettre d'informations dans son nom. Et généralement, c'est une bonne idée de garder la portée des variables petite.

Par exemple, si vous avez une variable pour la colonne de votre table de chiffrement de mots clés et qu'il est clair qu'il n'y a qu'une seule table utilisée dans la portée de votre variable, il est correct de l'appeler columnou même col. Si la portée est plus grande et que plusieurs tables sont impliquées, il est judicieux de l'appeler keyWordEncryptionTableColumn.

Un autre exemple: si vous avez une boucle avec un corps couvrant deux ou trois lignes et devez utiliser un index pour accéder aux éléments d'un tableau, il n'y a rien de mal à appeler l'index i. Dans ce contexte, il est beaucoup plus lisible (pour la plupart des gens au moins) que, disons arrayIndexOfMyVerySpecialDataSet.

Frank Puffer
la source
1
Je suis d'accord avec votre réponse. Au travail, nous utilisons 80 caractères / ligne pour c / c ++ pour des raisons héritées et parce que nous utilisons Reviewboard. Pour les caractères C / 100 / ligne, j'ai parfois enfreint la règle et dépassé légèrement 100 pour conserver la lisibilité.
peval27
Wow, quelle excellente réponse !! Tous ces responsables ont été formidables, merci pour l'aide que j'apprécie!
RaulT
Je suis tout à fait d'accord avec l'idée que 80 lignes de caractères sont obsolètes. Cela s'applique toujours à certains projets et lieux (principalement pour la cohérence), mais pour beaucoup, c'est tout simplement inutile. De nombreux développeurs utilisent quelque chose comme Visual Studio ou IntelliJ sur un moniteur complet et ont un deuxième moniteur pour d'autres choses (documentation, etc.). Ils disposent ainsi de beaucoup d'écran immobilier pour leur code. Si vous n'utilisez que 80 caractères par ligne, vous disposez probablement d'une tonne d'espace inutilisé. Et la limite de 80 caractères vous fait mal! Surtout quand on considère que la bibliothèque standard peut forcer des noms de cul longs.
Kat
1
Mon point étant que dans certaines langues, il est vraiment impossible d'éviter le fait que 80 caractères soit une grande limitation. Alors pourquoi l'avoir inutilement? Cela demande également de mentionner que presque tous les éditeurs et IDE de grands noms ont un excellent habillage intelligent des mots doux de nos jours, ce qui vous permet de ne pas restreindre les longueurs de ligne. Vous pouvez laisser les longueurs de ligne être ce que le lecteur peut voir. Ils peuvent redimensionner leur fenêtre pour obtenir un résultat plus optimal. J'ai personnellement trouvé cette approche parfois idéale. Et je n'ai pas encore été déçu du fonctionnement de cette enveloppe souple.
Kat
Chaque fois que vous utilisez des noms de variables simples, vous DEVEZ 100% être certain de la portée. J'ai passé trois heures à découvrir la fermeture de JavaScript.
Nelson
3

Je suis généralement d'accord avec vous, professeur. Cependant, si vous avez une variable que vous allez utiliser beaucoup dans un gros morceau de code défaillant, il peut être préférable d'utiliser une forme abrégée pour elle après avoir été explicite sur sa signification. Comme lorsque vous avez beaucoup d'expressions et d'affectations arithmétiques complexes, celles-ci ne se lisent pas aussi bien avec des noms de variable longs.

À propos des grandes lignes:

ExtractMessage(char keyWord[25], char cipherText[17424],
               int rowSize, char message[388]) 

Cela ne sert à rien, le fait de limiter la longueur de la ligne ne la rend pas plus lisible. Si vous voulez que cela soit lisible, procédez comme suit:

ExtractMessage(
  char keyWord[25],
  char cipherText[17424],
  int rowSize,
  char message[388]
  )
{

Et puis, vous pouvez même vouloir aligner les identificateurs de type (ajoutez un espace après int). Cependant, soyez prudent / restrictif en décrivant les initalisations ou les listes d'arguments comme ceci:

int keyColumn    = 0;
int cipherColumn = 0;
int offset       = 1;
int nextWord     = 1;

Le problème est que lorsque vous modifiez un nom ou ajoutez une variable, vous devrez peut-être reformater tout le bloc pour conserver son aspect esthétique. Ce n'est pas pour le travail autant que pour les changements insignifiants que vous introduiriez, cela aurait l'air horrible dans un système de contrôle de version. Votre collègue verrait que vous avez modifié le fichier et fera une différence avec la version précédente pour voir ce que vous avez fait. Ensuite, chaque ligne s'allumait comme modifiée, masquant le vrai changement. Cela dépendrait un peu de la qualité de l'outil de comparaison utilisé, à quel point cela serait mauvais, mais en général, ce n'est pas une bonne idée de rendre le code trop personnel et / ou de faire dépendre le formatage d'une ligne de l'autre.

Parfois, le contour peut servir à quelque chose, si vous avez des dizaines de lignes consécutives qui sont presque les mêmes, il sera facile de repérer où elles sont différentes si vous les décrivez.

Notez qu'un lieu de travail peut avoir un formatage automatisé en cours qui supprimera simplement tout formatage de fantaisie que vous faites à votre code avant de le soumettre au système de contrôle de version.

Martin Maat
la source
1
Personnellement, le premier bloc de code dans votre réponse est beaucoup plus lisible pour moi que le second.
Miles Rout
1
ne faites jamais le troisième, c'est un cauchemar de maintenance pour le garder comme ça.
jwenting
3

Avertissement: j'exagère un peu ici pour clarifier mon propos. Prenez donc tout superlatif avec un grain de sel.

Votre professeur a raison à 100%: il n'y a plus de "règle d'or" concernant environ 80 caractères (sauf si vous écrivez du code linux, c'est-à-dire). Cette règle a été établie en raison de la taille des terminaux à l'époque, mais de nos jours, vous pouvez facilement entasser plus de 150 caractères dans votre fenêtre enditor. Et même si vous dépassez cette limite, votre éditeur devrait, espérons-le, boucler la ligne en douceur afin que vous n'ayez pas à faire défiler. Et la seule raison de ne pas dépasser 80 caractères était la nécessité de faire défiler .

Cela dit, il est en effet nécessaire de ne pas laisser vos lignes croître indéfiniment. Plus la ligne est longue, plus il devient difficile pour un humain d'analyser. Mais les noms de variables courts ne sont pas le remède au problème des longues lignes .

Le remède consiste à diviser vos expressions logiquement en introduisant des variables encore plus correctement nommées . N'essayez pas d'être intelligent avec les espaces blancs. Identifiez simplement toute sous-expression qui peut être correctement nommée et créez une variable pour elle. Cela simplifie à la fois le code calculant la variable et le code utilisant cette variable .


Cela ne fait pas partie de votre question, mais j'aimerais quand même commenter: c'est une très mauvaise idée d'aligner verticalement vos =opérateurs.

Il y a trois raisons à cela:

  1. La modification d'un bloc contenant des opérateurs alignés verticalement est un PITA. Chaque fois que la longueur de la plus grande variable change (renommer, ajouter, supprimer), vous devez retoucher toutes les lignes du bloc pour retrouver votre "belle" disposition.

    Bien sûr, ce problème peut être réduit un peu en utilisant un éditeur compétent, c'est donc la raison mineure. La vraie raison est la seconde:

  2. Ces faux espaces blancs introduits par le réalignement ne fonctionnent pas bien avec les systèmes de contrôle de version modernes comme git. Ils ont tendance à créer des quantités importantes de conflits de fusion là où aucun conflit réel ne s'est produit et où aucun conflit ne serait signalé si l'alignement n'était pas utilisé. Chacun de ces faux conflits vous coûtera un temps précieux pour rien .

  3. L'alignement n'a aucune signification sémantique . C'est inutile. Il n'y a rien que vous puissiez mieux comprendre avec l'alignement. Chaque ligne de votre bloc doit être lue seule pour comprendre ce qu'elle fait, la connexion aux lignes ci-dessus et ci-dessous est de nature purement syntaxique.

Étant donné que l'alignement n'a aucune signification sémantique, mais génère des coûts importants, vous devez désapprendre l'habitude avant qu'elle ne vous coûte plus de temps.


Si vous aimez tant la limite de 80 caractères, essayez une programmation fortran. Certes, les nouvelles normes ont augmenté la limite de ligne fortran à 132 caractères, mais elle reste en vigueur, comme toujours, paralysant la compilation de tout programme qui dépasse la limite. Si vous êtes bon en programmation, vous allez bientôt détester le fortran, y compris sa limite de longueur de ligne. Après cela, vous serez guéri pour le reste de votre vie.

J'ai moi-même dû faire de la programmation fortran professionnellement, et je vous le dis, cela m'a appris à détester cette limite de longueur de ligne très cher. Il n'y a absolument rien de plus frustrant que de devoir diviser une ligne autrement simple et lisible en parties simplement parce que le compilateur ne la compilera plus correctement. Et il y a certainement des lignes de code qui sont plus simples lorsqu'elles sont exprimées en une seule ligne.

cmaster - réintégrer monica
la source
3

De nombreuses conventions stylistiques (pas des règles!) Sont apparues au fil des ans en raison des limitations des environnements de programmation. Retour en jours-cartes perforées, vous aviez une dure limite du nombre de caractères qui pourraient apparaître sur une ligne de source physique (qui était la raison pour laquelle la colonne réservée Fortran 6 pour les caractères de continuation). Il n'y a pas si longtemps, je travaillais sur un terminal VT220 ambre sur noir 80x24; alors que les éditeurs que j'ai utilisés ne limitaient pas les lignes à 80 caractères, la vie était beaucoup plus facile si vous faisiez de votre mieux pour éviter le défilement horizontal.

Sous les anciennes versions de Fortran (jusqu'à 77, IINM), vous ne pouviez même pas avoir d' identifiants de plus de 6 à 8 caractères. Même aussi tard que dans les années 80, C ne garantissait que les 8 premiers caractères des noms externes étaient significatifs (c'est pourquoi certaines fonctions de bibliothèque ont des noms merveilleusement descriptifs comme strpbrk).

Bien sûr, deux décennies après le début du 21e siècle, nous n'avons plus ces limites. Il n'y a aucune raison de ne pas utiliser plus d'identifiants descriptifs.

La chose est, dans les contextes à droite, iet jet ksont parfaitement raisonnables, des noms significatifs . Si j'itère à travers un tableau ou un vecteur dans une boucle et que j'ai juste besoin de quelque chose pour identifier l'élément actuel, cela ifonctionne parfaitement bien. Je n'utiliserais pas un nom comme currentElement- il n'a plus de sens dans ce contexte , et cela ajoute simplement du désordre visuel.

Cela dit, votre professeur n'a pas tort de vous forcer à penser en termes de noms plus longs et plus descriptifs pour tout - la vie sera plus facile pour vous si vous prenez d'abord cette habitude, puis apprenez où économiser si nécessaire. En tant que personne qui a été obligée à tout moment de tout faire en 8 caractères ou moins, il est certainement préférable d'errer du côté de plus d'informations que de moins. Au fur et à mesure que vous gagnez en expérience, vous apprendrez où vous pouvez économiser sur la longueur de l'identifiant et où vous devez être un peu plus descriptif.

John Bode
la source
-1

Je ne sais pas si cela fonctionne pour c ou non, mais existe-t-il un moyen de fractionner les formules sur plusieurs lignes? Je sais que quelque chose comme ça existe pour python.

Voyez si vous pouvez commencer + (rowSize * nextWord) + nextWord]) {sur une nouvelle ligne. (Comme appuyez sur Entrée dans votre IDE et voyez s'il l'indente afin que C sache que l'expression précédente est en train de se terminer sur la ligne actuelle)

Krio
la source
1
Oui, c'est définitivement possible. C reconnaît les lignes et les lignes de code jusqu'à ce que vous ajoutiez quelque chose comme un point-virgule. Le problème avec cela est que nos fonctions ne peuvent pas dépasser 50 lignes, et bien que mon exemple de code n'ait pas 50 lignes, ce n'est qu'une fraction de ma fonction totale. Je me sens fortement contraint d'écrire dans une boîte de 50 par 80, des algorithmes avec des variables significatives qui peuvent également exécuter les fonctions dont j'ai besoin. Je pourrais continuer à stocker ces longs morceaux de code dans de nouvelles fonctions, mais je sens que je vais me retrouver avec tant d'appels de fonction que les gens se perdront en lisant le code.
RaulT
5
"Je sens que je vais me retrouver avec tellement d'appels de fonction, les gens se perdront en lisant le code." Bien au contraire! L'extraction de code dans des méthodes distinctes vous permet de leur donner des noms descriptifs améliorant la lisibilité (en particulier de la méthode à partir de laquelle vous extrayez). Si vous vous retrouvez avec trop de méthodes, votre classe pourrait en faire trop (principe de responsabilité unique). Extraire à nouveau les méthodes dans une classe distincte vous permet de donner à cette chose un nom descriptif.
Roman Reiner
Toute fonction qui approche les 50 lignes est probablement trop longue et trop complexe (à l'exception peut-être de l'initialisation des données avec une complexité de 1), mais généralement lorsque des limites comme celle-ci sont discutées, ce sont des lignes de code et non des lignes de texte. ligne de code, c'est-à-dire que le point-virgule ne compte souvent pas comme une ligne supplémentaire, vérifiez avec le Prof!
Steve Barnes