La stampa su console / stdout è una buona strategia di debug?


11

Diciamo che abbiamo una funzione come questa:

public void myStart()
{
    for (int i = 0; i<10; i++) myFunction(i); 
}


private int myFunction(int a)
{

    a = foo(a);
    a = bar(a);
    return a; 
}

private int foo(int a)
{
    //do something here

    //something gnarly here

    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

Ora, per qualsiasi motivo, il nostro codice non funziona. Forse sta generando un errore, forse sta restituendo un valore sbagliato, forse è bloccato in un ciclo infinito.

La prima cosa che ogni programmatore del primo anno è stampare su console / std, (avendo imparato a stampare Hello World prima di imparare a usare un debugger).

Ad esempio, per eseguire il debug di questo codice potrebbero eseguire le seguenti operazioni:

private int myFunction(int a)
{
    print("before foo: a=" + a); 
    a = foo(a);
    print("before bar: a=" + a);
    a = bar(a);

    return a; 
}

private int foo(int a)
{
    //do something here
    print ("foo step1: a=" + a); 

    //something gnarly here
    print ("foo step2: a=" + a + " someOtherValue="+ someOtherValue + " array.length= " + someArray.length()); 
    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

Ora eseguono il codice, ottengono una grande console di stampa, che possono passare per rintracciare dove le cose vanno male.

Un'alternativa, ovviamente, è impostare punti di interruzione e scorrere il codice in ogni punto.

Uno dei principali vantaggi della stampa su console è che lo sviluppatore può vedere il flusso dei valori in una volta sola, senza dover fare clic su passaggi ecc.

Ma lo svantaggio è che il tuo codice è quindi pieno di tutte queste istruzioni di stampa che devono essere rimosse.

(È forse possibile dire al debugger di stampare solo determinati valori su un registro? I punti di interruzione possono quindi essere facilmente aggiunti o rimossi senza modificare effettivamente il codice.)

Uso ancora la stampa da console come metodo di debug primario, mi chiedo quanto sia comune / efficace rispetto a qualcos'altro là fuori.


1
È necessario imparare come utilizzare un debugger e utilizzare un framework di registrazione adeguato. Ti renderà molto più felice della stampa sulla console (che non sempre esiste).

7
È importante imparare a usare i debugger, tuttavia ci sono molte situazioni che potresti incontrare in cui il debugging di printf è l' unico metodo di debug disponibile.
whatsisname

Risposte:


26

Le dichiarazioni di stampa e il debugger non si escludono a vicenda. Sono solo strumenti diversi a tua disposizione per individuare / identificare i bug. Ci sono coloro che affermeranno come non toccano mai un debugger e ci sono quelli che non hanno una singola istruzione di registrazione / stampa in qualsiasi parte del codice che scrivono. Il mio consiglio è che non vuoi far parte di nessuno di questi gruppi.

Invece impara a usare la registrazione e impara ad usare un debugger. Con l'esperienza (quasi senza pensarci) sceglierai lo strumento giusto e eseguirai il lavoro in modo accurato ed efficiente. Senza esperienza, a volte sceglierai l'uno sull'altro, e forse ti ci vorrà un po 'più a frugare nelle variabili o a setacciare i file di registro, ma questo è tutto parte del processo di apprendimento.

Quindi, per rispondere alla tua domanda specifica. Sì. L'uso delle stampe per tracciare l'esecuzione è una strategia di debug valida e ampiamente utilizzata. Però...

Invece di utilizzare le istruzioni di stampa, è consigliabile utilizzare un framework di registrazione. I framework di registrazione hanno un concetto di livelli di registrazione in modo da poter aggiungere un sacco di messaggi di registro ma scegliere un livello per ognuno. Quando l'applicazione è in esecuzione in condizioni normali, il tuo livello sarebbe ERRORE o AVVISO in modo da riportare solo le cose importanti. Tuttavia, quando si sta analizzando il codice e è necessario comprendere il flusso di esecuzione, è possibile modificare il logger in INFO o DEBUG e ora tutte quelle istruzioni di "stampa" che già si hanno nel codice riporteranno ulteriori informazioni.

Utilizzo di un framework di registrazione ...

  1. non sarà necessario eliminare tutte le stampe dopo aver terminato.
  2. le stampe che lasci nel codice, possono aiutare te o qualsiasi altro sviluppatore a eseguire il debug dello stesso codice in futuro
  3. sarai in grado di eseguire il debug di questo codice sul campo senza doverlo ricostruire ogni volta solo per aggiungere le stampe che hai eliminato.
  4. sarai in grado di reindirizzare i messaggi di registrazione ovunque tu voglia, non solo una console. Potrebbero andare in un file, syslog, DB, socket ... ecc

Aggiornamento: Ho appena notato alla fine che stavi chiedendo "È possibile forse dire al debugger di stampare solo alcuni valori su un registro". A seconda del debugger utilizzato. Molti debugger moderni consentono di definire un'azione da invocare quando viene raggiunto un breakpoint. In alcuni (l'ho fatto in VS e WinDbg), è possibile specificare "stampa e riprendi". Visual Studio li chiama "punti di traccia" anziché "punti di interruzione"


+1 per il primo paragrafo. Debugger e log risolvono due problemi molto diversi.
Blrfl,

1
Ma non sei d'accordo sul fatto che lasciare le istruzioni di registro nel codice lo brutti?
dwjohnston,

1
dipende dal tipo di istruzioni di registro che lasci sul posto. Ho appena trovato e rimosso questo: "logger.error (" WHAT ")". Altrimenti, tratto il codice di registrazione proprio come il resto del mio codice. Formattalo, rendilo bello e rendilo informativo. Sì, cospargere una frase stampata ogni altra riga è un po 'troppo e ci sono state volte in cui ho dovuto ricorrere a quello. Ma in genere, avere 10-20 istruzioni di registro nell'intero file (file / classi di dimensioni ragionevoli e non gigantesche) non è affatto male.
DXM,

Capisco che lasciare alcune dichiarazioni di log in potrebbe essere utile, ad esempio se hai un sistema di produzione potresti voler registrare varie variabili importanti mentre vengono utilizzate, quindi se qualche errore si ripresenta puoi vedere immediatamente cosa è successo nella tua produzione ambiente. Tuttavia, per il contesto di sviluppo sembra disordinato. Ad esempio, stai scrivendo la tua funzione di analisi e non hai ancora capito bene la tua regex, quindi inserisci una serie di istruzioni di registro solo per controllare cosa sta succedendo e alla fine risolverlo. Non credo che aggiunga valore andando avanti lasciandoli dentro.
dwjohnston,

1
@Izkata: tutto dipenderà dalle specifiche del tuo specifico bug e dalla quantità di registrazione già effettuata dal tuo codice. Il punto che sto cercando di capire è che c'è sempre il valore di avere istruzioni di registrazione e di averle a diversi livelli: ERR -> WARN ... -> DEBUG. Se hai bisogno di qualcosa di più per qualcosa di molto specifico, sicuramente inizia ad aggiungere dichiarazioni di stampa. Ma la mia risposta a qualcuno che usa "print" come dichiarazione di registrazione, passerà sempre a un framework e inizierà a usarlo.
DXM,

3

Log / stampa e debugger sono tecniche complementari che presentano diversi punti di forza e di debolezza: è meglio usare entrambi. Ma nel complesso, direi che i debugger sono lo strumento migliore nella maggior parte dei casi e dovrebbero essere usati per primi, con la registrazione / stampa utilizzata solo per le cose in cui è effettivamente migliore.

Vantaggi dei debugger:

  • È possibile controllare l'intero stato del programma, non solo i valori che si pensava di stampare in anticipo. Ciò può accelerare enormemente il processo di debug riducendo il ciclo di feedback a meno di un secondo. Particolarmente importante quando ci vuole del tempo per raggiungere il bug.
  • Puoi vedere da dove provengono le chiamate e persino ispezionare i valori nella traccia dello stack.
  • È possibile (in una certa misura che dipende dalla lingua / dalla piattaforma) il codice di debug che non è possibile modificare facilmente poiché si dispone solo del codice binario o byte compilato.

Vantaggi della registrazione / stampa:

  • Non richiede una build o una configurazione di debug speciali. Funziona sempre
  • Può essere utilizzato per analizzare errori difficili da riprodurre e che si verificano raramente
  • Può essere utilizzato per analizzare errori dipendenti dal tempo in cui la pausa causata da un debugger può facilmente far scomparire il bug.
  • Ti fornisce informazioni permanenti che puoi analizzare a tuo piacimento. È possibile saltare avanti e indietro tra l'output in punti diversi nel flusso del programma.

Un altro vantaggio della registrazione è quando si verifica solo il problema all'ennesimo passaggio attraverso il codice e si potrebbe davvero usare un po 'di backtrace di come ci si è arrivati. La maggior parte dei debugger non ha un pulsante inverso, ma registrando i valori con cui è stata chiamata una funzione di livello superiore funzionerà, e spesso ti avvicina almeno a un piccolo caso riproducibile.
Christopher Creutzig,

1

La stampa su un output standard in un certo senso può essere una buona strategia per il debug del codice, ad esempio

  • Uso molte dichiarazioni di stampa per vedere cosa succede nei diversi livelli del mio codice, soprattutto se non capisco perfettamente l'errore

  • o forse l'errore non ha informazioni dettagliate che potrebbero indicarmi quale parte del codice sta causando esattamente il problema.

Tuttavia, devi abituarti agli strumenti di debug, ce ne sono molti là fuori a seconda della lingua o della piattaforma che usi.

Anche un altro metodo è la registrazione, registro errori continuamente quando lavoro su applicazioni Android, anche con la gestione delle eccezioni, si può facilmente registrare una traccia dello stack o un messaggio di errore dell'eccezione sollevata.


3
questo post è piuttosto difficile da leggere (wall of text). Ti dispiacerebbe modificarlo in una forma migliore?
moscerino il

L'ho reso un po 'leggibile. Ci scusiamo per il precedente!
Plaix,
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.