Bug fastidiosi - inesistenti?

1

Introduzione molto breve (questa è una domanda piuttosto contestualizzata):

Sono un programmatore di diciassette anni che fa alcuni progetti, di solito compensando circa 20 file di 200 righe ciascuno. Di solito non programma programmi di livello molto basso, più di alto livello con API incluse della batteria come Python + pygame e Lua + WoW API. Tuttavia ho scritto un bel po 'di codice anche nei livelli più bassi del computer (principalmente C / C ++).

Ora ho letto un sacco di discussioni con programmatori e un argomento di ritorno comune è prevenire bug fastidiosi , ad esempio in "riutilizzo di nomi di variabili". Ho sempre annuito e ho pensato che fosse un argomento valido, ma proprio ora mi chiedevo, quanto è valido?

Per essere onesti, dopo aver pensato per un po ', ho pensato di non avere idea di cosa intendessero con fastidiosi bug . Tutti noi abbiamo sentito storie su fenomenali bug impossibili da debug, tutti abbiamo passato serate inutili su quel fastidioso bug, ma a parte alcuni casi non sono mai stato impegnato con un bug relativo alla programmazione per più di qualche ora.

Anche se, d'altra parte, i progetti su cui lavoro (ed) non sono enormi 10 milioni di progetti di linea come il kernel di Linux, e sono piuttosto semplici ... script. Ne ho una buona comprensione (o almeno la mia parte nelle collaborazioni) e non sono molto inclini agli errori.

Quindi mi chiedo, questi fastidiosi bug si verificano in modo esponenziale più come la quantità di codice aumenta, o ...?

    
posta orlp 22.10.2011 - 04:08
fonte

4 risposte

7

I bug fastidiosi aumentano in caso di aumento del numero di righe di codice.

  1. Se non fai un buon OOD e definisci molte astrazioni (il che è molto possibile ma non praticato da tutti), l'aumento della quantità di codice aumenterà la complessità di quel codice. Ogni volta che lo modifichi, dovrai ricordare tutto ciò che hai fatto prima E ora avrai più informazioni da memorizzare nella tua testa.
  2. L'aumento della quantità di codice significa che alcune parti del tuo programma potrebbero non essere toccate per mesi. Tra qualche anno potreste persino rendervi conto che alcuni prodotti funzionano con codice che non è stato toccato da nessuno da anni. Ma se devi modificarlo, devi ricordare (o capire) come funziona.
  3. Quando la LOC sale, si inizia ad avere più di una persona in un progetto. Ora l'altra persona ha bisogno di ricordare cosa stava pensando l'autore originale. Se non lo fai, forse chiamerai una funzione che ha alcune cattive concezioni. Prova a ricordare qualcosa che non hai scritto in primo luogo.
  4. Con l'aumento della base di codice e le funzionalità della tua app, inizi a utilizzare più API di terze parti (beh, dovresti comunque). Dato che sempre più persone dipendono da elementi costitutivi di terze parti, a volte i bug emergeranno perché l'integrazione tra il tuo codice e il loro potrebbe non essere sempre fluida. Forse la loro parte è bacata, forse hai frainteso la documentazione.

Tutte le buone pratiche, che hai letto e annuendo, sono lì per rimuovere l'elemento della memoria il più possibile dall'equazione. Quando il codice è chiaro da leggere e capire. Quando scorre logicamente e non ci sono significati e scorciatoie segrete / nascoste, ci sono meno possibilità di rovinare un'applicazione esistente.

Per fare un esempio, nel mio primo lavoro, quando stavo lavorando al codice che stava creando archivi su nastro, ho trovato una riga di codice alla fine di una delle funzioni, ReadTapeDirectory (). Sapevo cosa ha fatto quel metodo, ho lavorato con esso prima e ho pensato che fosse una copia / incolla che qualcuno ha dimenticato di rimuovere. Ho cancellato la linea e alcune settimane dopo, quando qualcuno è andato a lavorare con i nastri, ci siamo resi conto che tutti gli archivi erano completamente vuoti. Vieni a scoprire che ReadTapeDirectory () stava spostando la posizione del nastro nel punto giusto, e senza di esso l'intero processo di archiviazione era rotto. Ovviamente, se uno sviluppatore precedente seguiva consigli sulle buone pratiche che si leggevano più e più volte, avrebbe chiamato la funzione qualcosa come ResetTapePosition () e quindi nello spirito del principio DRY ha rifatto la lettura di ReadTapeDirectory () in parti più piccole. Quando inizi a collaborare con altre persone, rimarrai sorpreso dal numero di questi esempi (denominazione non chiara con correzione semplice, non nastri danneggiati) in cui ti imbatterai quotidianamente.

Quindi è così importante assicurarsi di utilizzare sempre le variabili una sola volta? No non lo è. Ma non ci sono molte altre buone pratiche (beh ... alcune sono in realtà un po 'importanti). Ma il mio punto è che si sviluppa una capacità di scrivere codice chiaro e quando si mettono insieme tutte queste cose, fa un'enorme differenza tra codice leggibile / estensibile e una lattina di worm in cui ci vogliono 3 giorni solo per aggiungere una voce di menu. E alla fine della giornata, tutte le buone pratiche nel mondo non eliminano ancora quei fastidiosi bug, minimizzano le possibilità che si verifichino.

    
risposta data 22.10.2011 - 04:54
fonte
7

Nella mia esperienza, ho sicuramente incontrato diversi bug che hanno richiesto settimane o addirittura mesi per arrivare fino in fondo. Alcuni tipi di bug compaiono solo in modalità debug contro release o 32bit vs 64 bit, mentre altri si basano su condizioni di gara multi-threading che appaiono solo in tempi apparentemente casuali. Direi che generalmente la mancanza di sicurezza della memoria, la concorrenza della memoria condivisa e lo stato mutevole condiviso pervasivo sono i principali responsabili. Un gran numero di componenti interagenti, specialmente di terze parti, peggiora anche il problema. Ecco perché le persone sono così religiose riguardo ai cosiddetti progetti software "disaccoppiati" e "componibili": se ogni componente funziona e può essere testato indipendentemente, il numero di possibili interazioni (e quindi il numero di possibili bug) aumenta in modo lineare con la dimensione del software, piuttosto che esponenzialmente.

Uno dei miei preferiti era un bug che appariva solo ad alcuni utenti, solo nelle versioni rilasciate del software: occasionalmente quando si scorre il mouse in uno specifico componente della griglia, ci sarebbe un misterioso "ArithmeticOverflowException" non gestito.

L'abbiamo capito mesi dopo: gli sviluppatori eseguivano / code / eseguono il debug del programma in modalità 32 bit, per fornire edit-and-continue in Visual Studio. Il bug si sarebbe verificato solo in modalità 64 bit, e solo quando qualcuno ha fatto scorrere il mouse estremamente velocemente su quella particolare griglia ...

Si è scoperto che il componente di griglia (di terze parti) stava esaminando un certo messaggio di finestra per gestire gli eventi della rotella di scorrimento e il numero intero a 64 bit in uno a 32 bit perché la maggior parte dei messaggi di finestra non memorizzava nulla importante nei 32 bit superiori. Se un utente scorreva molto velocemente, per evitare di sovraccaricare la pompa dei messaggi con molti singoli messaggi "SCROLL", Windows "caricava" i messaggi e utilizzava parte dei 32 bit superiori del messaggio per registrare il numero di clic della rotella di scorrimento per batch. Lanciarlo su un numero intero a 32 bit ha comportato un overflow. Dato che si trattava di un componente di terze parti, abbiamo scoperto la causa solo mesi dopo, quando eseguivamo un po 'di hacker di pompe di messaggi e colpendo la stessa eccezione.

Quindi questo è un bug della mia esperienza che si qualifica sicuramente come fastidioso.

    
risposta data 22.10.2011 - 04:41
fonte
3

Quindi mi chiedo, questi fastidiosi bug si verificano in modo esponenziale più come la quantità di codice aumenta, o ...?

Direi che il numero di bug "fastidiosi" (heisenbugs, ecc.) ha effettivamente una certa correlazione con la quantità di codice. Ma credo che KLOC sia solo una metrica approssimativa per ciò che è realmente in discussione, e cioè la complessità e le interazioni. Più variabili hai, maggiore è il tuo stato e più punti di diramazione hai, più complesso è il tuo codice. Più parti del tuo codice interagiscono con altre parti o interagiscono con sistemi esterni, più le cose sono complesse. Le cose più complesse sono, più opportunità hai per quegli "strani" bug da intrufolarsi.

Quando si mischia la concorrenza, lo stato condiviso e un sistema esterno o due, anche un programma abbastanza breve può essere molto complesso e può manifestare un comportamento difficile da diagnosticare.

Leggi su cose come Cyclomatic Complexity e correttezza del software per ulteriori informazioni su questo argomento.

    
risposta data 22.10.2011 - 04:27
fonte
0

Direi che non è tanto la dimensione del codice quanto il numero di programmatori che ci lavorano. Il codice che ho scritto di recente è quasi sempre abbastanza facile da eseguire il debug. Sono le interazioni tra il codice che hai scritto e il codice che non hai causato la maggior parte dei problemi. Ecco perché così tante best practice si concentrano sul rendere il tuo codice semplice e robusto, così che altri programmatori (o te stesso tra un anno) non lo utilizzeranno per errore.

    
risposta data 22.10.2011 - 17:19
fonte

Leggi altre domande sui tag