Sacrifico nomi di variabili più brevi per codice "a colonne" più lungo?

17

Sono un programmatore dilettante in una classe CS che cerca di apprendere le corrette abilità di programmazione. Ecco come appare il mio codice, i suoi bordi si estendono fino a 103 colonne.

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;
        }
    }

Prima di avere quei nomi variabili super lunghi avevo cose come io, j, k, ma il mio professore insiste che non dobbiamo usare variabili del genere nel "mondo professionale" e che anche le variabili abbreviate come lenWord sono insufficienti perché la gente potrebbe presumere che sia sinonimo di "Lennard's World Literature". Dice di scegliere nomi variabili significativi, ma così facendo mi sembra di aver infranto la regola d'oro della codifica per mantenerla sotto le 80 colonne. Come faccio a evitare questo?

    
posta RaulT 18.03.2017 - 04:10
fonte

6 risposte

24

Normalmente quando vedo il codice pubblicato qui come il tuo, lo modifico, perché odiamo lo scroll orizzontale. Ma dal momento che fa parte della tua domanda, ti mostrerò la modifica qui:

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;
        }
    }
}

Questa interruzione potrebbe sorprendere, ma è più leggibile rispetto alla versione con scorrimento orizzontale, ed è meglio che abbreviare i nomi a i , j e k .

Non è che non dovresti mai usare i , j e k . Si tratta di nomi fini quando si indicizzano 3 cicli nidificati for . Ma qui i nomi sono davvero il mio unico indizio su cosa ti aspettavi che accadesse. Soprattutto perché questo codice in realtà non fa nulla.

La migliore regola da seguire sulla lunghezza del nome della variabile è l'ambito. Più una variabile è lunga, più variabili con cui il nome deve competere. Il nome CandiedOrange è unico nello scambio di pile. Se fossimo in una chat, potresti chiamarmi semplicemente "Candy". Ma al momento, sei in un ambito in cui quel nome potrebbe essere confuso con Candido , Candy Chiu o Candyfloss . Più lungo è il raggio d'azione, più lungo dovrebbe essere il nome. Più corto è lo scope, più breve è il nome.

La lunghezza della linea dovrebbe mai dettare la lunghezza del nome. Se ritieni che sia quindi trovare un modo diverso di disporre il codice. Abbiamo molti strumenti per aiutarti a farlo.

Una delle prime cose che cerco è il rumore inutile da eliminare. Sfortunatamente questo esempio non fa nulla, quindi è tutto rumore inutile. Ho bisogno di qualcosa su cui lavorare, quindi prima facciamolo fare qualcosa.

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;
}

Ecco, ora fa qualcosa.

Ora che fa qualcosa, posso vedere di cosa posso sbarazzarmi. Questa roba di lunghezza non è nemmeno usata. Anche questo continue non fa nulla.

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;
}

Facciamo qualche piccolo aggiustamento dello spazio bianco, perché viviamo in un mondo di controllo del codice sorgente ed è bello quando l'unica ragione per cui una riga viene segnalata come modificata è perché sta facendo qualcosa di diverso, non perché una parte di essa doveva allinearsi in una colonna.

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;
}

Sì, lo so che è leggermente meno leggibile, ma altrimenti farai impazzire la gente che usa gli strumenti di vdiff per rilevare i cambiamenti.

Ora risolviamo queste sciocche interruzioni di linea che abbiamo perché stiamo cercando di rimanere al di sotto dei limiti di lunghezza della linea.

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;
}

Ecco, ora la logica nel ciclo è focalizzata su quali cambiamenti nel ciclo. Infatti, tutto tranne cipherColumn potrebbe essere contrassegnato come final . Ehi! Guarda quello. Ora abbiamo spazio per farlo.

Tutto ciò che ho fatto è stato aggiungere altre 3 variabili, rinominarne una e riorganizzarle un po '. E il risultato è appena accaduto per rendere le linee abbastanza corte per adattarsi senza una stupida interruzione di riga su != .

Sicuramente i nomi key e keyNext non sono così descrittivi, ma vengono usati solo una volta, non vivono a lungo e, cosa più importante, non fanno nulla di interessante nel ciclo. Quindi non hanno bisogno di essere. Introducendo variabili extra ora abbiamo spazio per rendere i loro nomi lunghi se necessario. Le cose cambiano, quindi alla fine potremmo aver bisogno di farlo. Se lo facciamo, è bello che abbiamo il respiro.

Mi sono anche preso la libertà di mostrarti la variante di forma 6 di Jeff Grigg per definire i parametri di input in modo da rispettare le restrizioni sulla lunghezza della linea.

    
risposta data 18.03.2017 - 16:27
fonte
15

Altri hanno già fornito alcuni suggerimenti utili, vorrei riassumere:

  • 80 caratteri per linea potrebbe essere stata una regola d'oro negli anni '80. Oggigiorno la maggior parte delle persone concorda sul fatto che da 100 a 130 caratteri vanno bene.
  • Utilizza interruzioni di riga all'interno delle espressioni.
  • Dividi le espressioni lunghe introducendo risultati intermedi.

Mi piace aggiungere un altro consiglio: Non essere dogmatico riguardo ai nomi lunghi! Più è ampio lo scopo di una variabile, più informazioni devono essere inserite il suo nome. E generalmente è una buona idea mantenere l'ambito delle variabili piccolo.

Ad esempio, se si dispone di una variabile per la colonna della tabella di crittografia delle parole chiave ed è chiaro che esiste solo questa tabella utilizzata nell'ambito della variabile, è corretto chiamarla column o anche% codice%. Se l'ambito è più grande e sono coinvolte più tabelle, ha senso chiamarlo col .

Un altro esempio: se hai un ciclo con un corpo che comprende due o tre linee e devi usare un indice per accedere agli elementi di un array, non c'è niente di sbagliato nel chiamare l'indice keyWordEncryptionTableColumn . In questo contesto è molto più leggibile (per la maggior parte delle persone almeno) di, diciamo i .

    
risposta data 18.03.2017 - 10:11
fonte
4

In genere sono d'accordo con te insegnante. Tuttavia, se si dispone di una variabile che si utilizzerà molto in un pezzo di codice di faily di grandi dimensioni, può essere preferibile utilizzare una forma abbreviata per esso dopo essere stato esplicito sul suo significato. Come quando hai un sacco di espressioni e compiti aritmetici complessi, quelli non leggono molto bene con nomi di variabili lunghi.

Informazioni sul contorno:

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

Questo non serve a nulla, limitando solo la lunghezza della linea non lo rende più leggibile. Se vuoi che questo sia leggibile, fai questo:

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

E poi potresti anche voler allineare gli identificatori di tipo (aggiungi uno spazio dopo int). Tuttavia, sii attento / restrittivo con la definizione di initalizzazioni o liste di argomenti come questa:

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

Il problema è quando cambi un nome o aggiungi una variabile, potresti dover riformattare l'intero blocco per mantenere l'aspetto grazioso. Non è tanto per il lavoro quanto per i cambiamenti privi di significato che introdurrebbe, sembrerebbe orribile in un sistema di controllo delle versioni. Il tuo collaboratore ti vedrebbe cambiato il file e fare una diff con la versione precedente per vedere cosa hai fatto. Quindi ogni linea si accendeva come cambiata, oscurando il vero cambiamento. Dipenderebbe un po 'dalla qualità dello strumento di confronto usato quanto male sarebbe in realtà, ma in generale non è una buona idea rendere il codice troppo personale e / o avere la formattazione di una linea dipendente dall'altra.

A volte il contorno può servire a uno scopo, se hai decine di righe consecutive che sono quasi le stesse sarà facile individuare dove sono differenti se le elimini.

Tieni presente che su un luogo di lavoro potrebbe essere attiva una formattazione automatica che eliminerà qualsiasi formattazione di fantasia che fai sul tuo codice prima di inviarlo al sistema di controllo della versione.

    
risposta data 18.03.2017 - 08:58
fonte
3

Disclaimer: sto esagerando un po 'qui per rendere più chiaro il mio punto. Quindi prendi qualsiasi superlativo con un pizzico di sale.

Il tuo insegnante ha ragione al 100%: non esiste più una "regola d'oro" di circa 80 caratteri (a meno che tu non stia scrivendo il codice di linux, cioè). Quella regola è stata stabilita a causa delle dimensioni dei terminali al momento, ma al giorno d'oggi, si raccolgono facilmente oltre 150 caratteri nella finestra del proprio enditor. E anche se superi questo limite, il tuo editore spera che la riga si sposti in modo morbido, in modo da non dover scorrere. E l'unica ragione per non andare oltre gli 80 caratteri era la necessità di scorrere .

Detto questo, è davvero necessario non lasciare che le tue linee crescano indefinitamente. Più lunga è la linea, più difficile diventa per un essere umano analizzare. Ma i nomi di variabili brevi non sono il rimedio per il problema delle righe lunghe .

Il rimedio è di dividere logicamente le tue espressioni introducendo anche variabili con un nome più appropriato . Non cercare di essere intelligente con gli spazi bianchi. Identifica qualsiasi sottoespressione che può essere opportunamente denominata e crea una variabile per esso. Questo semplifica sia il codice che calcola la variabile, sia il codice che utilizza quella variabile .

Non una parte della tua domanda, ma mi piacerebbe comunque commentarla: è una pessima idea allineare verticalmente i tuoi operatori = .

Ci sono tre ragioni per questo:

  1. La modifica di un blocco contenente operatori con allineamento verticale è un PITA. Ogni volta che la lunghezza della variabile più grande cambia (rinominare, aggiungere, eliminare), è necessario ritoccare tutte le righe nel blocco per ottenere di nuovo il layout "bello".

    Ovviamente, questo problema può essere ridotto un po 'usando un editor competente, quindi è la ragione minore. Il vero motivo è il secondo:

  2. I cambiamenti spuri di spazi bianchi introdotti dal riallineamento non funzionano bene con i moderni sistemi di controllo delle versioni come git . Tendono a creare quantità significative di conflitti di fusione in cui non si è verificato alcun conflitto reale e in cui non viene segnalato alcun conflitto se l'allineamento non è stato utilizzato. Ognuno di questi conflitti spuri ti costerà del tempo prezioso per niente .

  3. L'allineamento ha un significato semantico zero . È inutile. Non c'è niente che tu possa capire meglio con l'allineamento. Ogni riga del blocco deve leggere da sola per capire cosa fa, la connessione alle linee sopra e sotto è di natura puramente sintattica.

Poiché l'allineamento non ha alcun significato semantico, ma produce costi significativi, dovresti disimparare l'abitudine prima che ti costi più tempo.

Se ti piace il limite di 80 caratteri così tanto, prova qualche programmazione fortran. È vero, i nuovi standard hanno innalzato il limite della linea di fortran a 132 caratteri, ma rimane in vigore come sempre paralizzante la compilazione di qualsiasi programma che superi il limite. Se sei bravo a programmare, presto verrai a odiare Fortran, incluso il limite di lunghezza della linea. Dopo di ciò, sarai guarito per il resto della tua vita.

Io stesso ho dovuto fare qualche programmazione fortran professionalmente, e ti dico, mi ha insegnato a odiare il limite di lunghezza della linea più caro. Non c'è assolutamente nulla di più frustrante di dover dividere una linea altrimenti semplice e leggibile in parti solo perché il compilatore non lo compilerà più correttamente. E ci sono sicuramente linee di codice che sono più semplici quando sono espresse come una singola riga.

    
risposta data 08.04.2017 - 23:07
fonte
3

Molte delle convenzioni stilistiche (non regole!) sono nate nel corso degli anni a causa di limitazioni negli ambienti di programmazione. Tornando ai giorni delle carte perforate, hai avuto un Limite difficile sul numero di caratteri che potrebbero apparire su una linea di origine fisica (motivo per cui Fortran ha riservato la colonna 6 per i caratteri di continuazione della riga). Non molti decenni fa stavo lavorando su un terminale VT220 color ambra-on-black 80x24; mentre gli editor che ho usato non limitavano le righe a 80 caratteri, la vita era molto più semplice se facevi del tuo meglio per evitare lo scrolling orizzontale.

Nelle versioni precedenti di Fortran (fino a '77, IINM), non potevi nemmeno avere identificatori con una lunghezza compresa tra 6 e 8 caratteri. Anche fino agli anni '80, C garantiva solo che i primi 8 caratteri nei nomi esterni fossero significativi (ecco perché alcune funzioni della libreria hanno nomi meravigliosamente descrittivi come strpbrk ).

Naturalmente, da due decenni al XXI secolo, non abbiamo più questi limiti. Non c'è alcun motivo non per usare identificatori più descrittivi.

La cosa è, nei contesti giusti, i e j e k sono nomi perfettamente ragionevoli e significativi . Se sto iterando attraverso un array o un vettore in un ciclo e ho solo bisogno di qualcosa per identificare l'elemento corrente, i funziona perfettamente. Non userei un nome come currentElement - non è più significativo in quel contesto , e aggiunge solo confusione visiva.

Detto questo, il tuo insegnante non ha torto a costringerti a pensare in termini di nomi più lunghi e più descrittivi per tutto - la vita sarà più facile per te se entri per primo in quell'abitudine, e poi imparare dove risparmiare se necessario. Come qualcuno che era un tempo costretto a inserire tutto in 8 caratteri o meno, è decisamente meglio errare sul lato di più informazioni che meno. Man mano che acquisisci più esperienza, imparerai dove puoi risparmiare sulla lunghezza dell'identificatore e dove devi essere un po 'più descrittivo.

    
risposta data 10.04.2017 - 19:13
fonte
-1

Non sono sicuro che funzioni per c o no ma esiste un modo per dividere le formule su più righe? So che esiste qualcosa del genere per Python.

Verifica se puoi avviare + (rowSize * nextWord) + nextWord]) {su una nuova riga. (Come premi, digita il tuo IDE e controlla se lo fa rientrare in modo che C sappia che l'espressione precedente viene completata sulla riga corrente)

    
risposta data 18.03.2017 - 04:18
fonte

Leggi altre domande sui tag