Warum sind nicht verwendete Variablen ein solches Problem?

9

Ich habe eines Tages Warnungen zu nicht verwendeten Variablen bereinigt und angefangen zu überlegen, was genau das Problem an ihnen ist.

Einige von ihnen helfen sogar beim Debuggen (z. B. Ausnahmedetails überprüfen oder den Rückgabewert vor der Rückgabe überprüfen).

Ich konnte kein wirkliches Risiko finden, sie zu haben.

Beispiele

Ich meine nicht Zeilen, die die Aufmerksamkeit anderer Programmierer in Anspruch nehmen, wie zum Beispiel:

int abc = 7;

Das ist eine offensichtliche Redundanz und Ablenkung. Ich meine Sachen wie:

try {
    SomeMethod();
} catch (SomeException e) {
    // here e is unused, but during debug we can inspect exception details
    DoSomethingAboutIt();
}
Teer
quelle
31
Sie meinen etwas anderes als die Tatsache, dass der Programmierer, der nach Ihnen kommt, Zeit damit verbringen muss, herauszufinden, warum sie dort sind?
Robert Harvey
1
Ihre Beispiele sind harmlos, aber ich habe noch nie solche Fälle gesehen, die als "nicht verwendete Variablen" bezeichnet werden. Woher kommen deine Warnungen?
Jacob Raihle
9
Nun, retist nicht unbenutzt.
Robert Harvey
4
Sie haben " Ich meine Sachen wie catch (SomeException e) " geschrieben - Sie tun so, als gäbe es andere, ähnliche Fälle. Erleuchte mich, welche? Ich frage, weil ich in C # oder C ++ Probleme habe, eine andere Situation für Ihren Fall zu finden.
Doc Brown

Antworten:

4

Nach dem von Ihnen angegebenen Rahmen ist es schwierig, gegen diese Variablen an sich zu argumentieren :

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

Nehmen Sie das zum Beispiel. Sie fangen eine Ausnahme ab und haben (möglicherweise) Code, der die Ausnahme ordnungsgemäß behandelt. Die Tatsache, dass Sie die tatsächliche Instanz der Ausnahme nicht verwenden, schadet weder dem Codefluss noch der Verständlichkeit.

Aber was mich zum Nachdenken bringt, ist, wenn Sie über die Legitimation von »nicht verwendeten Variablen« schreiben.

Einige von ihnen helfen sogar beim Debuggen

Das ist nicht der Zweck des Schreibens von Code: Sie müssen ihn später debuggen. Um Missverständnisse zu vermeiden, muss ich sagen, dass ich bin mir durchaus bewusst, dass oft müssen Sie reparieren Ihren Code; und manchmal ist das Debuggen die Lösung. Es sollte jedoch nicht das erste sein, was Ihnen beim Schreiben von Code in den Sinn kommt, dass Sie "Ankerpunkte" hinterlassen, deren einziger Zweck darin besteht, das Debuggen zu vereinfachen.

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

Hier kommt es darauf an, wie komplex stuffist und wie sich das auf den zurückgegebenen Wert bezieht.

Als "goldene Regel" würde ich folgendes sagen:

Wenn es hilft, den Zweck des Codes zu verstehen, ist es in Ordnung, Redundanz in Ihrem Code zu verursachen

oder anders ausgedrückt:

Schreiben Sie Ihren Code so redundanzfrei wie nötig, um später leicht zu verstehen, was der Code tut

Das führt zu: Meistens sollten Sie "Debug" -Variablen entfernen .

Thomas Junk
quelle
19

Das größte Problem ist die Klarheit . Wenn Ihr Code eine Menge fremden Müll enthält und ich Ihren Code pflege, muss ich herausfinden, was alles tut.

Wird diese Variable jemals für irgendetwas verwendet? Vielleicht führen Sie Operationen daran aus, verwenden aber niemals den Wert für etwas. Das einfache Inkrementieren einer Variablen bedeutet nicht, dass die Variable einen Zweck erfüllt, wenn Sie sie nie lesen (return, Eingabe in einen anderen Ausdruck usw.).

Allerdings: Wenn eine Variable einen Zweck hat und entsprechend benannt ist , beeinträchtigt dies nicht den gesamten Code.

Angesichts der Beispiele in Ihrer aktualisierten Frage und einiger anderer, an die ich gedacht habe:

  • Eine Funktion, die eine andere Funktion aufruft, das Ergebnis speichert, protokolliert und dann zurückgibt, ist ziemlich kurz und klar.

  • Splitting eine Anweisung mit mehreren Ausdrücke in mehrere Anweisungen (zB Splitting eine lange, komplexe Berechnung in mehrere Anweisungen mit mehreren Zwischenvariablen) kann der Code machen mehr klar trotz ausführlicher zu sein. Mit weniger Informationen, die gleichzeitig verarbeitet werden müssen, kann das Gehirn leichter erkennen, was gerade passiert.

  • Das Nichtverwenden von Ausnahmen ist völlig in Ordnung: In den meisten Sprachen muss die abgefangene Ausnahme angegeben werden, einschließlich der Angabe eines Variablennamens, der im catchBlock verwendet werden soll. In vielen gängigen Sprachen führt kein Weg daran vorbei, und Programmierer sind daran gewöhnt.

Wenn ich Zeit damit verbringen muss, herauszufinden, welche Codeelemente einen Zweck haben und welche nur meine Zeit verschwenden, sinkt meine Produktivität. Wenn der Code jedoch ziemlich präzise ist und Variablen auch dann gut benannt sind, wenn sie auf den ersten Blick irrelevant erscheinen, wird das Risiko verringert, unnötige Zeit damit zu verschwenden, den Code zu überprüfen, um ihn zu verstehen.

Schlechter Code mit fremden Variablen, leeren Blöcken und totem Code ist eine Möglichkeit, mit der Entwickler im Büro einen schlechten Ruf erlangen: "Ich habe einen Fehler in Schneemanns Code behoben. Ich habe zwei Stunden damit verbracht, herauszufinden, was diese Funktion tut, und 30 Sekunden lang der Fehler! Schneemann ist schrecklich beim Programmieren! " Aber wenn der Code einen Zweck erfüllt und klar geschrieben ist, ist er vollkommen in Ordnung.


quelle
9
+1 für "Schneemann ist schrecklich beim Programmieren." Ich habe es immer vermutet. Wie können Sie ein guter Programmierer sein, wenn Ihre Finger immer schmelzen?
Robert Harvey
Siehe meine Bearbeitung - ich meine nicht bloße Variablen, die aus heiterem Himmel ohne Zweck erstellt wurden, sondern nur solche, die hier und da beim Debuggen hilfreich sein können oder nur von einem dieser automatischen Tools wie Catch-Blöcke generiert wurden.
Tar
1
@Tar, der die gesamte Frage ändert - eingehende bearbeiten.
Beachten Sie, dass in Ihrer Liste mit Aufzählungszeichen, wenn Sie dies tun, die ersten beiden dazu neigen, nicht zu einer Warnung zu führen (ich habe in einem solchen Fall noch nie eine Sprache gesehen, die eine Warnung erzeugt hat). Für den dritten Fall hat jede Sprache, für die die Ausnahme eine Kennung erhalten muss, keine Warnung, und jede Sprache, die eine Warnung dafür erzeugt, benötigt keine Kennung (wieder, mit der ich vertraut bin) wie auch immer).
Servy
2
Wenn ich mir den Revisionsverlauf anschaue, sehe ich keinen Hinweis darauf, dass sich die Frage grundlegend ändert. Was den OP-Code betrifft, führen die ersten beiden zu einer Warnung in C # (die anscheinend die verwendete Sprache ist). Das dritte Beispiel würde keine Warnung ergeben. Die Kommentare zu der Frage weisen auch darauf hin, dass sie in Compiler-Warnungen ausdrücklich angegeben sind, und als Robert darauf hinwies, dass das dritte Beispiel keine Warnung erzeugt, räumte der Autor ein, dass es ein schlechtes Beispiel für ihre Frage war.
Servy
5

Nicht verwendete Variablen, die keinen offensichtlichen Zweck erfüllen, sind aus meiner Sicht ein Codegeruch. Bestenfalls können sie eine Ablenkung sein - sie tragen zum allgemeinen Rauschen im Modul bei.

Der schlimmste Fall ist, dass nachfolgende Codierer Zeit damit verbringen, herauszufinden, was sie tun sollten, und sich fragen, ob der Code vollständig ist. Tu dir (und allen anderen) einen Gefallen und werde los.

Robbie Dee
quelle
1
Was ist aus Ihrer Sicht ein "Bug"? Nicht verwendete Variablen führen per se nicht zu unerwarteten, fehlerhaften Ergebnissen, was die meisten Menschen als Fehler bezeichnen würden.
Harris
5
Warum wird die Variable nicht verwendet? Sehr wahrscheinlich, weil es hätte verwendet werden sollen, aber stattdessen wurde versehentlich eine andere Variable verwendet. Sie erhalten eine Compiler-Warnung, die Sie beheben und gleichzeitig den Fehler beheben. Das Problem ist, wenn Sie einen undisziplinierten Programmierer haben, der ein Durcheinander hinterlässt, können Sie nicht finden, wo diese Art von Warnung auf einen Fehler hinweist und wo sie nur auf einen unordentlichen Programmierer hinweist.
Gnasher729
@HarrisWeinstein Angesichts der Tatsache, dass Tester und Entwickler die meiste Zeit nicht einmal zustimmen können, was ein Fehler ist, werde ich das vorerst parken. Es genügt zu sagen, dass es sich um einen Mangel im Code handelt - und möglicherweise in der ausführbaren Datei, da diese Speicherplatz beansprucht. Zugegeben, nicht das größte Problem der Welt, aber da oben mit Rechtschreibfehlern im Kommentarfeld und auskommentiertem Code. Es ist Cruft, die nichts hinzufügt und daher entfernt werden sollte. Code, der gut aussieht, schafft Vertrauen. Ich denke, dieses Zitat ist auch passend und deckt den Refactoring-Prozess gut ab.
Robbie Dee
Wenn Sie eine dynamische Sprache verwenden, ist das Zuweisen eines Werts für some_varden Rest des Codes someVarfast garantiert ein Fehler. Dies ist in Java oder C möglicherweise kein Problem, kann jedoch leicht Python beschädigen.
Sean McSomething
1
@ThomasJunk Das ist wahrscheinlich ein besserer Begriff dafür - danke. Ich werde meine Antwort entsprechend anpassen.
Robbie Dee
5

Nicht verwendete Variablen machen die Absicht Ihres Codes unklar. Das ist schlecht , weil trotz des Anscheins, Code überwiegend geschrieben für Menschen zu lesen, nicht für Computer .

Andere haben bereits darauf hingewiesen, dass das Erstellen und Nichtverwenden eines Werts andere Personen verwirrt, die Ihren Code lesen und damit arbeiten müssen. Meiner Ansicht nach ist die größere Gefahr jedoch für Sie .

Eine nicht verwendete Variable kann beabsichtigt sein oder ein Versehen, das auf einen Fehler hinweist. Beispielsweise haben Sie möglicherweise einen Namen falsch eingegeben und einen Wert an einer Stelle gespeichert, als Sie dachten, Sie hätten ihn an einer anderen Stelle gespeichert. Das resultierende Programm könnte gut laufen, aber im Stillen das falsche Ergebnis liefern.

Durch die Analyse des Datenflusses können Sie solche und viele andere Fehler finden. Daher lohnt es sich, Ihren Code so zu schreiben, dass alles , was ein Datenflussanalysator als Anomalie ausweist, tatsächlich ein Fehler ist. Die automatische Unterstützung bei der Verhinderung von Fehlern ist von unschätzbarem Wert. Viele Leute denken "Oh, ich brauche keine Hilfe, ich wäre niemals so nachlässig", aber bisher alle, die ich getroffen habe und die das für falsch hielten.

Kilian Foth
quelle
2

Es gibt einen Codierungsstil, bei dem einer Variablen absichtlich alles zugewiesen wird, was von Interesse war (oder werden könnte), um es in einem Debugger einfach anzeigen zu können. Dies ist besonders nützlich für Code, der wie folgt aussieht:

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

Selbst mit etwas besseren Namen für die Funktionen kann es einfacher sein, herauszufinden, was beim Aufruf von foo falsch läuft, wenn Folgendes geschrieben wird:

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

Ich muss noch mit Leuten zusammenarbeiten, die dies als Standardkonfiguration praktizieren, aber das Umschreiben eines Codes, der sich hartnäckig weigert, in Form einer einzelnen Zuweisung einen Sinn zu ergeben, kann es einfacher machen, herauszufinden, was unter dem Debugger vor sich geht. Wir haben den Code danach immer wieder auf das kompakte, "hübsche" Format zurückgesetzt, aber ich frage mich, ob das ein Fehler war.

Die Alternative besteht darin, den Stapel auf und ab zu gehen und zu hoffen, dass Sie nicht zu weit gehen, oder (die äußerst seltenen) reversiblen Debugger zu verwenden.

Es ist keine beliebte Strategie, aber da sie mir geholfen hat, einige absurde Fehler zu beseitigen, denke ich nicht, dass sie als an sich schlecht abgeschrieben werden sollten.

Jon Chesterfield
quelle
Obwohl ich wahrscheinlich nicht so weit gehen würde wie Sie, finde ich Ihre erste "hübsche" Form zu kompakt.
Loren Pechtel
Nur dass Ihr Code keine einzige nicht verwendete Variable enthält.
Florian F
Auf der positiven Seite, wenn Sie eine Warnung vor nicht verwendeten Variablen erhalten würden, würden Sie wissen, dass Sie irgendwo in dieser Transformation einen großen Fehler begangen haben. Welches wäre leicht zu beheben.
Gnasher729
1

Für Personen, die ihren Unit-Test-Code in dieselben Projekte oder Module wie ihren "echten" Code aufnehmen, ist ein nicht verwendetes Feld wie eine Objektmethode ein starkes Signal dafür, dass Ihre Unit-Tests nicht alles testen. Dies erhöht die Wahrscheinlichkeit, dass ein Entwickler versucht, dieses derzeit nicht verwendete Feld oder diese Methode zu verwenden, und auf einen Fehler stößt, der bis dahin nicht erkannt wurde.

Eine nicht verwendete Variable in einer etwas nicht trivialen Unterroutine oder Methode kann darauf hinweisen, dass der Programmierer sie verwenden wollte, aber versehentlich eine andere Variable verwendet (z. B. nach dem Bereinigen nach einem Kopier-Einfüge-Vorgang).

Eine nicht verwendete Variable in einer trivialeren Unterroutine ist wahrscheinlich entweder unnötige Krätze, wie andere Leute geantwortet haben. Gelegentlich wird es in einer Breadcrumb-Anweisung verwendet, die derzeit auskommentiert ist:

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

... dem Augapfel ist klar, dass es dort und nur dort verwendet wird (dh someMethodeinen wichtigen Nebeneffekt hat), aber die IDE weiß das nicht, und das Entfernen dieser Variablen ist schwieriger als es wert ist. In solchen Fällen verwende ich vorläufig Warnunterdrücker.

Paul Brinkley
quelle
1
Ich frage mich, unter welchen Umständen Sie auskommentierten Code in Ihr Repository übertragen möchten. Eine ähnliche Situation tritt jedoch bei Verwendung der bedingten Kompilierung auf (z. B. bei Verwendung des assertMakros in C oder C ++). Nicht verwendete variable Warnungen können dort tatsächlich ärgerlich sein, und ihre Unterdrückung ist die vernünftigste Antwort, wenn Sie mich fragen.
5gon12eder
1
Ich habe meine Antwort bearbeitet und ein sehr grobes Beispiel für das hinzugefügt, was ich in der Vergangenheit gesehen habe. Der Block wird möglicherweise viele Male ausgeführt, und bei der Verfolgung eines Problems werden alle Debug-Informationen in einem Protokoll zur Analyse gesammelt. Der Druckvorgang ist jedoch langsam und daher normalerweise deaktiviert. Ich könnte die erste Zeile durch ersetzen someMethodund Informationen darüber verlieren, woher ich tmpkomme. Oder ich könnte eine saubere Version festschreiben und vergessen, dass eine frühere Version diesen nützlichen Breadcrumb hatte (und in späteren Versionen der erforderliche Code fehlte). ... Ich habe schon lange nach einem idealen Kompromiss gesucht.
Paul Brinkley
Aha. Anscheinend hat Ihre bevorzugte Sprache keinen Vorprozessor. ;-)
5gon12eder
Derzeit ja. :-) Um fair zu sein, habe ich in C und C ++ die gleichen Dinge gesehen, und es war auch in diesen Fällen nicht einfach, nicht verwendete Variablen loszuwerden (Quasi-Anhänge?). ... Die Tatsache, dass mein letztes großes C / C ++ - Projekt zu einer Zeit durchgeführt wurde, als es keine IDEs gab (Compiler-Warnungen erforderten das Ausführen von "gcc -pedantic"), half ebenfalls nicht.
Paul Brinkley
0

Wenn Sie Code schreiben, ist es einfach, zwei Variablen zu verwechseln. Sie berechnen eine Variable B, verwenden dann jedoch eine zuvor erstellte Variable A.

Ein möglicher Grund für eine nicht verwendete Variable ist also, dass Ihr Code einen Fehler enthält. Deshalb warnt Sie der Compiler. Wenn Sie nicht verwendete Variablen "nicht tun", ist dies sogar ein totes Werbegeschenk.

Wenn Sie eine solche Warnung sehen, sollten Sie Ihren Code überprüfen und entweder korrigieren oder die fehlerhafte Variable entfernen. Wenn Sie es nicht entfernen, werden Sie diese Warnungen nicht mehr beachten und können sie genauso gut vollständig deaktivieren. Aber dann verlieren Sie irgendwann einen Nachmittag beim Debuggen des Codes aufgrund eines dummen Fehlers.

Florian F.
quelle