Cosa c'è di sbagliato nei commenti che spiegano codice complesso?

231

Un sacco di persone sostengono che "i commenti dovrebbero spiegare" perché ", ma non" come "". Altri dicono che "il codice dovrebbe essere auto-documentante" ei commenti dovrebbero essere scarsi. Robert C. Martin afferma che (riformulato secondo le mie stesse parole) spesso "i commenti sono scuse per codice scritto male".

La mia domanda è la seguente:

Cosa c'è che non va nella spiegazione di un algoritmo complesso o di una parte di codice lunga e contorta con un commento descrittivo?

In questo modo, invece di altri sviluppatori (incluso te stesso) che devono leggere l'intero algoritmo riga per riga per capire cosa fa, possono semplicemente leggere il commento descrittivo amichevole che hai scritto in inglese semplice.

L'inglese è "progettato" per essere facilmente compreso dagli esseri umani. Java, Ruby o Perl, tuttavia, sono stati progettati per bilanciare la leggibilità umana e la leggibilità del computer, compromettendo così la leggibilità umana del testo. Un umano può capire un pezzo di inglese molto più velocemente che può capire un pezzo di codice con lo stesso significato (purché l'operazione non sia banale).

Quindi, dopo aver scritto un pezzo di codice complesso scritto in un linguaggio di programmazione parzialmente leggibile, perché non aggiungere un commento descrittivo e conciso che spieghi l'operazione del codice in inglese amichevole e comprensibile?

Alcuni diranno "il codice non dovrebbe essere difficile da capire", "crea funzioni piccole", "usa nomi descrittivi", "non scrivere codice spaghetti".

Ma sappiamo tutti che non è abbastanza. Queste sono semplici linee guida - importanti e utili - ma non cambiano il fatto che alcuni algoritmi sono complessi. E quindi sono difficili da capire quando li si legge riga per riga.

È davvero così difficile spiegare un algoritmo complesso con poche righe di commenti sulla sua operazione generale? Cosa c'è di sbagliato nello spiegare un codice complicato con un commento?

    
posta Aviv Cohn 01.09.2014 - 02:28
fonte

16 risposte

402

In parole povere:

  • C'è niente di sbagliato con i commenti di per sé.
  • Quello che non va è scrivere un codice che ha bisogno di quel tipo di commenti.
  • Ciò che è sbagliato è che si supponga che sia OK scrivere codice complicato purché lo si spieghi in modo semplice in inglese.
  • I commenti non si aggiornano automaticamente quando si modifica il codice. Ecco perché spesso i commenti dei tempi non sono sincronizzati con il codice.
  • I commenti non semplificano il test del codice.
  • Scusarsi non è male. Quello che hai fatto richiede scusa è cattivo.
  • Un programmatore che sia in grado di scrivere codice semplice per risolvere un problema complesso è meglio di uno che scrive codice complesso e quindi scrive un lungo commento che spiega cosa fa il suo codice.

Bottom line:

Spiegare te stesso è buono, non è necessario farlo è meglio.

    
risposta data 01.09.2014 - 02:52
fonte
109

Ci sono diversi motivi per cui il codice è complicato o confuso. I motivi più comuni sono meglio risolti rifattorizzando il codice per renderlo meno confuso, non aggiungendo commenti di alcun tipo.

Tuttavia, ci sono casi in cui un commento ben scelto è la scelta migliore.

  • Se è lo algoritmo stesso che è complicato e confuso, non solo la sua implementazione, il tipo che viene scritto nei diari di matematica e viene sempre chiamato Algoritmo di Mbogo, quindi hai inserito un commento proprio all'inizio dell'implementazione, leggendo qualcosa come "Questo è l'Algoritmo di Mbogo per i widget di refrobnating, originariamente descritto qui: [URL di carta]. Questa implementazione contiene i perfezionamenti di Alice e Carol [URL di un altro articolo]." Non cercare di entrare in altri dettagli; se qualcuno ha bisogno di maggiori dettagli probabilmente avrà bisogno di leggere l'intero documento.

  • Se hai preso qualcosa che può essere scritto come una o due righe in una notazione specialistica e lo espandi in un grande globo di codice imperativo, mettendo quelle o una o due righe di notazione specializzata in un commento sopra la funzione è un buon modo per dire al lettore che cosa è supposto fare. Questa è un'eccezione all'argomento "ma se il commento non sincronizza con il codice", perché la notazione specializzata è probabilmente molto più facile da trovare nel codice rispetto al codice. (È il contrario se hai scritto una specifica in inglese invece.) Un buon esempio è qui: link ...

    /**
     * Scan a unicode-range token.  These match the regular expression
     *
     *     u\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?
     *
     * However, some such tokens are "invalid".  There are three valid forms:
     *
     *     u+[0-9a-f]{x}              1 <= x <= 6
     *     u+[0-9a-f]{x}\?{y}         1 <= x+y <= 6
     *     u+[0-9a-f]{x}-[0-9a-f]{y}  1 <= x <= 6, 1 <= y <= 6
    
  • Se il codice è semplice nel complesso, ma contiene una o due cose che sembrano eccessivamente convolute, non necessarie o semplicemente errate, ma devono essere così per motivi, quindi si mette un commento immediatamente sopra il bit dall'aspetto sospetto, in cui indica i motivi . Ecco un semplice esempio, in cui l'unica cosa che deve essere spiegata è perché una costante ha un determinato valore.

    /* s1*s2 <= SIZE_MAX if s1 < K and s2 < K, where K = sqrt(SIZE_MAX+1) */
    const size_t MUL_NO_OVERFLOW = ((size_t)1) << (sizeof(size_t) * 4);
    if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
        nmemb > 0 && SIZE_MAX / nmemb < size)
      abort();
    
risposta data 01.09.2014 - 04:35
fonte
61

So what's wrong with explaining complicated code with a comment?

Non è una questione di giusto o sbagliato, ma della "migliore pratica", come definito nell'articolo di Wikipedia :

A best practice is a method or technique that has consistently shown results superior to those achieved with other means, and that is used as a benchmark.

Quindi la migliore pratica è provare prima a migliorare il codice e usare l'inglese se ciò non è possibile.

Non è una legge, ma è molto più comune trovare il codice commentato che richiede il refactoring rispetto al codice refactored che richiede commenti, la migliore pratica lo riflette.

    
risposta data 01.09.2014 - 03:25
fonte
52

Arriverà un giorno in cui il tuo codice bello, perfettamente realizzato, ben strutturato e leggibile non funzionerà. O non funzionerà abbastanza bene. Oppure sorgerà un caso particolare in cui non funziona e ha bisogno di essere aggiustato.

A quel punto, dovrai fare qualcosa che cambi le cose in modo che funzioni correttamente. Particolarmente nel caso in cui ci siano problemi di prestazioni, ma spesso anche in scenari in cui una delle librerie, API, servizi web, gemme o sistemi operativi con cui stai lavorando non si comportano come previsto, puoi finiscono per fare suggerimenti che non sono necessariamente ineleganti, ma sono contro-intuitivi o non ovvi.

Se non hai commenti per spiegare perché hai scelto quell'approccio, c'è una buona possibilità che qualcuno in futuro (e che qualcuno possa anche essere te stesso) guarderà il codice, vedi come potrebbe essere " corretto "a qualcosa di più leggibile ed elegante e annullare inavvertitamente la tua correzione, perché non sembra una soluzione.

Se tutti scrivessero sempre codice perfetto, sarebbe ovvio che il codice che sembra imperfetto sta lavorando a un intervento complicato del mondo reale, ma non è così che funzionano le cose. La maggior parte dei programmatori scrive spesso codice confuso o un po 'aggrovigliato, quindi quando lo incontriamo è una naturale inclinazione a riordinarlo. Giuro che il mio passato è un vero idiota ogni volta che leggo il vecchio codice che ho scritto.

Quindi non penso ai commenti come alle scuse per il codice errato, ma forse come spiegazione del perché non hai fatto la cosa ovvia. Avere // The standard approach doesn't work against the 64 bit version of the Frobosticate Library consentirà ai futuri sviluppatori, incluso il tuo sé futuro, di prestare attenzione a quella parte del codice e testare quella libreria. Certo, potresti anche inserire i commenti nel controllo del codice sorgente, ma le persone guarderanno solo quelli dopo che qualcosa è andato storto. Leggere i commenti del codice mentre modificano il codice.

Le persone che ci dicono che dovremmo sempre scrivere codice teoricamente perfetto non sono sempre persone con molta esperienza di programmazione in ambienti reali. A volte è necessario scrivere codice che funzioni ad un certo livello, a volte è necessario interagire con sistemi imperfetti. Ciò non significa che non puoi farlo in modi eleganti e ben scritti, ma le soluzioni non ovvie richiedono una spiegazione.

Quando scrivo codice per progetti hobbistici che so che nessun altro leggerà mai, continuo a commentare parti che trovo confuse - per esempio, qualsiasi geometria 3D implica matematica di cui non sono del tutto a suo agio - perché so quando Torno tra sei mesi, avrò completamente dimenticato come fare questa roba. Questa non è una scusa per il codice sbagliato, è un riconoscimento di una limitazione personale. Tutto ciò che farei lasciandolo senza parole è creare più lavoro per me stesso in futuro. Non voglio che il mio sé futuro debba imparare di nuovo qualcosa di inutilmente se posso evitarlo adesso. Quale valore possibile avrebbe?

    
risposta data 01.09.2014 - 12:47
fonte
29

La necessità di commenti è inversamente proporzionale al livello di astrazione del codice.

Ad esempio, il linguaggio assembly è, per la maggior parte degli scopi pratici, inintelligibile senza commenti. Ecco un estratto da un piccolo programma che calcola e stampa i termini della serie di Fibonacci :

main:   
; initializes the two numbers and the counter.  Note that this assumes
; that the counter and num1 and num2 areas are contiguous!
;
    mov ax,'00'                     ; initialize to all ASCII zeroes
    mov di,counter                  ; including the counter
    mov cx,digits+cntDigits/2       ; two bytes at a time
    cld                             ; initialize from low to high memory
    rep stosw                       ; write the data
    inc ax                          ; make sure ASCII zero is in al
    mov [num1 + digits - 1],al      ; last digit is one
    mov [num2 + digits - 1],al      ; 
    mov [counter + cntDigits - 1],al

    jmp .bottom         ; done with initialization, so begin

.top
    ; add num1 to num2
    mov di,num1+digits-1
    mov si,num2+digits-1
    mov cx,digits       ; 
    call    AddNumbers  ; num2 += num1
    mov bp,num2         ;
    call    PrintLine   ;
    dec dword [term]    ; decrement loop counter
    jz  .done           ;

    ; add num2 to num1
    mov di,num2+digits-1
    mov si,num1+digits-1
    mov cx,digits       ;
    call    AddNumbers  ; num1 += num2
.bottom
    mov bp,num1         ;
    call    PrintLine   ;
    dec dword [term]    ; decrement loop counter
    jnz .top            ;
.done
    call    CRLF        ; finish off with CRLF
    mov ax,4c00h        ; terminate
    int 21h             ;

Anche con i commenti, può essere piuttosto complicato da digerire.

Esempio moderno: i regex sono spesso costrutti di astrazione molto bassi (lettere minuscole, numero 0, 1, 2, nuove linee, ecc.). Probabilmente hanno bisogno di commenti sotto forma di campioni (Bob Martin, IIRC, lo riconosce). Ecco una espressione regolare che (penso) dovrebbe corrispondere agli URL HTTP (S) e FTP:

^(((ht|f)tp(s?))\://)?(www.|[a-zA-Z].)[a-zA-Z0-9\-\.]+\.(com|edu|gov|m
+il|net|org|biz|info|name|museum|us|ca|uk)(\:[0-9]+)*(/($|[a-zA-Z0-9\.
+\,\;\?\'\\+&amp;%\$#\=~_\-]+))*$

Mentre le lingue avanzano nella gerarchia di astrazione, il programmatore è in grado di utilizzare astrazioni evocative (nome di variabili, nomi di funzioni, nomi di classi, nomi di moduli, interfacce, callback, ecc.) per fornire documentazione integrata. Trascurare di approfittare di questo, e usare commenti su di esso è pigro, un disservizio e irrispettoso del manutentore.

Penso a Ricette numeriche in C tradotte per lo più letteralmente in Ricette numeriche in C ++ , che deduco iniziato come Ricette numeriche (in FORTAN), con tutte le variabili a , aa , b , c , cc , ecc. Mantenute tramite ogni versione. Gli algoritmi potrebbero essere stati corretti, ma non hanno sfruttato le astrazioni fornite dalle lingue. E mi hanno fregato. Esempio di articolo di Dr. Dobbs - Trasformazione di Fourier veloce :

void four1(double* data, unsigned long nn)
{
    unsigned long n, mmax, m, j, istep, i;
    double wtemp, wr, wpr, wpi, wi, theta;
    double tempr, tempi;

    // reverse-binary reindexing
    n = nn<<1;
    j=1;
    for (i=1; i<n; i+=2) {
        if (j>i) {
            swap(data[j-1], data[i-1]);
            swap(data[j], data[i]);
        }
        m = nn;
        while (m>=2 && j>m) {
            j -= m;
            m >>= 1;
        }
        j += m;
    };

    // here begins the Danielson-Lanczos section
    mmax=2;
    while (n>mmax) {
        istep = mmax<<1;
        theta = -(2*M_PI/mmax);
        wtemp = sin(0.5*theta);
        wpr = -2.0*wtemp*wtemp;
        wpi = sin(theta);
        wr = 1.0;
        wi = 0.0;
        for (m=1; m < mmax; m += 2) {
            for (i=m; i <= n; i += istep) {
                j=i+mmax;
                tempr = wr*data[j-1] - wi*data[j];
                tempi = wr * data[j] + wi*data[j-1];

                data[j-1] = data[i-1] - tempr;
                data[j] = data[i] - tempi;
                data[i-1] += tempr;
                data[i] += tempi;
            }
            wtemp=wr;
            wr += wr*wpr - wi*wpi;
            wi += wi*wpr + wtemp*wpi;
        }
        mmax=istep;
    }
}

Come caso speciale sull'astrazione, ogni lingua ha idiomi / snippet di codice canonico per alcune attività comuni (eliminazione di un elenco dinamico collegato in C), e indipendentemente da come appaiono, non dovrebbero essere documentati. I programmatori dovrebbero imparare questi idiomi, in quanto sono ufficiosamente parte della lingua.

Quindi il take away: il codice non idiomatico creato da blocchi di basso livello che non possono essere evitati richiede commenti. E questo è necessario WAAAAY meno di quanto accada.

    
risposta data 02.09.2014 - 17:42
fonte
19

Non credo che ci sia qualcosa di sbagliato nei commenti nel codice. L'idea che i commenti siano in qualche modo cattivi secondo me è dovuta ad alcuni programmatori che prendono le cose troppo lontano. C'è un sacco di giri di vite in questo settore, in particolare verso le vedute estreme. Da qualche parte lungo il modo in cui il codice commentato è diventato equivalente al codice cattivo e non sono sicuro del perché.

I commenti hanno problemi: è necessario tenerli aggiornati man mano che si aggiorna il codice a cui si riferiscono, cosa che accade troppo raramente. Un wiki o qualcosa è una risorsa più appropriata per una documentazione approfondita sul tuo codice. Il tuo codice dovrebbe essere leggibile senza richiedere commenti. Il controllo della versione o le note di revisione dovrebbero essere dove descrivi le modifiche al codice che hai apportato.

Tuttavia, nessuna delle precedenti invalide l'uso dei commenti. Non viviamo in un mondo ideale, quindi quando uno qualsiasi dei precedenti fallisce per qualsiasi motivo, preferisco avere alcuni commenti da ripiegare.

    
risposta data 01.09.2014 - 16:10
fonte
18

Penso che tu stia leggendo un po 'troppo a ciò che sta dicendo. Ci sono due parti distinte del tuo reclamo:

What's wrong with explaining (1) a complex algorithm or (2) a long and convoluted piece of code with a descriptive comment?

(1) è inevitabile. Non penso che Martin sarebbe in disaccordo con te. Se stai scrivendo qualcosa come la radice quadrata inversa rapida , hai bisogno di alcuni commenti, anche se è solo "hacking a livello di bit in virgola mobile". Escludendo qualcosa di semplice come una ricerca DFS o binaria, è improbabile che la persona che legge il codice abbia esperienza con quell'algoritmo, e quindi penso che ci dovrebbe essere almeno una menzione nei commenti su ciò che è.

La maggior parte del codice non è (1), tuttavia. Raramente scriverete un pezzo di software che è nient'altro che implementazioni mutex eseguite a mano, oscure operazioni di algebra lineare con scarso supporto di libreria e nuovi algoritmi noti solo al gruppo di ricerca della vostra azienda. La maggior parte del codice consiste in chiamate di librerie / framework / API, IO, boilerplate e unit test.

Questo è il tipo di codice di cui Martin sta parlando. E affronta la tua domanda con la citazione di Kernighan e Plaugher nella parte superiore del capitolo:

Don’t comment bad code—rewrite it.

Se hai sezioni lunghe e contorte nel codice, hai fallito nel mantenere il tuo codice pulito . La migliore soluzione a questo problema è non scrivere un commento lungo un paragrafo nella parte superiore del file per aiutare i futuri sviluppatori a cavarsela; la soluzione migliore è riscriverlo.

E questo è esattamente ciò che dice Martin:

The proper use of comments is to compensate for our failure to express ourself in code...Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them, but their use is not a cause for celebration.

Questo è il tuo (2). Martin concorda sul fatto che un codice lungo e contorto ha bisogno di commenti, ma attribuisce la responsabilità di quel codice alle spalle del programmatore che lo ha scritto, non una qualche nebulosa idea che "sappiamo tutti che non è abbastanza". Sostiene che:

Clear and expressive code with few comments is far superior to cluttered and complex code with lots of comments. Rather than spend your time writing the comments that explain the mess you’ve made, spend it cleaning that mess.

    
risposta data 01.09.2014 - 04:53
fonte
8

What's wrong with explaining a complex algorithm or a long and convoluted piece of code with a descriptive comment?

Nulla in quanto tale. Documentare il tuo lavoro è una buona pratica.

Detto questo, hai una falsa dicotomia qui: scrivere codice pulito e scrivere codice documentato - i due non sono in opposizione.

Ciò su cui dovresti concentrarti è semplificare e astrarre codice complesso in codice più semplice, invece di pensare che "il codice complesso va bene fintanto che viene commentato".

Idealmente, il tuo codice dovrebbe essere semplice e documentato.

This way, instead of other developers (including yourself) having to read the entire algorithm line by line to figure out what it does, they can just read the friendly descriptive comment you wrote in plain English.

È vero. Questo è il motivo per cui tutti i tuoi algoritmi API pubblici dovrebbero essere spiegati nella documentazione.

So after writing a complex piece of code written in a partly human-readable programming language, why not add a descriptive and concise comment explaining the operation of the code in friendly and understandable English?

Idealmente, dopo aver scritto una parte di codice complessa dovresti (non un elenco esaustivo):

  • considera una bozza (ovvero pianifica di riscriverla)
  • formalizzare i punti di ingresso dell'algoritmo / interfacce / ruoli / etc (analizzare e ottimizzare l'interfaccia, formalizzare le astrazioni, precondizioni di documenti, postcondizioni ed effetti collaterali e casi di errore del documento).
  • scrivi test
  • pulizia e refactoring

Nessuno di questi passaggi è banale da fare (ad esempio ognuno può richiedere alcune ore) e i premi per eseguirli non sono immediati. In quanto tali, questi passaggi sono (quasi) sempre compromessi (dagli sviluppatori che tagliano gli angoli, i manager che tagliano gli angoli, le scadenze, i vincoli di mercato / altre condizioni del mondo reale, la mancanza di esperienza, ecc.)

[...] some algorithms are complex. And therefore are hard to understand when reading them line by line.

Non dovresti mai fare affidamento sulla lettura dell'implementazione per capire cosa fa un'API. Quando lo fai, stai implementando il codice client basato sull'implementazione (invece dell'interfaccia) e questo significa che il tuo accoppiamento di moduli è già sparato all'inferno, stai potenzialmente introducendo dipendenze non documentate con ogni nuova linea di codice che scrivi e stai già aggiungendo il debito tecnico.

Is it really that bad to explain a complex algorithm with a few lines of comments about it's general operation?

No - è buono. Tuttavia, aggiungere poche righe di commenti non è sufficiente.

What's wrong with explaining complicated code with a comment?

Il fatto che non dovresti avere un codice complicato, se è possibile evitarlo.

Per evitare codice complicato, formalizzare le interfacce, spendere circa 8 volte di più nella progettazione dell'API di quanto spendi per l'implementazione (Stepanov ha suggerito di spendere almeno 10 volte l'interfaccia, rispetto all'implementazione) e iniziare a sviluppare un progetto con la consapevolezza che stai creando un progetto, non solo scrivendo un algoritmo.

Un progetto riguarda la documentazione API, la documentazione funzionale, le misurazioni di codice / qualità, la gestione dei progetti e così via. Nessuno di questi processi è una tantum, passi veloci da compiere (tutti richiedono tempo, richiedono lungimiranza e pianificazione, e tutti richiedono che tu torni periodicamente da loro e li riveda / completi con i dettagli).

    
risposta data 01.09.2014 - 14:33
fonte
6

instead of other developers (including yourself) having to read the entire algorithm line by line to figure out what it does, they can just read the friendly descriptive comment you wrote in plain English.

Considererei questo un leggero abuso di "commenti". Se il programmatore vuole leggere qualcosa invece di l'intero algoritmo, allora è a questo che serve la documentazione della funzione. OK, quindi la documentazione della funzione potrebbe effettivamente apparire nei commenti nel sorgente (forse per l'estrazione da strumenti doc), ma sebbene sintatticamente si tratti di un commento per quanto riguarda il compilatore, dovresti considerarli separatamente con scopi separati. Non credo che "i commenti dovrebbero essere scarsi" è necessariamente inteso come "la documentazione dovrebbe essere scarsa" o anche "le note sul copyright dovrebbero essere scarse"!

I commenti nella funzione permettono a qualcuno di leggere così come il codice. Pertanto, se nel codice sono presenti poche righe di difficile comprensione e non è possibile renderle di facile comprensione, un commento è utile per il lettore da utilizzare come segnaposto per tali righe. Questo potrebbe essere molto utile mentre il lettore sta solo cercando di ottenere l'essenza generale, ma ci sono un paio di problemi:

  • I commenti non sono necessariamente veri, mentre il codice fa quello che fa. Quindi il lettore ti sta prendendo la parola e questo non è l'ideale.
  • Il lettore non ha ancora capito il codice stesso, quindi fino a quando non ci tornano in seguito non sono ancora qualificati per modificarlo o riutilizzarlo. In tal caso, cosa stanno leggendo?

Ci sono delle eccezioni, ma la maggior parte dei lettori dovrà capire il codice stesso. I commenti dovrebbero essere scritti per aiutare questo, non per sostituirlo, motivo per cui generalmente si consiglia ai commenti di dire "perché lo stai facendo". Un lettore che conosce la motivazione per le prossime righe di codice ha una migliore possibilità di vedere cosa fanno e come.

    
risposta data 01.09.2014 - 10:41
fonte
5

Spesso dobbiamo fare cose complicate. È certamente giusto documentarli per una futura comprensione. A volte il posto giusto per questa documentazione è nel codice, dove la documentazione può essere aggiornata con il codice. Ma vale sicuramente la pena considerare una documentazione separata. Questo può anche essere più facile da presentare ad altre persone, inclusi diagrammi, immagini a colori e così via. Quindi il commento è solo:

// This code implements the algorithm described in requirements document 239.

o anche solo

void doPRD239Algorithm() { ...

Certamente le persone sono felici con le funzioni denominate MatchStringKnuthMorrisPratt o encryptAES o partitionBSP . Altri nomi oscuri valgono la pena di essere spiegati in un commento. Puoi anche aggiungere dati bibliografici e un link a un documento da cui hai implementato un algoritmo.

Se un algoritmo è complesso e innovativo e non ovvio, vale sicuramente la pena di essere un documento, anche se solo per la circolazione interna dell'azienda. Controlla il documento nel controllo del codice sorgente se sei preoccupato che si perda.

C'è un'altra categoria di codice che non è tanto algoritmica quanto burocratica. Devi impostare i parametri per un altro sistema o interagire con i bug di qualcun altro:

/* Configure the beam controller and turn on the laser.
The sequence is timing-critical and this code must run with interrupts disabled.
Note that the constant 0xef45ab87 differs from the vendor documentation; the vendor
is wrong in this case.
Some of these operations write the same value multiple times. Do not attempt
to optimise this code by removing seemingly redundant operations.
*/
    
risposta data 01.09.2014 - 16:50
fonte
5

Ho dimenticato dove lo leggo, ma è una linea netta e chiara tra ciò che dovrebbe apparire nel tuo codice e ciò che dovrebbe apparire come un commento.

Credo che dovresti commentare le tue intenzioni, non il tuo algoritmo . Cioè commenta cosa intendevi fare, non su ciò che fai .

Ad esempio:

// The getter.
public <V> V get(final K key, Class<V> type) {
  // Has it run yet?
  Future<Object> f = multitons.get(key);
  if (f == null) {
    // No! Make the task that runs it.
    FutureTask<Object> ft = new FutureTask<Object>(
            new Callable() {

              public Object call() throws Exception {
                // Only do the create when called to do so.
                return key.create();
              }

            });
    // Only put if not there.
    f = multitons.putIfAbsent(key, ft);
    if (f == null) {
      // We replaced null so we successfully put. We were first!
      f = ft;
      // Initiate the task.
      ft.run();
    }
  }
  try {
    /**
     * If code gets here and hangs due to f.status = 0 (FutureTask.NEW)
     * then you are trying to get from your Multiton in your creator.
     *
     * Cannot check for that without unnecessarily complex code.
     *
     * Perhaps could use get with timeout.
     */
    // Cast here to force the right type.
    return (V) f.get();
  } catch (Exception ex) {
    // Hide exceptions without discarding them.
    throw Throwables.asRuntimeException(ex);
  }
}

Qui non vi è alcun tentativo di indicare cosa esegue ogni fase, tutto ciò che afferma è ciò che è supposto fare.

PS: ho trovato la fonte a cui mi riferivo - Coding Horror: Il codice ti dice come, i commenti ti dicono perché

    
risposta data 01.09.2014 - 13:06
fonte
4

But we all know that's not enough.

Davvero? Da quando?

Il codice ben progettato con buoni nomi è più che sufficiente nella stragrande maggioranza dei casi. Gli argomenti contro l'uso di commenti sono ben noti e documentati (come si fa riferimento a).

Ma queste sono linee guida (come qualsiasi altra cosa). Nel raro caso (nella mia esperienza, circa una volta ogni 2 anni) in cui le cose sarebbero peggiori quando refactored in funzioni più leggibili (a causa di esigenze di performance o coesione) quindi andare avanti - inserire un lungo commento che spiega qual è la cosa in realtà fare (e perché stai violando le migliori pratiche).

    
risposta data 01.09.2014 - 02:57
fonte
2

Lo scopo principale del codice è comandare a un computer di fare qualcosa, quindi un buon commento non è mai un sostituto del buon codice perché i commenti non possono essere eseguiti.

Detto questo, i commenti nella fonte sono una forma di documentazione per altri programmatori (incluso te stesso). Se i commenti riguardano problemi più astratti di quello che il codice sta facendo ad ogni passo, stai facendo meglio della media. Quel livello di astrazione varia con lo strumento che stai usando. I commenti che accompagnano le routine di linguaggio assembly hanno generalmente un livello inferiore di "astrazione" rispetto, ad esempio, a questo APL A←0⋄A⊣{2⊤⍵:1+3×⍵⋄⍵÷2}⍣{⍺=A+←1}⎕ . Penso che probabilmente meriterebbe un commento sul problema che intende risolvere, hmmm?

    
risposta data 01.09.2014 - 04:12
fonte
2

Se il codice è banale, non ha bisogno di un commento esplicativo. Se il codice non è banale, molto probabilmente il commento esplicativo sarà non banale.

Ora, il problema con il linguaggio naturale non banale è che molti di noi non sono molto bravi a leggerlo oa scriverlo. Sono sicuro che le tue abilità comunicative scritte sono eccellenti, ma ciononostante qualcuno con una minore conoscenza della lingua scritta potrebbe fraintendere le tue parole.

Se ti sforzi molto a scrivere in un linguaggio naturale che non può essere interpretato in modo errato, ti ritroverai con qualcosa di simile a un documento legale (e come sappiamo tutti sono più prolissi e difficili da capire del codice).

Il codice dovrebbe essere la descrizione più concisa della tua logica e non dovrebbe esserci molto dibattito sul significato del tuo codice perché il tuo compilatore e la piattaforma hanno l'ultima parola.

Personalmente non direi che non dovresti mai scrivere un commento. Solo che dovresti considerare il motivo per cui il tuo codice ha bisogno di un commento e come potresti correggerlo. Questo sembra essere un tema comune nelle risposte qui.

    
risposta data 01.09.2014 - 15:00
fonte
0

Un punto non ancora menzionato è che a volte si commenta con precisione cosa può fare un pezzo di codice nei casi in cui una lingua usa una sintassi particolare per molteplici scopi. Ad esempio, supponendo che tutte le variabili siano di tipo float , prendere in considerazione:

f1 = (float)(f2+f3); // Force result to be rounded to single precision
f4 = f1-f2;

L'effetto di un casting esplicito di float in float consiste nel forzare il risultato a arrotondare alla precisione singola; il commento potrebbe quindi essere visto come semplicemente dicendo cosa fa il codice. D'altra parte, confronta quel codice con:

thing.someFloatProperty = (float)(f2*0.1); // Divide by ten

Qui lo scopo del cast è impedire al compilatore di schiamazzare nel modo più efficiente di calcolare accuratamente (f2 / 10) [è più preciso di moltiplicarlo per 0.1f, e sulla maggior parte delle macchine è più veloce della divisione per 10.0 f].

Senza il commento, qualcuno che stava rivedendo il codice precedente potrebbe pensare che il cast sia stato aggiunto in una errata convinzione che sarebbe stato necessario per impedire al compilatore di schiamazzare e che non era necessario. Infatti, il cast ha lo scopo di fare esattamente quello che le specifiche del linguaggio dicono che fa: forza il risultato del calcolo per essere arrotondato a precisione singola anche su macchine dove l'arrotondamento sarebbe più costoso di mantenere il risultato in una precisione maggiore. Dato che un cast su float può avere un numero di significati e scopi diversi, avere un commento specifica quale significato è inteso in uno scenario particolare può aiutare a chiarire che il significato reale si allinea con l'intento.

    
risposta data 01.09.2014 - 17:35
fonte
-1

Commenti che spiegano che cosa fa il codice sono una forma di duplicazione. Se si modifica il codice e quindi si dimentica di aggiornare i commenti, ciò può causare confusione. Non sto dicendo di non usarli, basta usarli con giudizio. Mi iscrivo alla massima di Zio Bob: "Commenta solo ciò che il codice non può dire".

    
risposta data 07.02.2015 - 13:36
fonte

Leggi altre domande sui tag