Trascorrere troppo tempo nel debug

24

Ieri ho lanciato una versione 1.0 di un progetto Web su cui ho lavorato per circa 6 settimane (acceso e spento, cioè). Non ho fatto alcuna registrazione esatta del mio tempo, ma secondo le mie esperienze stimerei che di tutto il tempo che ho passato a programmare, metà di esso è stato speso per il debugging. Stimo che trascorrerà circa 15-20 ore di debugging, il che per me è un tempo prezioso che sarebbe stato meglio spendere per scrivere un nuovo codice o finire il progetto prima. Soprattutto non aiuta che sarò una matricola al college in 5 settimane.

Il fatto è che mi sento male per aver passato tutto il tempo a debuggare. Tutto il tempo trascorso nel debugging mi ha fatto capire che ho commesso degli errori piuttosto stupidi mentre stavo sviluppando il mio progetto, errori che mi sono costati molto tempo per sistemare.

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

    
posta Ryan 16.07.2011 - 05:27
fonte

16 risposte

35

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

L'essenziale è tenere traccia dei tipi di errori che stai facendo e quindi eseguire un'analisi di tali errori per determinare se esiste una tendenza comune. L'analisi delle cause principali è il nome formale di questo tipo di introspezione e sul Web è presente materiale in abbondanza.

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

Difetti fase di progettazione

Se ritieni che la maggior parte dei tuoi errori provenga da un fraintendimento dell'affermazione del problema, o continui a cercare di aver scelto l'algoritmo o il percorso sbagliato da seguire per risolvere i tuoi problemi, hai problemi nella fase di progettazione.

Dovresti prendere più tempo all'inizio del progetto e scrivere esattamente ciò che deve essere fatto e come dovrebbe farlo. Esamina attentamente questo lavoro e rivisita il problema originale e stabilisci se lo stai affrontando nel modo giusto. Un'ora o tre in più all'inizio potrebbe farti risparmiare molte ore lungo la strada.

Errori di codifica

Se il tuo progetto è solido, ma combatti costantemente con il linguaggio con cui stai codificando, procurati alcuni strumenti che analizzeranno il tuo codice per te e ti avviseranno in anticipo e spesso che stai commettendo errori.

Se stai programmando in C, attiva tutti gli avvisi del compilatore, usa un controllo semantico come lint e usa uno strumento come valgrind per catturare problemi comuni relativi alla memoria dinamica.

Se stai programmando Perl, attiva strict e warnings e fai attenzione a ciò che dice.

Indipendentemente dalla lingua che stai utilizzando, probabilmente esistono molti strumenti che consentono di individuare errori comuni molto prima di raggiungere la fase di debug.

Difetti fase di integrazione

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

Qui è dove lo sviluppo guidato da test (TDD) è molto utile. Ogni modulo del tuo codice può avere test che verificano che funzionino in base a come sono stati progettati. Questi test dovrebbero essere scritti prima o molto presto nel processo in modo da poter avere una serie di "aiutanti" per mantenerti onesto. Quando inizi a far funzionare tutto insieme e scopri che stai cambiando il modo in cui questo o quello è implementato o interagisce con un altro sottosistema, puoi ricorrere ai test per assicurarti che ciò che hai fatto tutto funziona insieme non infrange 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 semplicemente una vecchia esperienza - guadagnare una laurea dalla scuola dei duri - ti aiuterà anche a metterti in forma.

Ciò che quasi tutto si riduce è che un po 'di tempo e il lavoro in anticipo ripaga 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.

    
risposta data 16.07.2011 - 05:58
fonte
36

Scrivi test delle unità

Scrivere test di unità per il tuo codice ti costringerà a pensare alla tua architettura e incoraggiarti a scrivere il tuo codice in piccoli pezzi testati attentamente controllati. Ciò ridurrà notevolmente il tuo sforzo di debug e la piccola quantità di debug che eseguirai sarà limitata a piccole parti di codice strettamente focalizzate.

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

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

    
risposta data 16.07.2011 - 05:54
fonte
25

50% per il debug (in senso lato) non è poi così male. In genere, le persone dedicano molto più tempo a progettare, testare, correggere bug, refactoring e scrivere test unitari rispetto a quando si scrive il codice vero e proprio. Fa parte del lavoro.

E per essere onesti, è molto peggio nella programmazione della manutenzione - molto spesso passerei un'ora a capire cosa va esattamente storto, poi cinque minuti a scrivere il codice per sistemarlo e poi mezz'ora a testare l'intera cosa . Si tratta di una codifica di oltre il 5% rispetto a quasi il 95% di non codifica.

Tuttavia ci sono alcune cose che puoi fare per ridurre il tempo di debug:

  • Scrivi codice debuggable . Ciò significa: una corretta gestione degli errori (con qualche pensiero in esso inserito), strutturare il codice per renderlo più facile da seguire, usando asserzioni, tracce e quant'altro può facilitare la vita del debugger. Evita le linee complicate; una linea che fa più di una cosa dovrebbe essere divisa in modo che tu le passi individualmente.
  • Scrivi codice verificabile . Dividi il tuo codice in semplici funzioni (o qualsiasi altra cosa supporti la tua lingua preferita); evitare effetti collaterali, poiché questi sono difficili da catturare nei test unitari. Progetta le tue funzioni in modo che possano essere eseguite in isolamento. Evitare le funzioni multiuso. Evita i casi limite. Documenta cosa dovrebbero fare le tue funzioni.
  • Scrivi test . Avere test unitari 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 tue modifiche non infrangono nulla. Assicurati di aver compreso i concetti di copertura del codice e copertura dell'input, nonché i limiti del test dell'unità.
  • Imposta un "workbench" . Quanto esattamente lo fai dipende dalla lingua in questione. Alcuni linguaggi, come Python o Haskell, hanno un interprete interattivo e puoi caricare il tuo codice esistente per giocare con esso. Questo è perfetto, dal momento che puoi chiamare le tue funzioni in qualsiasi contesto che ti piace, con il minimo sforzo - uno strumento inestimabile 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 problemi 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 sul pulsante "Elimina" . Qualsiasi codice non necessario al 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 disponi, più piccola è la tua superficie di debug.
  • Refactor presto e spesso. Senza refactoring, non puoi mantenere il tuo codice in uno stato di debugging aggiungendo nuove funzionalità.
risposta data 16.07.2011 - 10:41
fonte
5

Più pianificazione

È inevitabile che spenderai una buona quantità di tempo per il debug, il 10% è un obiettivo piuttosto ambizioso. Anche se uno dei modi migliori per ridurre il tempo speso per il debugging e lo sviluppo è passare più tempo nella fase di pianificazione.

Può variare da diagrammi a pseudo codice su un riquadro di pianificazione. In ogni caso, avrai più tempo per sgranocchiare quello che stai pianificando di fare piuttosto commettere quegli errori durante lo sviluppo.

    
risposta data 16.07.2011 - 05:35
fonte
5

Lavora con più attenzione

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

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

Tutto ciò che è stato detto, nulla eliminerà completamente i difetti. Devi accettare questo come un dato di fatto. Dato questo piano di fatti per i difetti, ad es. test unitario. Inoltre, non considerare questo come "prendi per sempre" (alias analisi-paralisi). Si tratta di trovare l'equilibrio.

    
risposta data 16.07.2011 - 19:52
fonte
4

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

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

Ora ovviamente, la distinzione tra "manutenzione" e "debugging" è un po 'soggettiva. Considerate solo "bug" i problemi con il codice che si trovano dopo il rilascio e gli utenti si sono lamentati di loro? O è ogni piccola cosa che va storta con il tuo codice una volta che hai aggiunto qualcosa (trovato nelle tue fasi di test pre-rilascio)? 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 la programmazione di qualcosa di più grande di un programma "Hello world" di un giocattolo richiede - un sacco di manutenzione e debugging. Alcune persone dicono addirittura qualcosa come " tutto ciò che è necessario prevedere dopo la prima riga di codice come" modalità di manutenzione ", con più sforzi di refactoring e debugging rispetto alla semplice scrittura di un nuovo codice ".

TL; DR: Mi sembra semplicemente che tu possa avere un'immagine un po 'irrealistica di cosa sia la programmazione di sistemi software non banali. La stragrande maggioranza degli sforzi consiste nella messa a punto, nella manutenzione, nel refactoring, nella correzione degli errori e, in generale, nel fare cose che potrebbero essere "debuggate" (manutenzione) - almeno in un senso molto generale - anziché fare un nuovo lavoro totalmente nuovo, scrivere nuovo codice nuovo.

    
risposta data 17.07.2011 - 11:29
fonte
2

È difficile dare tecniche specifiche senza dettagli specifici su cosa stai facendo e su quali tecnologie stai utilizzando. Ma anche i coder davvero bravi passano molto tempo a testare e eseguire il debug.

Un sacco di scrivere un buon codice senza un sacco di bug è esperienza. Fai degli errori, poi li correggi, poi ti ricordi quali erano gli errori e cosa dovevi fare, invece di farli bene, e non faresti lo stesso errore la prossima volta. E se ancora non sei ancora al college e stai già iniziando a pensare seriamente ai modi per fare meno errori, direi che sei decisamente più avanti al gioco.

    
risposta data 16.07.2011 - 05:38
fonte
2

INTEGRAZIONE CONTINUA (CI) è la risposta

Integrazione continua = Sistema di gestione della configurazione (cioè Git, Mercurial, SVN, ecc.) + Strumento CI + Test unità + Test fumo

Questa formula dovrebbe spingerti a leggere di più su CI (Continuous Integration). Di seguito sono riportate alcune risorse in quest'area:

risposta data 17.07.2011 - 20:42
fonte
1

In realtà, per ridurre il debug è possibile caricarlo frontalmente pianificando in modo più approfondito. Non sono ancora stato al college? Penso che vedrai nelle tue classi di college da metà a fine coprire 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 è passare il tempo a pianificare in modo completo il codice in anticipo.

    
risposta data 16.07.2011 - 05:45
fonte
1

Lo sviluppo guidato dai test può aiutare a ridurre i tempi di debug di:

  • avere molti piccoli test focalizzati significa che se uno fallisce c'è solo una piccola quantità di codice che potrebbe aver causato il problema.
  • lavorare a piccoli passi (scrivendo un test non funzionante e poi passandolo) significa che sei in grado di concentrarti su un compito alla volta. Cioè, facendo passare il test corrente.
  • refactoring dopo aver effettuato un test pass ti incoraggia a mantenere il tuo codice chiaro e comprensibile - semplificando la procedura da seguire in caso di problemi.

Anche se usi TDD, avrai ancora dei momenti in cui devi usare il debugger. Quando ciò accade, 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à catturato rapidamente quando il test fallirà e il test fungerà da indicatore dell'area del codice che ha causato il problema, riducendo la necessità di eseguire il debug.

    
risposta data 17.07.2011 - 10:53
fonte
1

Il debug è inevitabile in fase di programmazione, ma la chiave qui è che il tuo codice è facile da eseguire per il debug 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 nell'architettura del codice.

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

Inoltre, dovresti rifattorizzare il tuo codice di volta in volta. Ti suggerisco di leggere il libro di Martin Fowler: Refactoring: migliorare il design del codice esistente

    
risposta data 19.07.2011 - 11:37
fonte
1

Altri hanno menzionato la verifica e la revisione del codice. Questi sono entrambi estremamente utili ma hanno una differenza fondamentale - quando è meglio eseguirli. È meglio fare il test 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 fatta un po 'più tardi. Vuoi vedere il codice senza un ricordo perfetto in modo da non sorvolare dettagli che ricordi di aver pensato ma che non hai inserito. Vuoi realizzare luoghi in cui il tuo codice non è chiaro. Vuoi il piccolo sforzo in più di dover capire cosa sta facendo il codice. Vuoi essere in grado di applicare le nuove conoscenze acquisite sul problema o le interazioni con altri codici o nuove tecniche. Fondamentalmente, vuoi un cambio di prospettiva sul codice.

Tutto questo è ancora tangente alla tua domanda, però. Per dedicare meno tempo al debug, devi capire perché hai dovuto eseguire il debug in primo luogo. Malinteso il problema, conoscenza imperfetta dei vostri strumenti e tecnologie, e semplicemente imbattersi in "i dati reali non corrispondevano ai dati di esempio", i tipi di problemi si manifestano in modi diversi e richiedono tecniche e tipi di pratica diversi per evitare in futuro.

L'ultimo punto che farò è l'esperienza. Non c'è un modo semplice per ottenere questo, devi solo mettere il tempo. Man mano che acquisisci esperienza, passerai meno tempo a eseguire il debug perché inizierai a scrivere un codice migliore, noterai problemi in precedenza e svilupperai una migliore intuizione su quale potrebbe essere la fonte di un problema. Continua così e lo farai crescere costantemente durante la tua carriera.

    
risposta data 12.12.2011 - 00:52
fonte
0

Grandi risposte sopra ma nessuna menzionata direttamente (anche se è più sintomatico di questo):

LEGGI LEGGI LEGGI et a nauseam ...

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

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

È stato un problema di decisione di progettazione? Leggi su Design Patterns.

Era una mancanza di conoscenza del framework o della lingua? Fatto a pezzi!

etc

Ci sono due cose che uno sviluppatore (live) non può mai scappare: change (l'unica costante in IT) e RTFMing ...

    
risposta data 18.07.2011 - 07:46
fonte
0

Unit test e asserisce

Se possibile, calcola 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 cose che non possono essere facilmente verificate in modo automatico, come disegnare oggetti sullo schermo. A volte non è coinvolto il 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 giusta su alcuni input predeterminati, i test verificano la sanità mentale 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 messaggio di errore ambiguo. Inoltre, asserisce le ipotesi del documento e rende il tuo codice più leggibile.

    
risposta data 11.12.2011 - 22:42
fonte
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à molto importante?

Il motivo per cui lo chiedo è, secondo la 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 un altro. Quello che vedo fare persone di grande esperienza è ottenere 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 siano , perché usano quelle cose con parsimonia , o per niente, se il problema non le richiede.

    
risposta data 12.12.2011 - 00:20
fonte
0

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

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

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

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

  • Visualizza il flusso di controllo e dati

Riferimenti

risposta data 06.06.2018 - 17:38
fonte

Leggi altre domande sui tag