Perché le variabili non utilizzate sono un problema?

8

Un giorno stavo pulendo gli avvisi di variabili inutilizzati e ho iniziato a riflettere su quale fosse esattamente il problema?

In effetti, alcuni di essi aiutano anche nel debug (ad esempio, ispezionano i dettagli delle eccezioni o controllano il valore restituito prima di restituirli).

Non sono riuscito a trovare il rischio reale reale di averli ...

Esempi

Non intendo linee che richiedono tempo all'attenzione di altri programmatori, come ad esempio:

int abc = 7;

Questa è una evidente ridondanza e distrazione. Voglio dire cose del tipo:

try {
    SomeMethod();
} catch (SomeException e) {
    // here e is unused, but during debug we can inspect exception details
    DoSomethingAboutIt();
}
    
posta Tar 18.01.2017 - 16:57
fonte

7 risposte

4

In base al frame che hai fornito, è difficile discutere quelle di per sé:

try {
    SomeMethod();
} catch (SomeException e) {
// here e is unused, but during debug we can inspect exception details
DoSomethingAboutIt();
}

Prendi questo ad esempio. Stai rilevando un'eccezione e (forse) hai un codice che tratta l'eccezione in modo corretto. Il fatto che non si stia utilizzando l'istanza effettiva dell'eccezione non nuoce, né al flusso di codice né alla comprensibilità.

Ma ciò che mi fa pensare è quando scrivi sulla legittimazione di »variabili inutilizzate«

In fact, some of them even help in debugging

Questo non è lo scopo della scrittura del codice: dover eseguire il debug in un secondo momento. Per evitare malintesi, devo dire che, lo so bene, spesso devi correggere il tuo codice; e a volte debug è la soluzione. Ma non dovrebbe essere il primo, quello che ti viene in mente, quando scrivi il codice, che lasci "punti di ancoraggio", il cui unico scopo è rendere il debug più facile.

SomeClass Func() {
    // ...stuff...
    var ret = FinalComputationResult(thing, foo, bar);
    // ret is unused, but while debugging allows checking return value.
    return ret;
}

Qui dipende da quanto è complesso stuff e da come è correlato al valore, che viene restituito.

Come "regola d'oro", direi quanto segue:

If it helps understanding the purpose of the code, it is okay to incease redundancy in your code

o per dirla diversamente:

Write your code as redundancy free as is necessary to understand later easily, what the code is doing

Il risultato è: La maggior parte delle volte, dovresti rimuovere "debug" -variabili .

    
risposta data 19.01.2017 - 09:47
fonte
19

Il più grande problema è chiarezza . Se il tuo codice contiene un sacco di spazzatura estranea e sto mantenendo il tuo codice, devo capire cosa fa tutto.

Questa variabile è mai usata per qualcosa? Forse esegui operazioni su di esso, ma non usi mai il suo valore per qualcosa. Semplicemente incrementare una variabile non significa che la variabile abbia uno scopo se non la leggi mai (restituisci, inserisci in un'altra espressione, et al).

Tuttavia: se una variabile ha uno scopo ed è denominata in modo appropriato , non toglie il codice nel suo complesso.

Dati gli esempi nella tua domanda aggiornata e alcuni altri ho pensato a:

  • Avere una funzione che chiama un'altra funzione, memorizza il risultato, lo registra, quindi lo restituisce è piuttosto breve e chiaro.

  • Suddividere un'istruzione con più espressioni in più istruzioni (ad esempio suddividere un calcolo lungo e complesso in più istruzioni con più variabili intermedie) può rendere il codice più chiaro pur essendo più dettagliato. Con meno informazioni da elaborare alla volta, il cervello può più facilmente ingolfare quello che sta succedendo.

  • Non usare le eccezioni è perfettamente corretto: la maggior parte delle lingue richiede di specificare l'eccezione che viene rilevata, incluso fornire un nome di variabile da utilizzare nel blocco catch . Non c'è modo di aggirare questo in molte lingue popolari e i programmatori sono abituati.

Se ho bisogno di dedicare del tempo a capire quali elementi del codice hanno uno scopo e che stanno solo perdendo tempo, la mia produttività diminuisce. Tuttavia, se il codice è abbastanza conciso e le variabili sono ben definite anche se all'inizio sembrano estranee, ciò riduce il rischio di sprecare tempo inutile per rivedere il codice per comprenderlo.

Il codice errato con variabili estranee, blocchi vuoti e codice morto è un modo in cui gli sviluppatori ottengono una cattiva reputazione in ufficio: "Stavo correggendo un bug nel codice di Snowman. Ho passato due ore a capire cosa stava facendo quella funzione, e trenta secondi che riparano il bug! Snowman è terribile in programmazione! " Ma se il codice serve a uno scopo ed è scritto in modo chiaro, va perfettamente bene.

    
risposta data 18.01.2017 - 17:05
fonte
5

Le variabili non utilizzate che non hanno uno scopo ovvio sono un odore di codice a mio avviso. Nella migliore delle ipotesi, possono essere una distrazione - aggiungono al rumore generale nel modulo.

Il caso peggiore è che i successivi programmatori trascorrono del tempo a capire cosa dovrebbe fare e si chiedono se il codice è completo. Fai un favore a te stesso (e a tutti gli altri) e sbarazzati.

    
risposta data 18.01.2017 - 17:10
fonte
3

Le variabili non utilizzate rendono poco chiaro l' intento del tuo codice. Questo è male perché nonostante le apparenze, il codice è scritto principalmente per persone da leggere, non per computer .

Altri hanno già sottolineato che costruire un valore e non usarlo confonde le altre persone che devono leggere e lavorare con il tuo codice. Tuttavia, a mio avviso, il pericolo maggiore è quello di te .

Una variabile non utilizzata potrebbe essere intenzionale o potrebbe essere una svista che punta a un difetto. Ad esempio, potresti aver digitato in modo errato un nome e memorizzato un valore in un posto quando pensavi di averlo memorizzato in un altro. Il programma risultante potrebbe funzionare bene ma dare il risultato sbagliato.

L'analisi del flusso di dati può aiutarti a trovare tali errori e molti altri. Quindi paga scrivere il tuo codice in modo tale che tutto un analizzatore di flusso di dati indica un'anomalia, in effetti è un bug. L'assistenza automatica nella prevenzione dei bug è inestimabile; molte persone pensano "Oh, non ho bisogno di assistenza, non sarei mai così incurante", ma finora tutti quelli che ho incontrato pensavano che fosse sbagliato.

    
risposta data 19.01.2017 - 08:06
fonte
2

C'è uno stile di codifica che implica l'assegnazione deliberata di qualcosa che era (o potrebbe diventare) di interesse per una variabile allo scopo specifico di guardarlo facilmente in un debugger. Questo è particolarmente utile per il codice che assomiglia a:

return foo(bar(), baz(wot(12), wombat(&badger)));

Anche con nomi leggermente migliori per le funzioni, può essere più facile capire cosa non va nella chiamata a foo quando viene scritto come:

auto awombat = wombat(&badger);
auto awot = wot(12);
auto abaz = baz(awot, abadger);
auto abar = bar();
auto afoo = foo(abar, abaz);
return afoo;

Devo ancora lavorare con persone che lo praticano come configurazione predefinita, ma riscrivono un pezzo di codice che si rifiuta ostinatamente di avere senso in modulo di assegnazione singola può facilitare l'elaborazione di ciò che accade nel debugger. Abbiamo sempre ripristinato il codice in formato "carino" compatto, ma mi chiedo se sia stato un errore.

L'alternativa è camminare su e giù per lo stack e sperare di non andare troppo lontano, o di usare (i distruttivi rari) debugger reversibili.

Non è una strategia popolare, ma siccome mi ha aiutato a superare alcuni bug assurdi, non penso che dovrebbe essere cancellato come intrinsecamente cattivo.

    
risposta data 18.01.2017 - 22:55
fonte
1

Per le persone che includono il codice di test unitario negli stessi progetti o moduli del loro codice "reale", un campo non utilizzato, come un metodo oggetto, è un segnale strong che i tuoi test dell'unità non sono " t testare tutto Ciò aumenta le possibilità che uno sviluppatore proverà a utilizzare quel campo o metodo attualmente inutilizzato e si imbattesse in un errore che non era stato rilevato fino a quel momento.

Una variabile inutilizzata in una subroutine o un metodo un po 'non banale può indicare che il programmatore intendeva usarlo, ma sta usando un'altra variabile per errore (per esempio, dopo aver ripulito dopo un'operazione di copia-incolla) .

Una variabile inutilizzata in una subroutine più banale è probabilmente una scia non necessaria, come hanno risposto altre persone. Occasionalmente, viene utilizzato in una istruzione breadcrumb attualmente commentata:

SomeObject tmp = someMethod();
// printDebugInfoAbout (tmp);

... è chiaro per il bulbo oculare che è usato lì, e solo lì (cioè someMethod ha un importante effetto collaterale), ma l'IDE non lo sa, e rimuovere quella variabile è più un problema che ne vale la pena . Io uso provvisoriamente i soppressori di avvertimento in questi casi.

    
risposta data 18.01.2017 - 21:32
fonte
0

È facile scrivere codice per mescolare due variabili. Calcoli una variabile B, ma poi usa una variabile A creata in precedenza.

Quindi una possibile ragione per una variabile non utilizzata è che c'è un errore nel codice. Questo è il motivo per cui il compilatore ti avverte. Se "non fai" le variabili inutilizzate, è addirittura un regalo scarno.

Quando viene visualizzato un avviso di questo tipo, è necessario verificare il codice e correggerlo o rimuovere la variabile in questione. Se non lo rimuovi, smetterai di prestare attenzione a questi avvertimenti e potresti anche disabilitarli completamente. Ma poi alla fine perderai un pomeriggio facendo il debug del codice a causa di un errore stupido.

    
risposta data 19.01.2017 - 22:28
fonte