Come documentare il mio codice per la revisione del tempo minimo? [chiuso]


22

Voglio documentare il mio codice in modo tale che sia necessario leggere e sfogliare nuovamente il codice mesi dopo.

So che esistono diversi tipi di documentazione (nel codice sorgente e all'esterno, nei diagrammi di sequenza e così via).

Voglio solo sapere qual è un modo efficace per documentare il mio codice in modo che, quando pochi mesi dopo voglio vedere il mio codice, trascorro meno tempo a leggere il codice e comprenderne il flusso.


42
Il metodo migliore per passare meno tempo a leggere il codice in un secondo momento è scrivere codice più chiaro e comprensibile .
Mael


La documentazione dipende dall'obiettivo. Se ti rivolgi agli sviluppatori, i commenti nel codice possono essere molto utili. Se ti rivolgi agli analisti, anche i diagrammi della panoramica sono utili. Se ti rivolgi a un pubblico esperto di tecnologia, crea una guida per l'utente.
Laiv

@Laiv Bene in vista di uno sviluppatore del mio codice e forse del codice di altri sviluppatori.
Hamed_gibago

La cosa più importante è mantenere il codice piccolo. Se il codice necessario per implementare un articolo nel tuo sistema di localizzazione dei problemi è grande, il tuo team potrebbe aver bisogno di imparare come suddividerlo un po 'di più in modo che la quantità di codice esaminata non sia schiacciante.
Berin Loritsch l'

Risposte:


16

Devo ammettere di non essere d'accordo con alcune delle cose raccomandate dalle altre risposte, quindi lancerò i miei due centesimi;

Commenti

La documentazione è estremamente utile per gli estranei che leggono il tuo codice. Di solito molte cose non saranno abbastanza dettagliate per essere lette e comprese immediatamente, quindi dovresti spiegare cosa stai facendo.

Modifica : la discussione nella sezione dei commenti ha sottolineato qualcosa di giusto: i commenti eccessivi di solito vengono fatti quando si scrive codice errato .

Commentare il tuo lavoro dovrebbe essere preciso e minimale, ma, secondo me, dovrebbe assolutamente essere presente. Almeno un commento per ogni 15 righe di codice. Ad esempio, sopra i blocchi sul codice, aggiungi una riga su ciò che stai facendo:

def login(username: str, password: str, create_session: bool = True):

    # Filter the user we need from the database
    hash = md5(password)
    users = db.table("users", db_entities.USER)
    results = [x for x in users.query(lambda c: c.get("username") == username and c.get("password_hash") == hash)]


    if len(results) == 0:
        return None, None
    else:
        # Create a login session record in the database.
        if create_session:
            sessions = db.table("sessions", db_entities.SESSION)
            ses = sessions.new()
            ses.set("username", username) \
                .set("expiery", 31536000 + time.time())
            sessions.update(ses)
            return results[0], ses
        else:
            return results[0], None

I commenti minimi che spiegano perché e cosa stai facendo sono molto utili in tutto il codice. Non sono d'accordo con la risposta che afferma

Se mi imbatto in un codice contenente commenti, mi preparo al peggio: è probabile che il codice sia errato e, ad essere sincero, anche i commenti saranno probabilmente cattivi.

Molte volte, con garbo, è documentato un buon codice. È vero che i cattivi programmatori vedono la loro documentazione come "Va bene, il mio codice è cattivo, aggiungiamo alcune frasi per renderlo più chiaro".

Sì, e sebbene ciò si verifichi abbastanza, è anche vero che i bravi programmatori che scrivono codice pulito vogliono anche assicurarsi di tornare al loro codice e capire perché vogliono che la loro funzione si comporti in questo modo, o perché ne hanno bisogno linea che sembra un po 'ridondante, ecc ...

Sì, i commenti che spiegano cose ovvie, i commenti che non sono chiari, i commenti che sono stati messi insieme per assicurarsi che "questo codice sia documentato, sì, qualunque cosa", sono odori di codice. Rendono la lettura del codice più difficile e irritante. (Aggiunta di un esempio di seguito)

# Logging into Gmail when the module is imported
_client = login()
def get_client():
    global _client
    return _client

Chiarimento di esempio: "Nessuna merda, Sherlock. _client = login()Accede al servizio di posta? OMG!"

Ulteriori chiarimenti: il login()metodo non ha alcuna relazione con il login()metodo dell'esempio precedente.

Ma i commenti che corrispondono agli standard, spiegano il perché e non il come e rispondono alle domande giuste , sono molto ( molto ) utili.

Commenti incorporati

Una cosa che NON dovresti fare (e se potessi scriverlo più in grande, lo farei) è scrivere i tuoi commenti nella stessa riga del codice. Rende i commenti molto specifici per la riga, il che manca completamente allo scopo di commentare il tuo codice.

Ad esempio, commenti incorporati non validi:

outer = MIMEText(details["message"]) # Constructing a new MIMEText object
outer["To"] = details["to"] # Setting message recipient
outer["From"] = "xAI No-Reply" # Setting message sender
outer["Subject"] = details["subject"] # Setting message subject
outer.preamble = "You will not see this in a MIME-aware mail reader.\n" # I don't know what I'm doing here, I copied this from SO.
msg = outer.as_string() # Getting the string of the message
_client = details["client"] # Assigning the client
_client.sendmail(SENDER, details["to"], msg) # Sending the mail

Sarebbe molto più facile leggere e comprendere questo codice senza i commenti, che lo rendono disordinato e illeggibile.

Invece, i commenti all'interno del codice devono essere posizionati sopra i blocchi del codice e dovrebbero rispondere alle domande importanti che possono sorgere durante la lettura del blocco di codice.

# Constructing the email object with the values 
# we received from the parameter of send_mail(details)
outer = MIMEText(details["message"])
outer["To"] = details["to"]
outer["From"] = "xAI No-Reply"
outer["Subject"] = details["subject"]
outer.preamble = "You will not see this in a MIME-aware mail reader.\n"
msg = outer.as_string()

# Sending the mail using the global client (obtained using login())
_client = details["client"]
_client.sendmail(SENDER, details["to"], msg)

Molto più chiaro, vero? Ora sai anche che devi usare la login()funzione e fornire i parametri a send_mail()tutto ciò che hai usato. Aiuta un po ', ma manca ancora una cosa.

Documentazione delle funzioni

È stato ampiamente discusso. Dovresti sempre far sapere ai tuoi lettori di cosa tratta la tua funzione, perché e cosa fa. In che modo ciò non appartiene alla documentazione, ma forse alle note a piè di pagina della funzione.

Dovresti descrivere chiaramente quali sono i tuoi parametri e se desideri che siano ottenuti / creati in un metodo specifico. Dovresti dichiarare quale dovrebbe essere la tua funzione, a che serve, ecc.

Ancora una volta, questa è la mia opinione e metodologia durante la scrittura del mio codice. Non solo quelli, ma quelli sono solo alcune delle cose su cui non potrei essere d'accordo con le altre risposte. Oh, e ovviamente, non solo i commenti leggono il tuo codice, ma il tuo codice stesso. Scrivi codice pulito, comprensibile e gestibile . Pensa al tuo futuro io mentre scrivi il codice ;-)


5
Non sono d'accordo con un dato esempio: invece di scrivere molti commenti in un'unica enorme funzione, dovresti comporlo da molte funzioni più piccole con nomi descrittivi, che fungeranno da commenti. Senza il rischio di non essere sincronizzato con ciò che il codice sta realmente facendo.
user11153

6
Finalmente un po 'di sanità mentale. L'estrazione di ogni parte di codice che potrebbe utilizzare un commento nella propria funzione è il modo in cui finisci con migliaia di funzioni distribuite su centinaia di file.
user369450

2
Questo secondo esempio è adorabile.
Lightness Races con Monica

7
I commenti nel secondo esempio sono troppo dettagliati. Alcuni di essi (ad es. "Abbiamo trovato qualcosa?") Ripetono semplicemente ciò che dice il codice e sarebbe meglio rimuoverli. Per altri, potresti ottenere maggiore leggibilità tramite il refactoring, come rendere (stream.is_empty ()) la condizione del loop o spostare il check per accept_literals all'esterno.
Frax

3
@cpburnz, "Ho dovuto scavare troppi progetti legacy e librerie di terze parti senza commenti in codice per apprezzare i commenti che spiegano cosa sta succedendo e perché". esattamente il mio punto da sempre: i commenti sono lì per spiegare il codice di merda. Poiché la domanda è "come faccio a scrivere codice così facile da leggere", allora chiaramente questa risposta è sbagliata poiché si concentra sulla scrittura di commenti per spiegare il codice errato, piuttosto che scrivere un buon codice in primo luogo.
David Arno,

55

IMO la migliore documentazione è la documentazione che in realtà non è necessaria. Odio anche scrivere documentazione e commenti.

Detto questo:

  • Scegli nomi leggibili e parlanti. Non usare n, ma invece numberOfItemsFoundper esempio.
  • Non rifuggire dalla memorizzazione di parti di un calcolo in una variabile costante piuttosto che spingere tutto in una riga.
  • Sposta le attività parziali dai rami nelle loro funzioni (in linea), se le stai riutilizzando o la funzione genitore diventa lunga e noiosa da seguire.
  • Sii più elaborato e ottimizza il codice sulla leggibilità solo dove è veramente richiesto.

19
Ecco una buona metrica per la documentazione (link obbligatorio).
Neil

4
Questo dovrebbe essere anche nell'elenco: spiega nel codice perché stai facendo le cose che stai facendo.
t3chb0t


4
numberOfItemsFoundè abbastanza prolisso però; troppo prolisso è anche un problema.
Matthieu M.

6
@MatthieuM., Raramente è un problema "troppo dettagliato" con i nomi nel codice. Troppo conciso o criptico è un problema molto comune.
David Arno,

25

Tratta il tuo codice come documentazione

Il tuo codice è la tua documentazione principale. Descrive esattamente cosa fa effettivamente l'app risultante, la libreria o qualsiasi altra cosa. Pertanto, qualsiasi tentativo di accelerare la comprensione di quel codice deve iniziare con il codice stesso.

C'è molto scritto su come scrivere codice leggibile, ma alcuni dei punti chiave sono:

  • non fare affidamento sui commenti per spiegare il codice errato, migliorare il codice e sbarazzarsi dei commenti,
  • scrivere brevi funzioni focalizzate, metodi, classi ecc.
  • utilizzare nomi appropriati al contesto (ad es. nè utile per un ciclo, sono necessari nomi descrittivi più lunghi per gli elementi con ambito maggiore),
  • tratta i nomi delle funzioni come se fossero commenti, ad es. non utilizzarli UpdtTblcon un commento che spiega che aggiorna la tabella con le regole fornite quando UpdateTableContentsWithSuppliedRulespossono essere usati come nome,
  • evitare la mutabilità. Ogni volta che modifichi il contenuto di una variabile, aumenti la complessità del codice. Assegna quel nuovo valore a una nuova variabile (con un buon nome) ove possibile.
  • infine, e soprattutto, evitare il codice "intelligente". L'unico vero codice intelligente è il codice che è facile da leggere. Se scrivi un po 'di codice complesso e ti ritrovi a pensare "wow, non sono intelligente qui?", La risposta è quasi garantita per essere "no, non lo sei".

Migliora la lettura del codice

Leggere il codice, indipendentemente da quanto sia semplice, è un'abilità appresa. Nessuno è naturalmente bravo a leggere il codice. Ci vuole pratica; molta pratica. Quindi, per esempio, vai su Github o qualsiasi altra cosa e leggi il codice delle librerie che usi, piuttosto che semplicemente usare quelle librerie. Trova il codice per leggerlo e leggerlo.

I commenti sono un odore di codice

Solo allora arriviamo ad altri tipi di documentazione. In primo luogo, come precedentemente affermato, evitare commenti. Se mi imbatto in un codice contenente commenti, mi preparo al peggio: è probabile che il codice sia errato e, ad essere sincero, anche i commenti saranno probabilmente cattivi. È improbabile che qualcuno che non riesca a comunicare bene attraverso il codice sia in grado di comunicare meglio attraverso il linguaggio naturale.

Fai attenzione alla documentazione API generata automaticamente

Inoltre, fai attenzione alla documentazione API generata automaticamente. Se dovrò ricorrere alla lettura di tali documenti, sarà perché il tuo codice è così difficile da leggere. Ancora una volta, semplifica il codice e posso leggerlo direttamente.

Anche i test sono documenti

Anche i test sono documentazione. Quindi non trattare i test unitari come un lavoro di routine. Considerali come un modo di comunicare con gli altri (il tuo io successivo di sei mesi viene incluso qui) su come il codice funziona e deve essere usato.

Disegna immagini se aiuta

Se ti piace UML, allora trovi sicuramente un buon strumento e genera diagrammi UML dal tuo codice. Mai e poi mai e poi mai mai provare a usarlo per generare codice. Non è buono come strumento di progettazione e di conseguenza otterrai un codice orribile.

Avere un documento di visualizzazione "1000ft"

Infine, scriviti un documento di sintesi. Cosa fa l'app? Come lo fa? A quali altri sistemi si connette? Cose del genere. Non tentare di descrivere qui la struttura del codice. Lascia che il codice lo faccia. Lascia che questo documento ti ricordi perché hai scritto il codice in primo luogo.


14
Sono d'accordo con tutto il tuo punto, tranne per il fatto che i commenti hanno il loro posto. Anche se concordo sul fatto che non ha senso utilizzare commenti come add 1 to i, i commenti dovrebbero spiegare perché il codice fa quello che fa. Ad esempio, il codice if (!something.Exists()) {...}può utilizzare un commento del tipo: // something exists only when (explanation of the broader scenario).
Jonathan

16
Abbiamo visto tutti la nostra giusta dose di // increment x x++;commenti inutili, ma è sbagliato buttare via il bambino con l'acqua del bagno e dichiarare che i commenti sono sempre cattivi. Ad esempio, i commenti del modulo // this case should never happen because xyz throw exception "unreachable".
angrydust

7
Elenco molto bello. Ma come @Jonathan. Non sono d'accordo con i commenti. Alcune volte è necessario tenere conto dei bug in un framework di terze parti. Mentre questo può essere refactored nella sua stessa funzione, è comunque bello lasciare un po 'di descrizione del motivo per cui è richiesta la soluzione alternativa (bugnumber o bugname / descrizione del bug).
magu_

16
@DavidArno Ma non puoi farlo per un commento che spiega perché qualcosa non è stato fatto. Come //XXX: Not using straight-forward method Foo here because .... Tali commenti possono essere immensamente preziosi, ma sono impossibili da trasmettere con il codice per ovvie ragioni.
cmaster

7
Mi piace ancora di più: ogni commento è un fallimento nel esprimerti bene nel codice . Ad esempio, ho un commento a 4 righe in un metodo, che spiega la soluzione alternativa per un bug di terze parti. Non sono riuscito a esprimerlo bene nel codice, quindi è in un commento . Direi che ha migliorato la leggibilità, perché dubito che a chiunque piacerebbe scorrere in orizzontale per leggere un nome di metodo molto lungo e molto descrittivo. "I commenti sono un odore di codice" - sì, ma dobbiamo ricordare che non tutto ciò che odora è sh * t.
R. Schmitz,

5

Fornire una lettera di accompagnamento

A meno che tu non sia in un dominio molto tecnico, la maggior parte delle domande sul codice non riguarderanno il "come" ma il "perché" o il "cosa".

Pertanto, il modo per impedire alle persone di consultare il codice è quello di scriverne una breve descrizione. Il vantaggio di questo è che puoi compilare una panoramica delle descrizioni abbastanza facilmente e che questo è molto più accessibile. (Anche alle persone che non vedranno / non potranno vedere il codice).

Anche se le persone sono tecniche, la lettera di accompagnamento dovrebbe offrire una guida su dove dovrebbero cercare qualcosa.

Semplici punti estremamente minimalisti:

  1. Introduzione, perché esiste questo codice (base)
  2. Quale funzione svolge il sottoinsieme di codice
  3. Dov'è il codice (nome dello script per esempio)

Esempio

  1. Questo set di script racchiude StackOverflow e vota le risposte di Dennis Jaheruddin
  2. un. Questo script è responsabile dell'analisi dell'html e analizza se è l'utente giusto
  3. un. Lo script si trova su: ScrapeAndVote / RecognizeDennis.scr

1

Il maggior guadagno di velocità che di solito ottengo dalla costruzione di commit separati che rappresentano ciascuno un passaggio intermedio che compila e funziona.

Quindi, se devo introdurre un nuovo parametro in una funzione per implementare una funzione specifica, allora c'è un commit che non fa altro che aggiungere il parametro nella dichiarazione, nella definizione e in tutti i siti di chiamata. Quindi, il prossimo commit introduce funzionalità e il terzo aggiorna i siti di chiamata che utilizzano la nuova funzionalità.

Questo è facile da rivedere, perché i cambiamenti puramente meccanici possono essere esaminati rapidamente e quindi allontanarsi.

Allo stesso modo, se si riformatta il codice, dovrebbe essere sempre un commit separato.


1

Sebbene ci siano uno o due punti apparenti di disaccordo tra le risposte esistenti, anche se solo in enfasi, cercherò di riassumere i soliti consigli in un modo che chiarisca da dove provengono tutti:

  1. In primo luogo, scrivere un codice pulito; qualsiasi altra "documentazione" si prenderà cura di se stessa dopo. Il codice pulito è un insieme di principi da imparare in primo luogo: classi a responsabilità singola, metodi brevi che fanno una cosa, nomi di variabili e metodi buoni, nomi di classe / tipo migliori di questi focalizzandosi su metafore (ad esempio chiamare un MultiButtSupporter un soda), unit test per indicare i requisiti, DRY, SOLID, un paradigma coerente e così via.
  2. Il codice rivela come funziona il codice; i commenti rivelano perché il codice funziona. Ad esempio, spiega un +1 con "impedisce uno spegnimento di 1 errore" o una formula complicata con "derivato in questo libro di testo o in questa pagina Web".
  3. Qualunque cosa tu abbia fatto con i commenti, il punto 1 sopra potrebbe raggiungere questo obiettivo in un codice pulito. Vedi i commenti come fallimenti / mali necessari, o addirittura bugie se nel tempo si sincronizzano con il codice man mano che entrambi vengono modificati. I commenti non dovrebbero compensare il codice scritto male, perché i commenti dovrebbero essere scritti con più talento o attenzione rispetto al codice?

D'altra parte, se non altro probabilmente sbaglio troppo lontano dall'altra parte, quasi mai usando i commenti. I tuoi revisori del codice ti diranno se hai l'equilibrio nel posto sbagliato per loro, ma se fai uno sforzo consapevole per seguire il piano di 3 punti sopra probabilmente probabilmente sarai vicino al loro ottimale.


2
In che modo un commento "impedisce un errore off by 1" è diverso da un commento che dice "+1 non è un errore di battitura" o "Non sono a conoscenza di uno errori nel mio programma"? (I commenti utili in genere si riferiscono a qualcosa di più grande di +1 nel codice sorgente, o a qualcosa al di fuori del codice sorgente.) In tal modo, "il tuo punto 2 è ancora" derivato in questo libro di testo o in questa pagina Web ". Quindi il tuo punto 3 sembra suggerire che potresti essere in grado di esprimere "derivato in questo libro di testo o in questa pagina web" usando un codice abbastanza pulito senza alcun commento; wow, mi piacerebbe vederlo in azione.
Jirka Hanika,

@JirkaHanika Forse off-by-one è stato un cattivo esempio. Per quanto riguarda 3, intendevo "ciascuno potrebbe" piuttosto che "forse ciascuno"; quindi no, non credo che il solo codice possa chiarire queste cose. (Beh, potresti provare gaussianFromThisTextbookNamesApproximation come nome variabile, ma questa è una cattiva idea!)
JG
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.