Quale può essere la causa della comparsa di nuovi bug da qualche altra parte quando viene risolto un bug noto?


14

Durante una discussione, uno dei miei colleghi ha detto che ha qualche difficoltà con il suo progetto attuale mentre cerca di risolvere i bug. "Quando risolvo un bug, qualcos'altro smette di funzionare altrove", ha detto.

Ho iniziato a pensare a come ciò potesse accadere, ma non riesco a capirlo.

  • A volte ho problemi simili quando sono troppo stanco / assonnato per fare il lavoro correttamente e avere una visione d'insieme della parte del codice su cui stavo lavorando. Qui, il problema sembra essere per alcuni giorni o settimane e non è collegato al focus del mio collega.
  • Posso anche immaginare questo problema derivante da un progetto molto grande, gestito in modo molto cattivo , in cui i compagni di squadra non hanno idea di chi fa cosa e quali effetti sul lavoro degli altri possano avere un cambiamento che stanno facendo. Questo non è nemmeno il caso qui: è un progetto piuttosto piccolo con un solo sviluppatore.
  • Può anche essere un problema con una base di codice vecchia, mal gestita e mai documentata , in cui gli unici sviluppatori che possono davvero immaginare le conseguenze di un cambiamento avevano lasciato l'azienda anni fa. Qui, il progetto è appena iniziato e lo sviluppatore non utilizza la base di codici di nessuno.

Quindi quale può essere la causa di tale problema su una base di codice fresca e di piccole dimensioni scritta da un singolo sviluppatore che rimane concentrato sul suo lavoro ?

Cosa può aiutare?

  • Test unitari (non ce ne sono)?
  • Architettura corretta (sono abbastanza sicuro che la base di codice non abbia alcuna architettura e sia stata scritta senza pensiero preliminare), richiedendo l'intero refactoring?
  • Accoppia la programmazione?
  • Qualcos'altro?

14
Ah, il buon vecchio modello di progettazione "ondate di fallimento" a cascata. :-)
Brian Knoblauch,

1
L'ho paragonato a una bolla in un foglio di contatto. Spingilo verso il basso, si apre altrove. Migliore è la mia codifica, meno la vedo
johnc il

2
In una nota a margine, avevo esattamente questo su un sistema incorporato. Ho aggiunto una chiamata di funzione per risolvere un problema. Quella chiamata di funzione era troppo per lo stack (il microcontrollore non aveva alcun rilevamento dello stackoverflow) e quindi scriveva cose casuali altrove nella memoria, che ovviamente rompeva qualcosa di completamente diverso. Quindi, questa cosa PUO 'succedere su una piccola base di codice con un solo sviluppatore e una buona architettura.
risingDarkness

... ed è stato un incubo il debug.
risingDarkness

Risposte:


38

Non ha molto a che fare con focus, dimensioni del progetto, documentazione o altri problemi di processo. Problemi del genere di solito sono il risultato di un eccessivo accoppiamento nella progettazione, il che rende molto difficile isolare le modifiche.


15
questo combinato con test di regressione poveri o assenti
Ryathal

3
È vero, @Ryathal, anche se i test di regressione non impediranno questo tipo di bug, ti informo prima di loro.
Karl Bielefeldt,

Se ne conosci abbastanza presto (ad esempio pochi minuti dopo aver creato i bug), puoi annullare le modifiche e fingere in modo efficace che non siano mai avvenute.
bdsl

14

Una delle cause può essere l' accoppiamento stretto tra i componenti del software: se non ci sono interfacce semplici e ben definite tra i componenti, anche una piccola modifica in una parte del codice può introdurre effetti collaterali imprevisti in altre parti del codice.

Ad esempio, ultimamente stavo lavorando a una classe che implementa un componente GUI nella mia applicazione. Per settimane sono stati segnalati nuovi bug, li ho riparati e nuovi bug sono apparsi altrove. Mi sono reso conto che quella classe era diventata troppo grande, stava facendo troppe cose e molti metodi dipendevano da altri metodi che venivano chiamati nella giusta sequenza per funzionare correttamente.

Invece di correggere gli ultimi tre bug, ho fatto un forte refactoring: dividere il componente in una classe principale più le classi MVC (tre classi aggiuntive). In questo modo ho dovuto dividere il codice in pezzi più piccoli e più semplici e definire interfacce più chiare. Dopo il refactoring tutti i bug sono stati risolti e non sono stati segnalati nuovi bug.


7

È facile per un bug mascherarne un altro. Supponiamo che il bug "A" induca a chiamare una funzione errata per gestire l'input. Quando il bug "A" viene corretto, improvvisamente viene chiamata la funzione corretta, che non è mai stata testata.


5

Bene, la causa immediata è che due errori fanno un diritto, o almeno fanno un non-ovviamente-sbagliato. Una parte del codice compensa il comportamento errato dell'altra parte. O se la prima parte non è "sbagliata" in quanto tale, c'è un accordo non scritto tra le due parti che viene violato quando il codice viene modificato.

Ad esempio, supponiamo che le funzioni A e B utilizzino una convenzione a base zero per una certa quantità, quindi funzionano correttamente insieme, ma C ne usa una, potresti "correggere" A per lavorare con C e quindi scoprire un problema con B.

Il problema più profondo è la mancanza di una verifica indipendente della correttezza delle singole parti. I test unitari sono progettati per risolvere questo problema. Agiscono anche come una specifica degli input corretti. Ad esempio, una buona serie di test chiarirebbe che le funzioni A e B prevedevano input basati su 0 e basati su C 1.

È possibile ottenere le specifiche giuste anche in altri modi, dai documenti ufficiali ai buoni commenti nel codice, a seconda delle esigenze del progetto. La chiave è capire cosa si aspetta ogni componente e cosa promette, in modo da poter trovare incoerenze.

Una buona architettura aiuta con il problema di comprendere il codice, rendendolo più semplice. La programmazione delle coppie è utile per evitare bug in primo luogo o per trovarli più rapidamente.

Spero che sia di aiuto.


5

Accoppiamento stretto, mancanza di test, questi sono probabilmente i colpevoli più comuni. Fondamentalmente il problema comune sono solo standard e procedure scadenti. Un altro è solo un codice errato che riesce a essere fortunato per un po 'con un comportamento corretto. Prendi in considerazione i memcpybug di Linus Torvalds in cui modificando la sua implementazione sono stati rilevati (non causati) bug nei client utilizzati memcpyin luoghi in cui avrebbero dovuto essere utilizzati memmovecon la sorgente e la destinazione sovrapposte.


4

Sembra che questi "nuovi" bug non siano in realtà "nuovi" bug. Non sono stati un problema, fino a quando l'altro codice che è stato rotto, è stato effettivamente risolto. In altre parole, il tuo collega non si rende conto di aver effettivamente avuto due bug per tutto il tempo. Se il codice che non si sta dimostrando rotto non fosse rotto, non avrebbe avuto esito negativo, una volta che l'altra parte di codice fosse stata effettivamente riparata.

In entrambi i casi potrebbe essere utile un migliore regime di test automatizzato. Sembra che il tuo collega debba testare l'unità della base di codice corrente. In futuro i test di regressione verificheranno che il codice esistente continui a funzionare.


0

Migliora l' ampiezza del tuo regime di test automatizzato. Eseguire SEMPRE il set completo di test prima di eseguire le modifiche al codice. In questo modo, rileverai l'effetto dannoso delle tue modifiche.


0

L'ho appena riscontrato quando un test non era corretto. Il test ha verificato un determinato stato di autorizzazione che era! Corretto. Ho aggiornato il codice ed eseguito il test delle autorizzazioni. Ha funzionato. Quindi ho eseguito tutti i test. Tutti gli altri test che hanno utilizzato la risorsa controllata non sono riusciti. Ho corretto il test e il controllo dei permessi, ma all'inizio c'era un po 'di panico.

Si verificano anche specifiche incoerenti. Quindi è quasi garantito che la correzione di un bug ne creerà un altro (eccitante quando quella parte specifica non verrà esercitata fino a tardi nel progetto).


0

Immagina di avere un prodotto completo. Quindi aggiungi qualcosa di nuovo, tutto sembra a posto, ma hai rotto qualcos'altro, che dipende da un codice modificato per far funzionare la nuova funzionalità. Anche se non modifichi alcun codice, aggiungi solo funzionalità a quelle esistenti, potrebbe rompere qualcos'altro.

Quindi praticamente ti sei quasi risposto:

  • accoppiamento lasco
  • mancanza di test

Basta imparare ad adattare il principio TDD (almeno per le nuove funzionalità) e provare a testare ogni possibile stato che può accadere.

La programmazione delle coppie è ottima, ma non sempre "disponibile" (tempo, denaro, entrambi ..). Ma anche le revisioni del codice (ad esempio da parte dei colleghi) una volta al giorno / settimana / serie di commit saranno di grande aiuto, soprattutto quando la revisione include la suite di test. (Trovo difficile non scrivere bug per testare le suite ... a volte devo testare il test internamente (controllo di integrità) :)).


0

Supponiamo che lo sviluppatore A abbia scritto del codice con un bug. Il codice non è esattamente quello che dovrebbe fare, ma qualcosa di leggermente diverso. Lo sviluppatore B ha scritto un codice che si basava sul codice di A facendo esattamente ciò che è previsto e il codice di B non funziona. B indaga, trova il comportamento errato nel codice A e lo risolve.

Nel frattempo il codice dello sviluppatore C funzionava correttamente solo perché si basava sul comportamento scorretto del codice A. Il codice di A ora è corretto. E il codice di C smette di funzionare. Ciò significa che quando si corregge il codice, è necessario controllare attentamente chi utilizza questo codice e come cambierà il loro comportamento con il codice fisso.

Ho avuto un'altra situazione: alcuni codici si sono comportati male e hanno impedito che una funzione funzionasse completamente in alcune situazioni X. Quindi ho cambiato il comportamento scorretto e ho fatto funzionare la funzione. Lo sfortunato effetto collaterale era che l'intera caratteristica aveva problemi significativi nella situazione X e falliva dappertutto - questo era completamente sconosciuto a nessuno perché la situazione non era mai sorta prima. Bene, è difficile.

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.