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

13

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

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

  • A volte ho problemi simili quando sono troppo stanco / assonnato per eseguire correttamente il lavoro e per avere una visione generale della parte del codice su cui stavo lavorando. Qui, il problema sembra essere di alcuni giorni o settimane, e non è collegato al focus del mio collega.
  • Posso anche immaginare che questo problema si presenti in un progetto molto grande, gestito molto male , in cui i compagni di squadra non hanno idea di chi fa cosa e quale effetto sul lavoro degli altri può avere un cambiamento loro stanno facendo. Questo non è il caso nemmeno qui: è un progetto piuttosto piccolo con un solo sviluppatore.
  • Può anche essere un problema con la base di codice precedente, con scarsa manutenzione e mai documentata , in cui gli unici sviluppatori che possono davvero immaginare le conseguenze di un cambiamento hanno lasciato la società anni fa. Qui, il progetto è appena iniziato e lo sviluppatore non usa la base di codice di nessuno.

Quindi quale può essere la causa di tale problema su un nuovo codebase di piccole dimensioni scritto da un singolo sviluppatore che rimane concentrato sul suo lavoro ?

Che cosa può aiutarti?

  • Test di unità (non ce ne sono)?
  • Architettura corretta (sono abbastanza sicuro che il codebase non abbia alcuna architettura e sia stato scritto senza pensieri preliminari), richiedendo l'intero refactoring?
  • Accoppia programmazione?
  • Qualcos'altro?
posta Arseni Mourzenko 09.12.2011 - 18:39
fonte

10 risposte

37

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

    
risposta data 09.12.2011 - 18:49
fonte
13

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

Ad esempio, ultimamente stavo lavorando su una classe che implementa un componente GUI nella mia applicazione. Per settimane sono stati segnalati nuovi bug, li ho sistemati e nuovi bug sono apparsi da qualche altra parte. Mi sono reso conto che quella classe era diventata troppo grande, faceva 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 eseguito un strong refactoring: suddividere il componente in una classe principale più classi MVC (tre classi aggiuntive). In questo modo ho dovuto dividere il codice in parti più piccole e più semplici e definire interfacce più chiare. Dopo il refactoring sono stati risolti tutti i bug e non sono stati segnalati nuovi bug.

    
risposta data 09.12.2011 - 18:54
fonte
7

È facile per un bug mascherarne un altro. Supponiamo che l'errore "A" risulti nella chiamata alla funzione sbagliata per gestire l'input. Quando il bug "A" è corretto, improvvisamente viene chiamata la funzione corretta, che non è mai stata testata.

    
risposta data 09.12.2011 - 18:52
fonte
5

Bene, la causa immediata sono due torti che fanno un diritto, o almeno che fanno un non-ovviamente-sbagliato. Una parte del codice compensa il comportamento scorretto dell'altra parte. Oppure 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 basata su zero per una certa quantità, quindi funzionano insieme correttamente, ma C ne usa una, potresti "aggiustare" A per lavorare con C e poi 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. Fungono anche da specifica degli input appropriati. Per esempio. una buona serie di test renderebbe chiaro che le funzioni A e B si aspettavano l'input basato su 0 e basato su C 1.

Ottenere le specifiche corrette può anche essere fatto in altri modi, dai documenti ufficiali ai buoni commenti nel codice, a seconda delle esigenze del progetto. La chiave sta nella comprensione di ciò che ciascun componente si aspetta e di ciò che promette, quindi puoi trovare incongruenze.

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

Spero che questo aiuti.

    
risposta data 09.12.2011 - 18:56
fonte
5

Accoppiamento stretto, mancanza di test, questi sono probabilmente i colpevoli più comuni. Fondamentalmente il problema comune è solo degli standard e delle procedure scadenti. Un altro è solo codice errato che riesce a essere fortunato per un po 'con un comportamento corretto. Considera memcpy bug di Linus Torvalds in cui modifica l'implementazione dei bug esposti (non causati) nei client che hanno utilizzato memcpy in luoghi in cui avrebbero dovuto utilizzare memmove con origine e destinazione sovrapposte.

    
risposta data 15.01.2016 - 15:47
fonte
4

Sembra che questi "nuovi" bug non siano in realtà bug "nuovi". Non erano solo un problema, fino a quando l'altro codice che è stato rotto, è stato effettivamente risolto. In altre parole, il tuo collega non si rende conto che in realtà ha avuto due bug per tutto il tempo. Se il codice che non sta dimostrando di essere rotto non è stato rotto, non sarebbe fallito, una volta che l'altro peice di codice è stato effettivamente corretto.

In entrambi i casi potrebbe essere utile un regime di test automatizzato migliore. Sembra che il tuo collega abbia bisogno di testare l'attuale base di codice. Nel futuro i test di regressione verificheranno che il codice esistente continui a funzionare.

    
risposta data 09.12.2011 - 21:26
fonte
0

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

    
risposta data 09.12.2011 - 18:51
fonte
0

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

Anche le specifiche incoerenti si verificano. Quindi è quasi garantito che la correzione di un bug ne creerà un'altra (eccitante quando quella particolare parte della specifica non viene esercitata fino a più tardi nel progetto).

    
risposta data 09.12.2011 - 19:30
fonte
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 che modifichi per far funzionare la nuova funzione. Anche se non modifichi alcun codice, aggiungi funzionalità a esistenti, potrebbe rompere qualcos'altro.

Quindi in pratica hai quasi risposto a te stesso:

  • accoppiamento lento
  • 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 accoppiata è ottima, ma non sempre "disponibile" (tempo, denaro, entrambi ..). Tuttavia, le revisioni del codice (ad esempio dei colleghi) una volta un giorno / settimana / un insieme di commit possono essere di grande aiuto, specialmente 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à) :)).

    
risposta data 09.12.2011 - 22:18
fonte
0

Diciamo che lo sviluppatore A ha 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 è basato sul codice di A facendo esattamente ciò che è stato specificato per fare, e il codice di B non funziona. B indaga, trova il comportamento scorretto nel codice di A e lo risolve.

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

Ho avuto un'altra situazione: alcuni codice si sono comportati male e hanno fermato completamente una funzione dal lavorare in qualche situazione X. Così ho cambiato il comportamento scorretto e ho fatto funzionare la funzione. Lo sfortunato effetto collaterale è stato che l'intera caratteristica ha avuto problemi significativi nella situazione X e ha fallito dappertutto - questo era stato completamente sconosciuto a nessuno perché la situazione non era mai sorto prima. Bene, è difficile.

    
risposta data 04.02.2018 - 00:10
fonte

Leggi altre domande sui tag