Trascorrere troppo tempo nel debug


24

Ieri, ho lanciato una versione v1.0 di un progetto Web su cui ho lavorato circa 6 settimane (acceso e spento, cioè). Non ho registrato esattamente il mio tempo, ma in base alle mie esperienze stimerei che, per tutto il tempo che ho trascorso a programmare, la metà è stata spesa per il debug. Stimo che impiegare circa 15-20 ore per il debug, che per me è un tempo prezioso che avrebbe potuto essere speso meglio scrivendo un nuovo codice o terminando il progetto prima. Inoltre, non aiuta in particolare il fatto che sarò una matricola al college tra 5 settimane.

Il fatto è che mi sento male per passare tutto il tempo a fare il debug. Tutto il tempo dedicato al debug mi fa capire che ho fatto degli errori piuttosto stupidi mentre stavo sviluppando il mio progetto, errori che mi sono costati un bel po 'di tempo per essere riparati.

Come posso evitare che ciò accada in futuro? Non voglio dedicare il 50% del mio tempo al debug, preferirei spendere il 10% al debug e il resto a scrivere nuovo codice. Quali sono alcune tecniche che posso provare per aiutarmi a raggiungere questo obiettivo?


22
Quando ero una matricola, anch'io ero un programmatore lento. Dagli solo 20 anni.
Giobbe

27
eh sì, buona fortuna con quello. "Se il debug è il processo di rimozione dei bug. Quindi la programmazione deve essere il processo per inserirli." -Edsger Dijkstra
Matt,

7
Hai imparato qualcosa da quegli errori? Se lo hai fatto, non li farai la prossima volta e questo ridurrà il tempo di debug.
Craig T

5
Questa si chiama "esperienza" e ti aiuterà nel tuo prossimo progetto.

4
Parlando della fine degli anni '40, Maurice Wilkes scrisse: "Non appena abbiamo iniziato a programmare, abbiamo scoperto con nostra sorpresa che non era facile ottenere i programmi come pensavamo. Il debugging ha dovuto essere scoperto. i miei viaggi tra la sala EDSAC e l'attrezzatura di punzonatura che "esitando agli angoli delle scale" mi sono reso conto con piena forza che buona parte del resto della mia vita sarebbe stata spesa a trovare errori nei miei programmi ".
Trevor Powell,

Risposte:


35

Stai chiedendo il Santo Graal per l'ingegneria del software e nessuno ha ancora "la" risposta a questa domanda.

Ciò che è essenziale è tenere traccia dei tipi di errori che si stanno facendo e quindi fare un'analisi di tali errori per determinare se esiste una tendenza comune. L'analisi della causa principale è il nome formale di questo tipo di introspezione e sul web è disponibile molto materiale.

I professionisti utilizzano un sistema di tracciamento dei bug in modo che possano (1) sapere cosa deve essere risolto, ma anche (2) analizzare ciò che deve essere corretto dopo il fatto. Non è necessario essere così formali: tenere un conteggio di un quaderno può andare bene per te.

Difetti della fase di progettazione

Se scopri che la maggior parte dei tuoi errori proviene da un malinteso sull'affermazione del problema, o se continui a scoprire che hai scelto l'algoritmo o il percorso sbagliato da seguire nella risoluzione dei problemi, hai problemi in fase di progettazione.

Sarebbe opportuno che tu impiegassi più tempo all'inizio del progetto e scriva esattamente cosa deve essere fatto e come dovrebbe farlo. Rivedi attentamente questo lavoro e rivisita il problema originale e determina se lo stai davvero affrontando nel modo giusto. Un'ora o tre in più all'inizio può farti risparmiare molte ore lungo la strada.

Errori di codifica

Se il tuo design è solido, ma stai costantemente combattendo il linguaggio con cui stai codificando, procurati alcuni strumenti che analizzeranno il tuo codice per te e ti avvertiranno presto e spesso che stai commettendo errori.

Se stai programmando in C, attiva tutti gli avvisi del compilatore, usa un controllo semantico simile linte usa uno strumento simile valgrindper rilevare problemi comuni relativi alla memoria dinamica.

Se si programma Perl, accendere stricte warningsed attenzione quello che dice.

Indipendentemente dalla lingua che stai utilizzando, probabilmente esistono molti strumenti per aiutarti a rilevare errori comuni molto prima che tu raggiunga la fase di debug.

Difetti dello stadio di integrazione

Man mano che sviluppi il codice seguendo le buone pratiche di modularità, devi iniziare a incollare i pezzi separati. Ad esempio, diverse sezioni del codice potrebbero avere a che fare con l'input dell'utente, l'interazione con il database, la visualizzazione dei dati, gli algoritmi / la logica e ognuno di questi è costruito relativamente indipendente l'uno dall'altro (vale a dire, si tende a concentrarsi sulla sezione a portata di mano piuttosto che preoccuparsi dell'integrazione con tutto il resto).

Qui è dove lo sviluppo test driven (TDD) è molto utile. Ogni modulo del tuo codice può avere test che verificano che funzionino secondo il modo in cui sono stati progettati. Questi test dovrebbero essere scritti prima o molto presto nel processo in modo da poter avere una serie di "aiutanti" per renderti onesto. Quando inizi a far funzionare tutto insieme e scopri che devi cambiare il modo in cui questo o quello viene implementato o interagisce con un altro sottosistema, puoi ricorrere ai tuoi test per assicurarti che ciò che hai fatto per rendere tutto funziona insieme non rompe la correttezza del codice.

E così via...

Raccogli alcuni libri sull'ingegneria del software e sulle tecniche pratiche di codifica e imparerai molti modi diversi per rendere lo sviluppo meno caotico e più affidabile. Scoprirai anche che solo una semplice vecchia esperienza - guadagnare una laurea dalla scuola dei colpi duri - ti metterà in forma.

Ciò che quasi tutto si riduce a è che un po 'di tempo e lavoro in anticipo paga in enormi dividendi più avanti nel processo di sviluppo / rilascio.

Il fatto che tu abbia notato questi problemi così presto nella tua carriera parla bene per il tuo futuro e ti auguro buona fortuna.


1
Questa è un'ottima risposta, ma IMHO a una domanda leggermente diversa. L'OP sta dicendo che ho trascorso 6 settimane a scrivere / spegnere qualcosa e ho dovuto dedicare molto tempo al debug. Non sappiamo ancora nulla della qualità, della manutenibilità, della scalabilità del suo prodotto. Se assumiamo TDD, una buona progettazione, il tracciamento dei bug, c'è ancora la domanda su come scrivere il codice (incluso il codice di test che deve anche essere sottoposto a debug) con meno difetti. Attivare gli avvisi, usare lanugine, ecc. Sono buoni suggerimenti. Più di quelli della scuola dei duri? :-)
Guy Sirton,

1
@Guy - Sì ... la domanda dell'OP era un po 'vaga, ecco perché sono andato con l'accento sull'analisi delle cause alla radice. Non sai cosa c'è che non va finché non sai cosa non va. Il motivo per cui ho dato il sondaggio sulle aree problematiche è perché volevo che fosse consapevole di molte potenziali insidie ​​e che ogni fase del processo merita il proprio esame. Per quanto ne so, potrebbe essere il prossimo Tony Hoare, ma uno con le abilità di battitura a macchina di un elefante cieco - correzioni diverse per cause diverse.
unpythonic il

37

Scrivi test unitari

Scrivere unit test per il tuo codice ti costringerà a pensare alla tua architettura e ti incoraggerà a scrivere il tuo codice in piccoli pezzi controllati con cura e testabili. Ciò ridurrà notevolmente il tuo sforzo di debug e la piccola quantità di debug che esegui sarà limitata a piccoli pezzi di codice strettamente focalizzati.

Inoltre, i test che scrivi "copriranno" il tuo codice; sarai in grado di dire quando una modifica apportata al codice rompe qualcosa, perché uno o più dei tuoi test esistenti falliranno. Ciò riduce la complessità complessiva delle attività di debug e aumenta la sicurezza che il codice funzioni.

Il trucco, ovviamente, è che il tempo dedicato al debug è ora dedicato alla scrittura di test. Ma devi scriverli solo una volta e possono essere eseguiti tutte le volte che è necessario dopo averli scritti.


+1 per i test unitari: prima nel processo di sviluppo i bug vengono individuati più a buon mercato e più facili da correggere.
Paul R,

26

Il 50% per il debug (in senso lato) non è poi così male. Le persone in genere impiegano molto più tempo a progettare, testare, correggere bug, refactoring e scrivere test unitari di quanto tu non scriva il codice reale. Fa parte del lavoro.

E ad essere onesti, è molto peggio nella programmazione della manutenzione - abbastanza spesso, passerei un'ora a capire cosa va esattamente storto, poi cinque minuti a scrivere il codice per ripararlo, e poi mezz'ora a testare il tutto. Questo è poco più del 5% di codifica contro quasi il 95% di non codifica.

Ci sono alcune cose che puoi fare per ridurre i tempi di debug:

  • Scrivi codice debuggable . Ciò significa: una corretta gestione degli errori (con qualche pensiero messo in esso), strutturare il codice per renderlo facile da seguire, usando assert, tracce e qualsiasi altra cosa possa semplificare la vita del debugger. Evita linee complicate; una linea che fa più di una cosa dovrebbe essere divisa in modo da poterla attraversare individualmente.
  • Scrivi codice testabile . Dividi il tuo codice in semplici funzioni (o qualsiasi altra cosa la tua lingua di scelta supporti); evitare effetti collaterali, poiché questi sono difficili da catturare nei test unitari. Progetta le tue funzioni in modo che possano essere eseguite in modo isolato. Evita le funzioni multiuso. Evitare i casi limite. Documenta cosa dovrebbero fare le tue funzioni.
  • Scrivi test . Avere unit test significa che sai che le tue funzioni funzionano per almeno un sottoinsieme dei loro input; significa anche che hai un controllo di integrità per confermare che le modifiche non interrompono nulla. Assicurati di comprendere i concetti di copertura del codice e copertura dell'input, nonché i limiti del test unitario.
  • Crea un "banco di lavoro" . Come esattamente lo fai dipende dalla lingua in questione. Alcune lingue, come Python o Haskell, sono dotate di un interprete interattivo e puoi caricare il tuo codice esistente per giocarci. Questo è perfetto, dal momento che puoi chiamare le tue funzioni in qualsiasi contesto tu voglia, con il minimo sforzo - uno strumento prezioso per trovare e isolare i bug. Altre lingue non hanno questo lusso e dovrai ricorrere a scrivere piccoli programmi di test interattivi.
  • Scrivi codice leggibile . Prendi l'abitudine di scrivere il tuo codice per esprimere le tue intenzioni nel modo più chiaro possibile. Documenta tutto ciò che non è perfettamente ovvio.
  • Scrivi un codice semplice . Se il tuo cervello ha difficoltà a comprendere l'intera base di codice, allora non è semplice ed è altamente improbabile che qualcun altro sia in grado di capirlo appieno. Non è possibile eseguire il debug del codice in modo efficace a meno che non si capisca cosa dovrebbe fare.
  • Sii facile con il pulsante "Elimina" . Qualsiasi codice che non ti serve in questo momento appartiene al cestino. Se ne hai bisogno in seguito, ripristinalo dal controllo del codice sorgente (l'esperienza mostra che questo è estremamente raro). Più codice viene eliminato, minore è la superficie di debug.
  • Refactor presto e spesso. Senza refactoring, non è possibile mantenere il codice in uno stato di debug mentre si aggiungono nuove funzionalità.

1
Inoltre, il mondo potrebbe comportarsi diversamente da come ci si aspetta in caso di problemi. Ciò può causare bug molto sottili.

2
+1. Direi che spendere solo il 50% per gli sforzi di debug è piuttosto basso, specialmente ma non solo in una base di codice consolidata. Se mi viene assegnato un bug, a meno che non richieda praticamente una riscrittura completa delle parti rilevanti del codice (improbabile), potrei spendere molto più di quella frazione del tempo totale solo per capire cosa non va, quindi testare la correzione. La correzione stessa è spesso rapida, spesso pari a una o poche righe di codice modificato.
un CVn del

@ ThorbjørnRavnAndersen Inferno sì, soprattutto con progetti Web come menziona l'OP. Ci stiamo divertendo molto con la codifica dei personaggi questa settimana al lavoro ...
Izkata

5

Più pianificazione

È inevitabile che trascorrerai un bel po 'di tempo a fare il debug, il 10% è un obiettivo piuttosto ambizioso. Sebbene uno dei modi migliori per ridurre il tempo dedicato al debug e allo sviluppo sia passare più tempo nella fase di pianificazione.

Questo può variare da diagrammi a pseudo codice su un tappetino di pianificazione. Ad ogni modo, avrai più tempo per sgridare ciò che la tua pianificazione su di fare piuttosto fare quegli errori durante lo sviluppo.


1
+1 perché è ciò che faccio per ridurre i tempi di debug. Quando inizio un nuovo progetto, scrivo tutto ciò che ho intenzione di fare nei commenti, quindi torno indietro e sostituisco i commenti con il codice
CamelBlues

Faccio lo stesso con i commenti, tanto più per impedirmi di dimenticare da dove avevo interrotto. Ma mi piace disegnare diagrammi di classe su carta e le loro dipendenze. Questo mi dà una buona visione di ciò che sto pensando in quel momento.
Bryan Harrington,

5

Lavora più attentamente

Questo è l'equivalente software di "misura due volte una volta":

  • Non programmare se ti senti distratto o stanco.
  • Trascorrere abbastanza tempo a pensare al problema in modo da avere una soluzione pulita ed elegante. Le soluzioni semplici hanno meno probabilità di avere problemi.
  • Dai tutta la tua attenzione al compito. Messa a fuoco.
  • Leggi il tuo codice rapidamente dopo la codifica per cercare e cercare errori. Revisione del codice di auto.
  • Non aspettare troppo a lungo tra codifica e test. Il feedback immediato è importante per migliorare.
  • Evita di fare cose che comunemente portano a errori. Continua a leggere odori di codice .
  • Scegli gli strumenti giusti per il lavoro.

Detto questo, nulla eliminerà completamente i difetti. Devi accettarlo come un fatto della vita. Dato questo piano informativo per difetti, ad es. Unit test. Inoltre, non prendere questo per significare "prendere per sempre" (aka analisi-paralisi). Si tratta di trovare un equilibrio.


4

Altre risposte hanno già coperto la maggior parte di ciò che voglio dire, ma voglio comunque darti la mia opinione (brutalmente onesta):

Fondamentalmente, per un lavoro software non banale, aspettati di dedicare la stragrande maggioranza del tuo tempo alla manutenzione e al debug. Se stai lavorando su un sistema software di produzione maturo e stai spendendo meno dell'80-90% del tuo tempo in manutenzione e debug, stai andando bene!

Ora, ovviamente, la distinzione tra "manutenzione" e "debug" è un po 'soggettiva. Consideri i "bug" solo problemi con il codice che si trovano dopo che è stato rilasciato e che gli utenti si sono lamentati? O è ogni piccola cosa che non va nel tuo codice una volta che hai aggiunto qualcosa (trovato nelle tue fasi di test pre-release)? In un sistema software non banale (a seconda dei modelli di utilizzo) uno può essere molto più grande dell'altro. Ma in ogni caso, questo è ciò che richiede la programmazione di qualcosa di più grande di un programma "Hello world", un sacco di manutenzione e debugging. Alcune persone dicono addirittura qualcosa del tipo " tutto ciò che dovrebbe essere dopo la prima riga di codice è" modalità di manutenzione ",

TL; DR: Mi sembra semplicemente che potresti avere un quadro leggermente irrealistico di ciò che riguarda la programmazione di sistemi software non banali. La stragrande maggioranza degli sforzi è finalizzata alla messa a punto, alla manutenzione, al refactoring, alla correzione di bug e, in generale, a fare cose che verrebbero sottoposte a "debug" (manutenzione) - almeno in senso molto generale - invece di fare un lavoro completamente nuovo, scrivere nuovo codice nuovo.


2

È difficile fornire tecniche specifiche senza dettagli specifici su ciò che stai facendo e quali tecnologie stai utilizzando. Ma anche i programmatori davvero bravi impiegano molto tempo a testare e eseguire il debug.

Scrivere un buon codice senza molti bug è esperienza. Fai degli errori, poi li ripari, poi ricordi quali erano gli errori e cosa dovevi fare invece per farli nel modo giusto, e la prossima volta non commetti lo stesso errore. E se non sei ancora al college e stai già iniziando a pensare seriamente ai modi per fare meno errori, direi che sei decisamente in vantaggio.


1
Mi stupisce le persone che vedo che non imparano dai loro errori (o che si preoccupano di cercare di ricordare ciò che hanno imparato). E subito dopo che qualcosa è esploso in faccia alla grande, si girano e fanno esattamente la stessa cosa nel prossimo progetto.
HLGEM

2

INTEGRAZIONE CONTINUA (CI) è la risposta.

Integrazione continua = Sistema di gestione della configurazione (vale a dire, Git, Mercurial, SVN, ecc.) + Strumento CI + Test unità + Test fumi

Tale formula dovrebbe spingerti a leggere di più sull'integrazione continua (CI). Di seguito sono riportate alcune risorse in quest'area:


1

In realtà, per ridurre il debug è possibile caricarlo anticipatamente pianificando in modo più approfondito. Non sei ancora stato al college? Penso che vedrai nei tuoi corsi di scuola media e tardiva che tratterai i dettagli del ciclo di vita dello sviluppo del software che molto bene potrebbe far luce sulle tue follie.

Mentre cerco di spiegare ai miei datori di lavoro, il modo migliore per ridurre la manutenzione del codice e il supporto tecnico è di dedicare del tempo a pianificare in anticipo il codice in modo completo.


1

Lo sviluppo testato può aiutare a ridurre i tempi di debug:

  • avere molti test piccoli e mirati significa che se si fallisce c'è solo una piccola quantità di codice che potrebbe aver causato il problema.
  • lavorare in piccoli passi (scrivendo un test fallito e poi facendolo passare) significa che puoi concentrarti su un compito alla volta. Cioè, rendendo l'attuale test passato.
  • il refactoring dopo aver effettuato un test test ti incoraggia a mantenere il tuo codice chiaro e comprensibile, facilitando il seguito in caso di problemi.

Anche se usi TDD, avrai comunque dei momenti in cui dovrai usare il debugger. In questo caso, dovresti provare a scrivere un test unitario per riprodurre lo scenario che ha causato la sessione di debug. Ciò assicurerà che se il problema si ripresenta, verrà rapidamente rilevato quando il test fallisce e il test fungerà da marker per l'area di codice che ha causato il problema, riducendo la necessità di debug.


1

Il debug è inevitabile nella programmazione, ma la chiave qui è: è facile eseguire il debug del codice o no? Se hai bisogno di passare ore solo per eseguire il debug di qualcosa di semplice, allora ci deve essere qualcosa di veramente sbagliato nella tua architettura di codice.

Dovresti abituarti a scrivere codice pulito e rimuovere cattive abitudini come copiare il codice di incollaggio e scrivere metodi lunghi, ecc.

Inoltre, è necessario refactoring il codice di volta in volta. Ti consiglio di leggere il libro di Martin Fowler: Rifattorizzare: migliorare la progettazione del codice esistente


1

Altri hanno menzionato test e revisione del codice. Entrambi sono estremamente utili ma hanno una differenza fondamentale: quando è meglio eseguirli. Il test viene eseguito molto vicino alla scrittura originale del codice, in modo da poter ricordare più facilmente perché hai fatto le cose in un certo modo e puoi individuare più rapidamente il problema quando fallisce il test. La revisione del codice, d'altra parte, è meglio fare un po 'più tardi. Volete guardare il codice senza un perfetto ricordo, in modo da non sorvolare i dettagli a cui vi ricordate di aver pensato ma che non avete inserito. Volete realizzare luoghi in cui il vostro codice non è chiaro. Volete il piccolo sforzo extra di dover capire cosa sta facendo il codice. Vuoi essere in grado di applicare tutte le nuove conoscenze acquisite sul problema o le interazioni con altri codici o nuove tecniche. Fondamentalmente,

Tutto ciò è comunque tangente alla tua domanda. Per dedicare meno tempo al debug, devi innanzitutto capire perché hai dovuto eseguire il debug. Incomprensione del problema, conoscenza imperfetta dei vostri strumenti e tecnologie, e semplicemente incappando in "i dati reali non corrispondevano ai dati di esempio" tipi di problemi si manifesteranno tutti in modi diversi e necessitano di tecniche e tipi di pratica diversi per evitare nel futuro.

L'ultimo punto che farò è l'esperienza. Non esiste un modo semplice per ottenere questo, devi solo mettere il tempo. Man mano che acquisisci esperienza, passerai meno tempo a eseguire il debug perché, per cominciare, scriverai un codice migliore, noterai i problemi in precedenza e svilupperai una migliore intuizione su quale potrebbe essere la fonte di un problema. Continuate così e lo farete crescere costantemente nel corso della vostra carriera.


0

Grandi risposte sopra, ma nessuno ha menzionato direttamente (anche se la maggior parte ha accennato a questo):

LEGGI LEGGI LEGGI LEGGI e su nauseam ...

Più sai, meno non sai. Un po 'di cliché, ma comunque la verità di base.

Dopo aver seguito i suggerimenti di cui sopra e aver documentato analiticamente i bug, provare a classificarli, quindi leggere la letteratura pertinente.

È stato un problema di decisione di progettazione? Leggi i modelli di progettazione.

Era una mancanza di conoscenza della struttura o della lingua? Dacci dentro!

eccetera

Ci sono due cose che uno sviluppatore (live) non può mai sfuggire: il cambiamento (l'unica costante nell'IT) e RTFMing ...


0

Test unitari e asserzioni

Ove possibile, fattorizza il tuo codice in piccoli pezzi che possono essere testati separatamente. Questo non è sempre pratico, però. Alcune funzionalità dipendono da input estremamente complicati. Alcuni fanno qualcosa che non può essere facilmente verificato in modo automatizzato, come disegnare elementi sullo schermo. A volte è coinvolto il non determinismo, ecc.

Quando non puoi scrivere buoni test unitari, la cosa migliore da fare è affermare. Mentre i test unitari controllano se si ottiene la risposta corretta su alcuni input prestabiliti, si asserisce verificare l'integrità dei passaggi intermedi sugli input del mondo reale. Se il tuo codice ha dei bug, fallirà rapidamente, vicino alla radice del problema e con un chiaro messaggio di errore, piuttosto che lontano dal problema con un ambiguo messaggio di errore. Inoltre, afferma ipotesi documentali e rende il tuo codice più leggibile.


0

Quando avvii un progetto, quanti approcci alternativi identifichi?

Hai da due a quattro approcci diversi, con pro e contro per ciascuno? Quindi fai una scelta ragionata tra di loro?

Quindi, cosa più importante, consideri la semplicità come estremamente importante?

Il motivo per cui chiedo è, nella mia esperienza, il volume del codice, e quindi il numero di bug (per non parlare delle prestazioni), può variare di più di un ordine di grandezza tra un approccio progettuale e l'altro. Quello che vedo fare persone di grande esperienza è svolgere lavori senza più codice del necessario.

Sono pienamente competenti e consapevoli di tutti gli algoritmi della struttura dei dati, delle caratteristiche dei linguaggi orientati agli oggetti e così via, ma il loro codice sembra che non lo siano , perché usano queste cose con parsimonia , o per niente, se il problema lo fa non li richiedono.


0

Ogni volta che correggi un bug, vuoi evitare di ripetere lo stesso errore. Per fare ciò, puoi fare quanto segue:

  • Annotalo in un registro di registrazione dei difetti , che include:

    • tipo di difetto
    • fase in cui è stato iniettato il difetto
    • fase in cui è stato rimosso
    • tempo fisso
    • una descrizione del problema e correzione
  • Adotta una styleguide per normalizzare lo stile del codice che scrivi

  • Integra regole di codifica sicure nel tuo processo di revisione del codice

  • Visualizza il flusso di controllo e i dati

Riferimenti

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.