Come ridurre il numero di bug durante la codifica?


30

Nessuno è perfetto, e non importa quello che facciamo, di tanto in tanto produciamo codice che contiene dei bug. Quali sono alcuni metodi / tecniche per ridurre il numero di bug che produci, sia quando si scrive un nuovo software sia quando si modifica / mantiene il codice esistente?


Un buon metodo consiste nel progettare più in anticipo (non troppo, ma abbastanza per rendere il codice più strutturato e più facile da capire).
Giorgio,

Risposte:


58

Evita la codifica elaborata. Più è complicato il codice, più è probabile che ci siano dei bug. Di solito sui sistemi moderni, il codice chiaramente scritto sarà veloce e abbastanza piccolo.

Usa le librerie disponibili. Il modo più semplice per non avere bug che scrivono una routine di utilità è non scriverlo.

Impara alcune tecniche formali per le cose più complicate. Se ci sono condizioni complicate, inchiodale con carta e penna. Idealmente, conosci alcune tecniche di prova. Se riesco a dimostrare che il codice è corretto, è quasi sempre buono tranne che per bug grandi, stupidi, ovvi che sono facili da correggere. Ovviamente, questo va solo così lontano, ma a volte puoi formalmente ragionare su cose piccole ma complicate.

Per il codice esistente, scopri come eseguire il refactoring: come apportare piccole modifiche al codice, spesso utilizzando uno strumento automatizzato, che rendono il codice più leggibile senza modificare il comportamento.

Non fare nulla troppo in fretta. Prendersi un po 'di tempo in anticipo per fare le cose nel modo giusto, controllare ciò che hai fatto e pensare a quello che stai facendo può ripagare alla grande in un secondo momento.

Dopo aver scritto il codice, utilizza ciò che hai per renderlo valido. I test unitari sono fantastici. Spesso puoi scrivere test in anticipo, il che può essere un ottimo feedback (se fatto in modo coerente, si tratta di uno sviluppo guidato dai test). Compilare con le opzioni di avviso e prestare attenzione agli avvisi.

Chiedi a qualcun altro di guardare il codice. Le revisioni formali del codice sono buone, ma potrebbero non essere utili. Estrai richieste o simili se il tuo scm non le supporta consente revisioni asincrone. Il controllo degli amici può essere una revisione meno formale. La programmazione delle coppie garantisce che due paia di occhi guardino tutto.


x2 - cosa ha detto Ryan.
JBR Wilkinson,

2
anche la maggior parte delle lingue può essere più o meno esigente. Vuoi che sia il più esigente possibile.

1
"Impara alcune tecniche formali per le cose più complicate." ... per esempio?
Dan Rosenstark,

1
@Yar: mi aspetto qualcosa di simile ai sistemi spiegati in questo libro: amazon.com/Verification-Sequential-Concurrent-Programs-Computer/… ; anche se devo dire che il libro specifico è estremamente secco e noioso, quindi probabilmente ce ne sono di molto migliori là fuori (ma è l'unico che ho letto).
Joeri Sebrechts,

30

I test unitari ti consentono di ridurre il numero di bug che compaiono una seconda volta. Se trovi un bug nel tuo codice, scrivere un test unit farà in modo che non venga più visualizzato in seguito. (Inoltre, pensare a tutti i casi e scrivere migliaia di test unitari in anticipo è difficile da fare a volte)


3
"Pensare a tutti i casi in anticipo" porta a interfacce pulite e completamente specificate, che possono solo essere una buona cosa. I test unitari sono difficili da scrivere solo se li stai adattando a codice che non è stato progettato pensando ai test.
Mike Seymour,

1
Se puoi, dovresti. Sfortunatamente, la maggior parte dei posti in cui ho visto i test unitari è qualcosa che costa di più del semplice "correggere i bug molto velocemente". Quindi, se puoi, allora dovresti scrivere i test in anticipo, ma se non è visto come "conveniente", quindi scriverli insieme a correzioni di bug ti aiuta a costruirlo nel tempo senza mettere troppo budget per scrivere solo test di unità .
Ryan Hayes,

4
"I test mostrano la presenza, non l'assenza di bug." - E. Dijkstra. Detto questo, i test automatizzati sono sicuramente un modo molto utile per mantenere e aumentare la qualità del software.
limist

9

+1 su entrambi i commenti del test unitario.

Oltre a ciò, imposta il livello di avviso più alto offerto dal compilatore e assicurati che gli avvisi vengano trattati come errori. I bug spesso si nascondono in quegli errori "errati".

Allo stesso modo, investi in strumenti di analisi statica che vengono eseguiti in fase di compilazione (li vedo come un livello aggiuntivo di avvisi del compilatore).


+1 per il commento sull'analisi statica. È prezioso ottenere tutte queste informazioni gratuitamente :)
Morten Jensen il

9

Oltre a quanto menzionato:

  • Non ignorare i codici di errore - ad es. Non dare per scontato che tu abbia ottenuto un risultato valido, che un file sia stato creato con successo, ecc ... Perché un giorno succederà qualcosa.
  • Non dare per scontato che il tuo codice non entrerà mai in alcuna condizione e che quindi "è sicuro ignorare quella condizione".
  • Prova il tuo codice, quindi fallo testare da qualcun altro. Trovo di essere la persona peggiore per testare il mio codice.
  • Fai una pausa, quindi rileggi il tuo codice e vedi se hai "perso l'ovvio". Mi capita spesso.

Molte altre cose che sto dimenticando in questo momento, ma le altre sicuramente ci penseranno. :)


7
E se sei così sicuro che la condizione X non accadrà mai ... usa un'affermazione per assicurarti che quando si verifica la condizione X, lo saprai (tramite un'eccezione, o la registrazione, o qualsiasi altra cosa).
Frank Shearar,

@MetalMikester: i test unitari sono buoni. Ma con linguaggi di alto livello e buone librerie, la maggior parte dei bug corretti richiede test di integrazione e regressione per essere risolti.
Vector

9

Ho sviluppato uno stile di programmazione abbastanza funzionale, nonostante i miei linguaggi principali siano C ++ e Python. Ho scoperto che se passo tutto il contesto a una funzione (o metodo) di cui quella funzione ha bisogno per fare il suo lavoro, e restituendo i dati significativi che sto cercando, il mio codice è diventato molto più robusto.

Lo stato implicito è il nemico e nella mia esperienza è la prima fonte di bug. Questo stato può essere variabili globali o variabili membro, ma se i risultati dipendono da qualcosa che non viene passato alla funzione che stai chiedendo problemi. Chiaramente non è possibile eliminare lo stato, ma minimizzarlo ha enormi effetti positivi sull'affidabilità del programma.

Mi piace anche dire ai miei colleghi che ogni ramo (se, per, mentre, :) è probabilmente un bug. Non posso dire quale sarà la manifestazione del bug, ma meno comportamento condizionale ha il tuo codice, più è probabile che sia privo di bug semplicemente perché la copertura del codice durante l'esecuzione sarà più coerente.

Vai a capire, tutte queste cose hanno anche effetti positivi sulle prestazioni. Vincere!


Nella mia esperienza, può rapidamente diventare noioso passare tutto lo stato per ogni chiamata, se i metodi sono piccoli come dovrebbero essere. Questo problema può essere risolto utilizzando molte piccole classi immutabili con brevi tempi di vita degli oggetti. In questo modo è possibile memorizzare lo stato temporaneo come campi e scartare l'oggetto quando non è più necessario lo stato. :-)
Jørgen Fogh

Un'altra considerazione per quel caso in cui diventa noioso è che forse stai cercando di passare troppo stato. :)
dash-tom-bang,

In molti casi è vero, ma spesso non lo è. All'interno di alcuni domini è necessario accedere a molti stati, anche se non si dispone di molti stati mutabili . Attualmente sto lavorando a un generatore di codice in cui ho bisogno di accedere a diverse tabelle di simboli. Non voglio passarli a tutti i metodi.
Jørgen Fogh,

8
  • Scrivi meno codice che fa di più.
  • Pensa alle implicazioni di basso livello e alle ramificazioni di alto livello
  • Contempla l'astrazione che stai creando nel tuo codice.
  • Scrivi solo la complessità essenziale, se possibile.

Stavo per scrivere un grosso post che riassumesse come "scrivere meno che fa di più" (IOW conosco e uso gli strumenti a tua disposizione). Invece lo farò +1.
Kaz Dragon,

1
Ma fai attenzione a non ottenere codice elaborato quando cerchi di ottenere meno codice.
gablin,

1
@gablin: la fantasia è negli occhi di chi guarda per molti aspetti. Oggi posso scrivere e leggere il codice che mi sarei stupito 4 anni fa. Haskell oggi mi piace. :)
Paul Nathan,

8

Risposta un po 'meno tecnica: non programmare quando sei stanco (9 ore al giorno sono sufficienti), ubriachi o "cotti". Quando sono stanco non ho la pazienza necessaria per scrivere un codice pulito.


2
Di solito ci vogliono molti anni per la maggior parte dei programmatori per rendersene conto. È un punto importante
Jeff Davis,


5

Alcune ottime risposte qui per quanto riguarda i test e gli strumenti di unità. L'unica cosa che posso aggiungere a loro è questa:

Coinvolgi i tester il prima possibile

Se hai un team di test, non cadere nella trappola di trattarli come gatekeeper per la qualità del tuo codice e cogliere i tuoi difetti per te. Invece, lavora con loro e coinvolgi il più presto possibile (su progetti agili questo sarà dall'inizio del progetto, ma possiamo sempre trovare il modo di coinvolgerli prima se davvero ci proviamo).

  • Scopri qual è il loro piano di test. Rivedi i loro casi di test con loro - li stai coprendo tutti con il tuo codice?
  • Chiedi loro di comprendere i requisiti. È uguale al tuo?
  • Dai loro build precoci per eseguire test esplorativi: rimarrai stupito dai miglioramenti che suggeriranno.

Avere un buon rapporto di lavoro con i tester significa che è possibile rilevare presupposti e difetti scadenti molto presto, prima che possano arrecare danni. Significa anche che i tester si sentono in grado di aiutare con la progettazione del prodotto e rilevare i problemi di usabilità quando c'è tempo per risolverli.


4

Strumenti di analisi statica

Plugin e app come FindBugs eseguono la scansione del codice e trovano luoghi in cui sono presenti potenziali bug. I luoghi in cui le variabili non sono inizializzate e utilizzate o solo cose folli che 9 volte su 10, facilitano l'insorgere di bug. Strumenti come questo mi aiutano a impedire che la mia testa di osso si muova lungo la strada anche se non è ancora un bug.

PS: ricorda di cercare sempre perché uno strumento ti dice che qualcosa non va. Non fa mai male all'apprendimento (e non tutto è giusto in tutte le situazioni).


3

Ispezione del codice o altre forme di peer review come la programmazione di coppie.

Revisioni di codici strutturati come l'ispezione di Fagan possono essere almeno efficaci ed efficienti quanto i test unitari e in alcuni casi ha persino dimostrato di essere migliore dei test unitari. Le ispezioni possono anche essere utilizzate in precedenza nel ciclo di vita del software e con artefatti diversi dal codice.

Peer Review in Software di Karl Wiegers è un ottimo libro su questo argomento.


2

Oltre a tutti gli altri suggerimenti qui, attiva tutti i possibili avvisi al massimo livello di sensibilità e trattali come errori. Utilizza anche tutti gli strumenti di sfilacciatura della lingua.

Si sarebbe stupito di come molti errori semplici possono essere catturati da avvisi e quante di queste cose semplici tradurre in reali bug nel codice.


2

Molte buone risposte qui, ma alcune cose che volevo aggiungere. Assicurati di aver effettivamente compreso il requisito. Ho visto molti bug quando l'utente pensava che il requisito significasse X e il programmatore pensava che significasse Y. Respingi per chiarimenti su requisiti scadenti o ambigui. So che a tutti piace saltare e programmare, ma più tempo speso in anticipo per garantire la comprensione, meno rielaborazioni e correzione di errori ci saranno.

Conosci il business che stai supportando, spesso vedrai cose nei requisiti che mancano o che necessitano di ulteriori spiegazioni. Sappi che se esegui l'attività Y come indicato, si interromperà la funzione Z esistente.

Comprendi la struttura del tuo database. Molti molti bug sono il risultato di una query sintatticamente corretta, ma che restituisce risultati errati. Scopri come riconoscere quando i tuoi risultati sembrano divertenti. Se scrivo una complessa query di segnalazione, chiedo sempre a uno specialista tecnico di rivedere i miei risultati prima di contrassegnarlo come pronto per andare, vedranno inevitabilmente qualcosa nei dati che ho perso. Quindi prendi appunti su ciò che hanno catturato che non hai fatto e ricorda che la prossima volta che fai qualcosa di simile.


1

Penso che la tecnica più importante sia prenderti il ​​tuo tempo . Se ritieni di aver bisogno di due giorni per codificare un nuovo modulo, ma il tuo capo ti costringe a programmare solo in un giorno ... il tuo codice sarà probabilmente più difettoso.

Uno dei libri che ho letto qualche tempo fa, diceva che non dovresti vivere con le finestre rotte , perché alla gente non importa se qualcuno si rompe ... Il codice è lo stesso, a tutti importa di essere il primo a fare qualcosa di brutto ma veloce , ma nessuno si preoccuperà di un codice infernale , con molti bug e design e stile molto scadenti.


1

Seguo la pratica di Test-Code-Test invece di Code-test-code-test. Questo mi aiuta a pensare ai casi d'uso e ad inquadrare adeguatamente la logica


1

Utilizzare strumenti di ispezione del codice come ReSharper o IDE come IntelliJ IDEA che avvisano di molti bug di copia e incolla e altri, ad esempio sottolineando le variabili che "vengono scritte, ma mai lette". Mi ha fatto risparmiare un sacco di tempo.


1

Sorprendentemente, i seguenti tre punti molto importanti non sono ancora stati menzionati:

  • Usa affermazioni liberamente. La domanda che dovresti sempre porti non è "dovrei affermarlo?" ma "c'è qualcosa che ho dimenticato di affermare?"

  • Optare per l'immutabilità. (Usa il finale / in sola lettura liberamente.) Quanto meno sei mutevole, meno cose possono andare storte.

  • Non ottimizzare prematuramente. Molti programmatori vengono monitorati a livello di problemi di prestazioni, causando la convoluzione inutile del loro codice e la loro codardia nei loro progetti senza nemmeno sapere in anticipo se le prestazioni saranno un problema. Innanzitutto, crea il tuo prodotto software in modo accademico, ignorando le prestazioni; quindi, vedere se funziona male; (Probabilmente non lo farà.) Se ci sono problemi di prestazioni, vai a trovare uno o due posti in cui puoi fornire ottimizzazioni algoritmiche gradevoli e formali che consentano al tuo prodotto di soddisfare i suoi requisiti di prestazioni invece di modificare e hackerare l'intera base di codice per spremere i cicli qua e là.

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.