Laut der akzeptierten Antwort zu " Argumentation, lokale Variablen gegenüber Instanzvariablen zu bevorzugen? " Sollten Variablen im kleinstmöglichen Bereich leben.
Vereinfache das Problem in meiner Interpretation, es bedeutet, dass wir diese Art von Code überarbeiten sollten:
public class Main {
private A a;
private B b;
public ABResult getResult() {
getA();
getB();
return ABFactory.mix(a, b);
}
private getA() {
a = SomeFactory.getA();
}
private getB() {
b = SomeFactory.getB();
}
}
in so etwas:
public class Main {
public ABResult getResult() {
A a = getA();
B b = getB();
return ABFactory.mix(a, b);
}
private getA() {
return SomeFactory.getA();
}
private getB() {
return SomeFactory.getB();
}
}
aber nach dem "Geist" von "Variablen sollten möglichst im kleinsten Bereich leben", haben "niemals Variablen" nicht einen kleineren Bereich als "Variablen"? Daher denke ich, dass die obige Version überarbeitet werden sollte:
public class Main {
public ABResult getResult() {
return ABFactory.mix(getA(), getB());
}
private getA() {
return SomeFactory.getA();
}
private getB() {
return SomeFactory.getB();
}
}
das getResult()
hat also überhaupt keine lokalen Variablen. Ist das wahr?
refactoring
scope
local-variable
ocomfd
quelle
quelle
final
Schlüsselwort verwenden sollten oder nicht.Antworten:
Nein. Es gibt mehrere Gründe, warum:
Und so weiter.
quelle
var taxIndex = getTaxIndex();
).now()
), kann das Entfernen der Variablen und das mehrmalige Aufrufen der Methode zu Fehlern führen. Dies kann zu einer Situation führen, die sehr subtil und schwer zu debuggen ist. Es mag offensichtlich erscheinen, aber wenn Sie sich in einer Blind-Refactoring-Mission befinden, um Variablen zu entfernen, kann es leicht zu Fehlern kommen.Stimmen Sie zu, Variablen, die nicht erforderlich sind und die Lesbarkeit des Codes nicht verbessern, sollten vermieden werden. Je mehr Variablen an einem bestimmten Punkt im Code im Geltungsbereich sind, desto komplexer ist der Code zu verstehen.
Ich sehe nicht wirklich den Nutzen der Variablen
a
undb
in Ihrem Beispiel würde ich die Version ohne Variablen schreiben. Andererseits ist die Funktion so einfach, dass ich nicht denke, dass es wichtig ist.Je länger die Funktion wird und je mehr Variablen im Gültigkeitsbereich sind, desto problematischer wird es.
Zum Beispiel, wenn Sie haben
An der Spitze einer größeren Funktion erhöhen Sie die mentale Belastung, den Rest des Codes zu verstehen, indem Sie statt einer drei Variablen einführen. Sie müssen den Rest des Codes durchlesen, um zu sehen, ob
a
oderb
wieder verwendet werden. Einheimische, deren Umfang länger ist als erforderlich, beeinträchtigen die allgemeine Lesbarkeit.Wenn eine Variable erforderlich ist (z. B. um ein temporäres Ergebnis zu speichern) oder wenn eine Variable die Lesbarkeit des Codes verbessert, sollte sie natürlich beibehalten werden.
quelle
var result = getResult(...); return result;
gehört, dass Sie einen Haltepunkt setzenreturn
und herausfinden können, was genau dasresult
ist.Neben den anderen Antworten möchte ich noch auf etwas anderes hinweisen. Der Vorteil, den Gültigkeitsbereich einer Variablen klein zu halten, besteht nicht nur darin, dass weniger Code syntaktisch auf die Variable zugreifen kann, sondern auch darin, dass die Anzahl der möglichen Steuerungsflusspfade verringert wird, die eine Variable möglicherweise ändern können (entweder durch Zuweisen eines neuen Werts oder durch Aufrufen) eine Mutationsmethode für das vorhandene Objekt in der Variablen).
Klassenbezogene Variablen (Instanzen oder statische Variablen) verfügen über wesentlich mehr mögliche Kontrollflusspfade als lokale Variablen, da sie durch Methoden mutiert werden können, die in beliebiger Reihenfolge, beliebig oft und häufig durch Code außerhalb der Klasse aufgerufen werden können .
Werfen wir einen Blick auf Ihre ursprüngliche
getResult
Methode:Nun werden die Namen
getA
undgetB
kann vorschlagen , dass sie vergeben werdenthis.a
undthis.b
können wir nicht wissen , sicher von einem Blick aufgetResult
. Daher ist es möglich, dass die an die Methode übergebenen Wertethis.a
und stattdessen aus dem Zustand des Objekts stammen, von demthis.b
zuvor diemix
Methode aufgerufen wurde. Dies kann nicht vorhergesagt werden, da Clients steuern, wie und wann Methoden aufgerufen werden.this
getResult
In dem überarbeiteten Code mit den Variablen local
a
undb
ist klar, dass es genau einen (ausnahmefreien) Kontrollfluss von der Zuweisung jeder Variablen zu ihrer Verwendung gibt, da die Variablen unmittelbar vor ihrer Verwendung deklariert werden.Das Verschieben (modifizierbarer) Variablen aus dem Klassenbereich in den lokalen Bereich sowie das Verschieben (modifizierbarer) Variablen von der Außenseite einer Schleife nach innen hat daher einen erheblichen Vorteil, da das Schließen des Kontrollflusses vereinfacht wird.
Andererseits hat das Eliminieren von Variablen wie in Ihrem letzten Beispiel einen geringeren Vorteil, da es die Argumentation für den Kontrollfluss nicht wirklich beeinflusst. Sie verlieren auch die Namen der Werte, was nicht der Fall ist, wenn Sie eine Variable einfach in einen inneren Bereich verschieben. Dies ist ein Kompromiss, den Sie berücksichtigen müssen, sodass die Eliminierung von Variablen in einigen Fällen besser und in anderen schlechter sein kann.
Wenn Sie die Variablennamen nicht verlieren, aber dennoch den Gültigkeitsbereich der Variablen verringern möchten (falls sie in einer größeren Funktion verwendet werden), können Sie die Variablen und ihre Verwendung in eine Blockanweisung einschließen ( oder sie in ihre eigene Funktion versetzen ).
quelle
Dies ist etwas sprachabhängig, aber ich würde sagen, dass einer der weniger offensichtlichen Vorteile der funktionalen Programmierung darin besteht, dass Programmierer und Leser von Code ermutigt werden, diese nicht zu benötigen. Erwägen:
Oder etwas LINQ:
Oder Node.js:
Die letzte ist eine Kette von Aufrufen einer Funktion für das Ergebnis einer vorherigen Funktion ohne Zwischenvariablen. Ihre Einführung würde es viel unklarer machen.
Der Unterschied zwischen dem ersten und den beiden anderen Beispielen ist jedoch die implizite Reihenfolge der Operationen . Dies ist möglicherweise nicht die gleiche Reihenfolge wie die tatsächlich berechnete, aber die Reihenfolge, in der der Leser darüber nachdenken sollte. Für die zweiten beiden ist dies von links nach rechts. Für das Lisp / Clojure-Beispiel ist es eher von rechts nach links. Sie sollten etwas vorsichtig sein, wenn Sie Code schreiben, der nicht in der "Standardrichtung" für Ihre Sprache ist, und Ausdrücke mit "mittlerer Ausprägung", die beides vermischen, sollten auf jeden Fall vermieden werden.
Der Pipe-Operator von F #
|>
ist unter anderem deshalb nützlich, weil Sie damit von links nach rechts schreiben können, was sonst von rechts nach links erfolgen müsste.quelle
myCollection.Select(_ => _.SomeProp).Where(_ => _.Size > 4);
Ich würde nein sagen, weil Sie "kleinstmöglichen Bereich" als "unter vorhandenen Bereichen oder solchen, die sinnvoll sind, hinzuzufügen" lesen sollten. Andernfalls müssten Sie künstliche Bereiche erstellen (z. B. unbegründete
{}
Blöcke in C-ähnlichen Sprachen), um sicherzustellen, dass der Bereich einer Variablen nicht über den letzten Verwendungszweck hinausgeht, und dies würde im Allgemeinen als Verschleierung / Unordnung angesehen, es sei denn, dies ist bereits geschehen Ein guter Grund für die Unabhängigkeit des Geltungsbereichs.quelle
Betrachten Sie Funktionen ( Methoden ). Dort wird weder der Code in die kleinstmögliche Teilaufgabe aufgeteilt, noch das größte einzelne Codestück.
Es ist eine Verschiebungsgrenze, bei der logische Aufgaben in Verbrauchsgüter unterteilt werden.
Gleiches gilt für Variablen . Aufzeigen logischer Datenstrukturen in verständliche Teile. Oder benennen Sie einfach die Parameter:
Aber natürlich mit einer Erklärung oben und zweihundert Zeilen weiter wird die erste Verwendung heutzutage als schlechter Stil akzeptiert. Dies ist eindeutig das, was "Variablen im kleinstmöglichen Rahmen leben sollten" zu sagen beabsichtigt. Wie ein sehr nahes "Variablen nicht wiederverwenden."
quelle
Was als Grund für NEIN etwas fehlt, ist Debugging / Readabillity. Code sollte dafür optimiert sein und klare und prägnante Namen helfen viel, zB stellen Sie sich eine 3-Wege-Lösung vor
Diese Zeile ist kurz, aber schon schwer zu lesen. Fügen Sie ein paar weitere Parameter hinzu, und das, wenn Sie sich über mehrere Zeilen erstrecken.
Ich finde diesen Weg einfacher zu lesen und Bedeutung zu kommunizieren - so habe ich kein Problem mit Zwischenvariablen.
Ein anderes Beispiel wären Sprachen wie R, bei denen die letzte Zeile automatisch der Rückgabewert ist:
das ist gefährlich, ist die rückgabe zu erwarten oder wird sie benötigt? das ist klarer:
Wie immer handelt es sich hierbei um einen Beurteilungsaufruf - eliminieren Sie Zwischenvariablen, wenn sie das Lesen nicht verbessern, andernfalls behalten oder einführen.
Ein weiterer Punkt kann die Debug-Fähigkeit sein: Wenn die Zwischenergebnisse von Interesse sind, kann es am besten sein, einfach einen Zwischenhändler einzuführen, wie im obigen R-Beispiel. Wie oft dies aufgerufen wird, ist schwer vorstellbar und Sie müssen vorsichtig sein, was Sie einchecken - zu viele Debugging-Variablen sind verwirrend -.
quelle
Nur unter Bezugnahme auf Ihren Titel: Wenn eine Variable nicht benötigt wird, sollte sie unbedingt gelöscht werden.
Aber "unnötig" bedeutet nicht, dass ein äquivalentes Programm ohne Verwendung der Variablen geschrieben werden kann, sonst würde uns gesagt, dass wir alles in Binärform schreiben sollten.
Die am häufigsten vorkommende Art von unnötiger Variable ist eine nicht verwendete Variable. Je kleiner der Gültigkeitsbereich der Variablen ist, desto einfacher lässt sich feststellen, dass sie nicht erforderlich ist. Ob eine Zwischenvariable unnötig ist, ist schwieriger zu bestimmen, da es sich nicht um eine binäre Situation handelt, sondern um eine kontextbezogene. Tatsächlich könnte identischer Quellcode in zwei verschiedenen Methoden eine unterschiedliche Antwort desselben Benutzers ergeben, abhängig von den Erfahrungen in der Vergangenheit bei der Behebung von Problemen im umgebenden Code.
Wenn Ihr Beispielcode genau so wäre, wie er dargestellt wurde, würde ich vorschlagen, die beiden privaten Methoden loszuwerden, hätte aber kaum Bedenken, ob Sie das Ergebnis der Factory-Aufrufe für eine lokale Variable gespeichert oder sie nur als Argumente für die Mischung verwendet haben Methode.
Die Lesbarkeit des Codes übertrifft alles außer der korrekten Funktionsweise (enthält korrekterweise akzeptable Leistungskriterien, die selten „so schnell wie möglich“ sind).
quelle