Soll ich Variablen wiederverwenden?


59

Soll ich Variablen wiederverwenden?

Ich weiß, dass viele Best Practices besagen, dass Sie dies nicht tun sollten, aber später, wenn verschiedene Entwickler den Code debuggen und 3 Variablen haben, die gleich aussehen, und der einzige Unterschied darin besteht, dass sie an verschiedenen Stellen im Code erstellt werden, könnte dies der Fall sein verwirrt. Unit-Tests sind ein gutes Beispiel dafür.

Ich weiß jedoch , dass Best Practices die meiste Zeit dagegen sind. Sie sagen beispielsweise, dass Methodenparameter nicht "überschrieben" werden sollen.

Es wird sogar empfohlen, die vorherigen Variablen nicht auf null zu setzen (in Java gibt es Sonar, das eine Warnung ausgibt, wenn Sie nulleine Variable zuweisen , dass dies nicht erforderlich ist, um den Garbage Collector seit Java 6 aufzurufen. Sie können nicht immer steuern welche Warnungen deaktiviert sind, meistens ist die Standardeinstellung aktiviert.)


11
Seit Java 6? Sie mussten Variablen in keiner Java-Version den Wert null zuweisen. Wenn eine Variable den Gültigkeitsbereich verlässt, gibt sie den Verweis auf ihr Objekt frei.
Kevin Panko

35
Die Wiederverwendung von Variablen ist eines der ersten Dinge, die Code-Obfuscators verwenden
Lelouch Lamperouge

7
Die Wiederverwendung von Variablen widerspricht der Auswahl geeigneter Bezeichner für Ihre Variablen. In modernen Sprachen bietet die Wiederverwendung von Variablen keine wirklichen Vorteile, die die Vorteile guter Bezeichner überwiegen.
Joren

4
Beachten Sie auch, dass nicht jede Wiederverwendung eine Wiederverwendung ist. Alte FORTRAN-Programmierer, auch diejenigen, die in andere Sprachen abgewandert sind, verwenden routinemäßig I, J, K, L, M, N (oder i, j, k, l, m, n) für alle unsere DO-Schleifen (for- Schleifenzähler. Wir sind es gewohnt, Dinge wie SUM = SUMME + A (I, K) * B (K, J) oder Summe + = a [i] [k] * b [k] [j] zu sehen.
John R. Strohm

1
Die Wiederverwendung von Variablen könnte gerechtfertigt sein, wenn Mikrocontroller mit sehr begrenzten Ressourcen (einige kByte RAM) programmiert werden.
m.Alin

Antworten:


130

Ihr Problem wird nur angezeigt, wenn Ihre Methoden lang sind und mehrere Aufgaben in einer Sequenz ausführen. Dies erschwert das Verständnis (und somit die Pflege) des Codes an sich. Das Wiederverwenden von Variablen erhöht das Risiko zusätzlich, sodass der Code noch schwerer zu befolgen und fehleranfälliger ist.

Die IMO-Best-Practice besteht darin, Methoden zu verwenden, die kurz genug sind und nur eines tun, um das gesamte Problem zu beseitigen.


Was ist mit Unit-Tests? Zum Beispiel muss ich testen, ob die Methode nach dem zweiten Ausführen immer noch wie erwartet funktioniert.
IAdapter

20
@IAdapter, Unit-Test-Code ist ein anderes Problem, bei dem die Standards möglicherweise gelockerter sind als bei Seriencode. Dennoch hat es hohe Priorität, es lesbar und leicht zu warten zu machen. Sie können (und sollten) auch Methoden aus Ihren Komponententests extrahieren , um sie kurz und übersichtlich zu halten (und die Wiederverwendung von Variablen zu vermeiden).
Péter Török

3
@IAdapter, für das von Ihnen beschriebene Szenario würde ich keine Variable wiederverwenden. Das Richtige wäre, dass result1 = foo(); result2 = foo(); Assert.AreEqual(result1, result2);ich nicht viele Stellen sehe, an denen Sie in diesem Fall eine Variable wiederverwenden müssten.
JSB ձոգչ

1
@IAdapter für (int i = 0; i <2; i ++) {result = foo (); assertEquals (expectedResult, result);}
Bill K

2
+1 - Dies ist ein guter Codegeruch für kleinere Methoden.

49

Die Wiederverwendung von Variablen in einer Methode ist ein starkes Zeichen dafür, dass Sie sie umgestalten / aufteilen sollten.

Meine Antwort wäre also, dass Sie sie nicht wiederverwenden sollten, denn wenn Sie dies tun, wäre es umso schwieriger, sie später umzugestalten.


19

Es hängt davon ab, ob.

Einige Variablen können genau zum Speichern einer bestimmten Art von Daten erstellt werden, die sich während der Ausführung einer Funktion ändern können. Ich erinnere mich hier an Rückkehrcodes, zum Beispiel:

void my_function() {
    HRESULT errorcode;
    errorcode = ::SomeWindowsApiFunction();
    if (FAILED(errorcode)) { /* handle error */ }
    errorcode = ::AnotherWindowsApiFunction();
    if (FAILED(errorcode)) { /* handle error */ }
}

Der Variablenname macht sehr deutlich, was diese Variable speichern soll. Ich denke, dass andere Verwendungszwecke wie dieser möglich sind, bei denen eine Variable konzeptionell ein Container ist, der von verschiedenen Instanzen sehr ähnlicher Dinge im Verlauf einer Funktion logisch verwendet wird.

Im Allgemeinen sollte dies jedoch nur unter Umständen erfolgen, bei denen es für mögliche Leser des Codes absolut klar ist. In keinem Fall sollte eine Variable wiederverwendet werden, nur weil der Typ passt.

All dies ergibt sich im Wesentlichen aus guten Praktiken bei der Benennung von Variablen. Namen sollten für sich selbst sprechen. Wenn es schwierig ist, den genauen Zweck für alle Wiederverwendungen in einem kurzen Namen anzugeben, ist es am besten, nur unterschiedliche Variablen zu verwenden.


15

Der Hauptgrund, warum ich keine Variablen wiederverwende (insbesondere bei Unit-Tests), ist die Einführung eines unnötigen Codepfads, der schwer zu testen und zu debuggen ist. Ein guter Komponententest sollte unabhängig von anderen Tests sein. Wenn Sie Klassenvariablen (Instanzenvariablen) in einem Komponententestgerät wiederverwenden, müssen Sie sicherstellen, dass vor jedem Test deren Status bestätigt wird. Ein guter Komponententest isoliert auch Fehler, so dass theoretisch jeder Testfall (Methode) nur 1 Verhalten für das zu testende System bestätigen sollte. Wenn Ihre Testmethoden so geschrieben sind, ist die Wiederverwendung einer Variablen auf Methodenebene selten erforderlich oder sinnvoll. Schließlich ist es in Sprachen, die Closures und asynchrone Verarbeitung unterstützen, wirklich schwierig zu überlegen, was zum Teufel passiert, wenn Sie Variablen in einer Methode wiederverwenden.


Also sollte ich Testmethoden wie -testSomething schreiben und für einen einzelnen Methodenaufruf -testSomethingTwoInvocations und Asserts für nur einen zweiten Aufruf geltend machen?
IAdapter

2
Ja. Auf diese Weise können Sie feststellen, ob die erste oder zweite Iteration fehlgeschlagen ist. mspec kann dazu beitragen, sein Vererbungsbaum wird sehr nützlich sein.
Bryan Boettcher

Wenn Sie "Variable" verwenden, wenn Sie "Klassenvariable" oder "Instanzvariable" meinen, müssen Sie sich klarer ausdrücken.
gnasher729

13

Sie sollten verschiedene Variablen verwenden. Wenn Sie befürchten, dass Ihr Kollege verwirrt wird, geben Sie ihm Namen, die eindeutig seine Rollen abdecken.
Die Wiederverwendung von Variablen kann in Zukunft zu Verwirrung führen. es ist besser, es jetzt aufzuklären.
In einigen Fällen kann derselbe Variablenname wiederverwendet werden. zum Beispiel iin einer einfachen Zählschleife. In diesen Fällen sollten Sie natürlich sicherstellen, dass sich die Variablen in ihrem eigenen Bereich befinden.

BEARBEITEN: Die Wiederverwendung von Variablen ist manchmal ein Zeichen dafür, dass das Prinzip der einfachen Verantwortung verletzt wird. Überprüfen Sie, ob die wiederverwendete Variable in derselben Rolle verwendet wird. Wenn dies der Fall ist, kann es möglicherweise überhaupt nicht wiederverwendet werden (obwohl es immer noch vorzuziehen ist, zwei verschiedene Variablen zu haben, um den Umfang dieser Variablen einzuschränken). Wenn es in verschiedenen Rollen verwendet wird, liegt eine SRP-Verletzung vor.


4

Es gibt eine Situation, in der Sie eine Variable möglicherweise wiederverwenden möchten, ungeachtet der guten Ratschläge anderer Antworten: Wenn Ihr Compiler eine helfende Hand benötigt.

In einigen Fällen kann es sein, dass Ihr Compiler nicht klug genug ist, um zu erkennen, dass eine bestimmte vom Register zugewiesene Variable im nächsten Teil des Codes nicht mehr verwendet wird. Daher wird dieses theoretisch freie Register für die nächsten Variablen nicht wiederverwendet, und der generierte Code ist möglicherweise nicht optimal.

Beachten Sie, dass ich keine aktuellen Mainstream-Compiler kenne, die diese Situation nicht richtig erfassen. Tun Sie dies also niemals, es sei denn, Sie wissen, dass Ihr Compiler suboptimalen Code generiert. Wenn Sie mit benutzerdefinierten Compilern für spezielle eingebettete Systeme kompilieren, tritt dieses Problem möglicherweise weiterhin auf.


17
-1, es sei denn, Sie können auf eine reale Situation verweisen, in der dies tatsächlich geschieht und die Wiederverwendung einer Variablen einen spürbaren Unterschied macht. Dies ist eine theoretische Lösung für ein theoretisches Problem und noch keine sehr gute. Wo der Compiler entscheidet, Variablen zu setzen, ist das Anliegen des Compilers. Wenn Ihr Compiler schlechten Code generiert und dies wirklich einen Unterschied macht, reparieren oder ersetzen Sie den Compiler.
Caleb

3
@Caleb - Sie haben nicht immer Zugriff auf den Compiler-Quellcode für die Plattform, auf der Sie entwickeln, insbesondere für proprietäre Embedded-Plattformen. Ich auch DID in meiner Antwort sagen , dass ich weiß nicht von irgendwelchen aktuellen Mainstream - Compiler (oder Interpreter / VMs in der Tat) , die nicht korrekt diese Vitalitätsanalyse in allen Fällen durchführen , die ich angeschaut habe. Ich habe jedoch an proprietären eingebetteten Systemen mit benutzerdefinierten Compilern gearbeitet, die in der Vergangenheit (vor ungefähr 10 Jahren) noch sehr einfach waren. Das System und der Compiler waren in ihren Fähigkeiten sehr eingeschränkt, so dass diese Situation dort auftrat.
Joris Timmermans

2
+1 Ich habe genau eine solche Wiederverwendung in früheren Projekten durchgeführt (hochoptimierter Mediencode in ANSI C). Soweit ich mich erinnere, war der Unterschied in der Montage leicht sichtbar und in Benchmarks messbar. Habe ich noch nie erlebt und hoffe, dass ich niemals eine solche Wiederverwendung in Java durchführen muss.
gnat

Das Reparieren oder Ersetzen des Compilers durch @Caleb kann aus mehreren Gründen nicht in Frage kommen, und Sie müssen einfach mit dem auskommen, was Sie haben.

@ ThorbjørnRavnAndersen Ist es denkbar, dass man gezwungen ist, einen miesen Compiler zu verwenden, und dass die Leistung möglicherweise so kritisch ist, dass Sie den Compiler noch einmal erraten und Ihren Code manipulieren müssen, um ein Register wiederzuverwenden? Ja. Ist es wahrscheinlich ? MadKeithV stimmt zu, dass er kein reales Beispiel liefern kann. Ist es eine bewährte Methode ? Ist es guter Stil ? Ist es ein Indikator für die Codequalität ? Definitiv nicht. Ist dies eine nützliche Antwort auf die geschriebene Frage? Aus Rücksicht auf MadKeithV, aber ich glaube nicht.
Caleb

2

Ich würde NEIN sagen.

Denken Sie an dieses Szenario: Ihr Programm ist abgestürzt und Sie müssen herausfinden, was bei der Überprüfung eines Core-Dumps passiert ist. Können Sie den Unterschied erkennen? ;-)


Wenn Ihr Core-Dump von einem optimierten Build stammt, teilen sich die Variablen möglicherweise trotzdem den Speicher. Das ist also weniger hilfreich, als es sein könnte.
Winston Ewert

Natürlich ist ein optimierter Build für das Debuggen nicht sehr nützlich! In jedem Fall haben Sie jedoch weiterhin die Möglichkeit, einen Debugbuild zu verwenden. Wenn Sie den Debugger angehängt haben, müssen Sie nicht vom Anfang einer Funktion an schrittweise vorgehen, um zu sehen, wie sich die Variablen ändern, weil sie sich ändern nicht! :-D
fortran

2

Nein, Sie verbessern nicht den Code, den der Computer ausführt (... den Assembly-Code). Belassen Sie die Wiederverwendung des vom Compiler für die Variable verwendeten Speichers beim Compiler. Ziemlich oft wird es ein Register sein, und die Wiederverwendung hat dir nichts gekauft. Konzentrieren Sie sich darauf, den Code besser lesbar zu machen.


0

Es hängt davon ab, ob. In einer dynamischen Sprache, in der der Typ eher auf Werten als auf Variablen basiert, hätte ich ein Argument mit gutem Namen für eine Funktion, die zum Beispiel eine Zeichenfolge war. Wenn ich den Algorithmus ändere, bedeutet dies, dass er immer verwendet wurde, nachdem er als Ganzzahl interpretiert wurde. Als ersten Entwurf könnte ich dann das Äquivalent von tun

scrote = int (scrote)

Aber ich würde eventuell versuchen, den an die Funktion gesendeten Typ zu ändern und die Änderung des Parametertyps zu vermerken.


1
Das Einfügen einer Zeile wie "scrote = int (scrote)" in die Mitte eines langen Codestapels ist eine großartige Möglichkeit, Wartungsprogrammierer in den Wahnsinn zu treiben.
jhocking

Es ist wahrscheinlicher, dass das Problem bei der von Ihnen erwähnten "langen Codestapel" liegt.
Paddy3118

Neben den akzeptierten Antwortnotizen ist die Wiederverwendung von Variablen nur bei langen Codestapeln wirklich ein Problem. Grundsätzlich würde ich es in jeder Situation, in der Sie so etwas wie "scrote = int (scrote)" schreiben, vorziehen, int (scrote) in eine neue Variable zu setzen oder besser noch int (scrote) an eine neue Funktion zu übergeben.
jhocking

0

Schauen Sie sich zunächst Ihre Entwicklungsumgebung an. Wenn Sie Probleme beim Debuggen haben, weil Sie fünf Variablen in unterschiedlichen Bereichen mit identischen Namen haben und der Debugger Ihnen nicht anzeigt, welche dieser Variablen Sie benötigen, verwenden Sie keine fünf Variablen mit demselben Namen. Dies kann auf zwei Arten erreicht werden: Verwenden Sie eine Variable oder fünf verschiedene Namen.

Ihr Debugger kann es auch schmerzhaft machen, eine Funktion mit vielen Variablen zu debuggen. Wenn eine Funktion mit 20 Variablen schwerer zu debuggen ist als eine mit 16 Variablen, können Sie 5 Variablen durch eine ersetzen. ("Könnte berücksichtigen" ist nicht dasselbe wie "sollte immer").

Es ist in Ordnung, eine Variable an mehreren Stellen zu verwenden, solange die Variable immer denselben Zweck hat. Wenn beispielsweise zehn Funktionsaufrufe einen Fehlercode zurückgeben, der sofort für jeden Aufruf verarbeitet wird, verwenden Sie eine Variable und nicht 10. Verwenden Sie dieselbe Variable jedoch nicht für völlig unterschiedliche Dinge. Wenn Sie beispielsweise "name" für einen Kundennamen und 10 Zeilen später dieselbe Variable für einen Firmennamen verwenden, ist das schlecht und bringt Sie in Schwierigkeiten. Schlimmer noch: Verwenden Sie "customerName" für einen Kundennamen und 10 Zeilen später dieselbe Variable "customerName" für einen Firmennamen.

Wichtig ist, dass nichts eine eiserne Regel ist. Alles hat Vor- und Nachteile. Wenn "Best Practices" eine Sache nahelegen und Sie Gründe haben zu sagen, dass es in Ihrer spezifischen Situation eine schlechte Idee ist, dann tun Sie es nicht.


0

Schauen Sie sich zunächst Ihre Entwicklungsumgebung an. Wenn Sie Probleme beim Debuggen haben, weil Sie fünf Variablen in unterschiedlichen Bereichen mit identischen Namen haben und der Debugger Ihnen nicht anzeigt, welche dieser Variablen Sie benötigen, verwenden Sie keine fünf Variablen mit demselben Namen. Dies kann auf zwei Arten erreicht werden: Verwenden Sie eine Variable oder fünf verschiedene Namen.

Ihr Debugger kann es auch schmerzhaft machen, eine Funktion mit vielen Variablen zu debuggen. Wenn eine Funktion mit 20 Variablen schwerer zu debuggen ist als eine mit 16 Variablen, können Sie 5 Variablen durch eine ersetzen. ("Könnte berücksichtigen" ist nicht dasselbe wie "sollte immer").

Es ist in Ordnung, eine Variable an mehreren Stellen zu verwenden, solange die Variable immer denselben Zweck hat. Wenn beispielsweise zehn Funktionsaufrufe einen Fehlercode zurückgeben, der bei jedem Aufruf sofort behandelt wird, verwenden Sie eine Variable und nicht 10. Hierbei gibt es ein Problem: Normalerweise teilt Ihnen der Compiler mit, wann Sie eine nicht initialisierte Variable verwenden. Wenn Sie jedoch nach Aufruf 6 den Fehlercode lesen, die Variable jedoch nach Aufruf 5 nicht geändert wurde, erhalten Sie unbrauchbare Daten, ohne dass der Compiler Sie warnt. Da die Variable mit Daten initialisiert wurde, die jetzt unbrauchbar sind.

Wichtig ist, dass nichts eine eiserne Regel ist. Alles hat Vor- und Nachteile. Wenn "Best Practices" eine Sache nahelegen und Sie Gründe haben zu sagen, dass es in Ihrer spezifischen Situation eine schlechte Idee ist, dann tun Sie es nicht.


-2

Verwenden Sie globale Variablen, wenn Sie einen Status verwalten oder Konstanten speichern müssen. Durch die Wiederverwendung von Variablen wird nur der Name wiederverwendet, der auf eine Position im Speicher verweist. Beschreibende Namen bei Initialisierungen können Ihnen nur Klarheit verschaffen (vorausgesetzt, Java und kein primitives OCD).

Es sei denn, Sie befassen sich mit Code-Verschleierung von Hand oder irritieren andere Entwickler.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.