Um beispielsweise eine CPU in Android eingeschaltet zu lassen, kann ich folgenden Code verwenden:
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();
Ich denke aber die lokalen Variablen powerManager
und wakeLock
können beseitigt werden:
((PowerManager)getSystemService(POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
.acquire();
Eine ähnliche Szene wird in der iOS-Benachrichtigungsansicht angezeigt, z. B .: von
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"my title"
message:@"my message"
delegate:nil
cancelButtonTitle:@"ok"
otherButtonTitles:nil];
[alert show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[alertView release];
}
zu:
[[[UIAlertView alloc]
initWithTitle:@"my title"
message:@"my message"
delegate:nil
cancelButtonTitle:@"ok"
otherButtonTitles:nil] show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[alertView release];
}
Ist es empfehlenswert, eine lokale Variable zu entfernen, wenn sie nur einmal im Gültigkeitsbereich verwendet wird?
Antworten:
Code wird viel öfter gelesen als geschrieben, daher sollten Sie Mitleid mit der armen Seele haben, die den Code in sechs Monaten lesen muss (Sie vielleicht) und nach dem klarsten und am einfachsten zu verstehenden Code streben wird. Meiner Meinung nach ist die erste Form mit lokalen Variablen viel verständlicher. Ich sehe drei Aktionen in drei Zeilen, anstatt drei Aktionen in einer Zeile.
Und wenn Sie glauben, Sie optimieren etwas, indem Sie lokale Variablen entfernen, tun Sie dies nicht. Ein moderner Compiler legt
powerManager
in einem Register 1 fest , ob eine lokale Variable verwendet wird oder nicht, um dienewWakeLock
Methode aufzurufen . Gleiches gilt fürwakeLock
. So erhalten Sie in beiden Fällen denselben kompilierten Code.1 Wenn Sie zwischen der Deklaration und der Verwendung der lokalen Variablen viel Code verwendet haben, wird dieser möglicherweise auf dem Stapel abgelegt, es handelt sich jedoch nur um ein geringfügiges Detail.
quelle
Einige hoch gelobte Kommentare sagten dies aus, aber keine der Antworten, die ich gesehen habe, tat es. Deshalb werde ich es als Antwort hinzufügen. Ihr Hauptfaktor bei der Entscheidung für dieses Problem ist:
Debuggbarkeit
Oft verbringen Entwickler viel mehr Zeit und Mühe mit dem Debuggen als mit dem Schreiben von Code.
Mit lokalen Variablen können Sie:
Haltepunkt in der Zeile, der er zugewiesen wurde (mit allen anderen Haltepunktdekorationen, wie z. B. bedingtem Haltepunkt usw.)
Überprüfen / beobachten / drucken / ändern Sie den Wert der lokalen Variablen
Fang Probleme, die durch Abgüsse entstehen.
Lesbare Stapelspuren haben (Zeile XYZ hat eine Operation anstelle von 10)
Ohne lokale Variablen sind alle oben genannten Aufgaben, abhängig von Ihrem Debugger, entweder viel schwieriger, extrem schwierig oder überhaupt nicht möglich.
Befolgen Sie daher die berüchtigte Maxime (schreiben Sie den Code so, als ob der nächste Entwickler, der ihn selbst wartet, ein verrückter Wahnsinniger ist, der weiß, wo Sie leben), und gehen Sie auf die Seite der einfacheren Debug-Fähigkeit , dh verwenden Sie lokale Variablen .
quelle
Nur wenn es den Code verständlicher macht. In Ihren Beispielen ist das Lesen meiner Meinung nach schwieriger.
Das Eliminieren der Variablen im kompilierten Code ist für jeden seriösen Compiler eine triviale Operation. Sie können die Ausgabe selbst überprüfen.
quelle
Ihre Frage "Ist es eine gute Praxis, eine lokale Variable zu entfernen, wenn sie nur einmal im Gültigkeitsbereich verwendet wird?" testet die falschen Kriterien. Das Dienstprogramm einer lokalen Variablen hängt nicht davon ab, wie oft sie verwendet wird, sondern davon, ob der Code dadurch klarer wird. Das Beschriften von Zwischenwerten mit aussagekräftigen Namen kann die Übersichtlichkeit in Situationen wie der von Ihnen dargestellten verbessern, da der Code in kleinere, besser verdauliche Teile zerlegt wird.
Meiner Ansicht nach ist der von Ihnen vorgelegte unveränderte Code klarer als der von Ihnen geänderte Code und sollte daher unverändert bleiben. Tatsächlich würde ich erwägen, eine lokale Variable aus Ihrem geänderten Code zu ziehen, um die Übersichtlichkeit zu verbessern.
Ich würde keine Auswirkung auf die Leistung von den lokalen Variablen erwarten, und selbst wenn es eine gibt, ist sie wahrscheinlich zu klein, um in Betracht gezogen zu werden, es sei denn, der Code befindet sich in einer sehr engen Schleife in einem geschwindigkeitskritischen Teil des Programms.
quelle
Vielleicht.
Persönlich würde ich zögern, lokale Variablen zu entfernen, wenn es sich um eine Typumwandlung handelt. Ich finde Ihre kompakte Version weniger lesbar, da sich die Anzahl der Klammern einer mentalen Grenze nähert, die ich habe. Es wird sogar ein neuer Satz von Klammern eingeführt, der in der etwas ausführlicheren Version unter Verwendung einer lokalen Variablen nicht benötigt wurde.
Die vom Code-Editor bereitgestellte Syntaxhervorhebung kann solche Bedenken in gewissem Maße abmildern.
Für mich ist dies der bessere Kompromiss:
Auf diese Weise wird eine lokale Variable beibehalten und die andere über Bord geworfen. In C # würde ich das Schlüsselwort var in der ersten Zeile verwenden, da der Typecast bereits die Typinformationen enthält.
quelle
Obwohl ich die Gültigkeit der Antworten akzeptiere, die lokale Variablen bevorzugen, werde ich den Anwalt des Teufels spielen und eine konträre Sichtweise vertreten.
Ich persönlich bin etwas dagegen, lokale Variablen nur zu Dokumentationszwecken zu verwenden, obwohl dieser Grund selbst anzeigt, dass die Praxis einen Wert hat: Die lokalen Variablen dokumentieren den Code faktisch pseudodokumentiert.
In Ihrem Fall ist das Hauptproblem die Einrückung und nicht das Fehlen von Variablen. Sie könnten (und sollten) den Code wie folgt formatieren:
Vergleichen Sie das mit der Version mit lokalen Variablen:
Mit den lokalen Variablen: Die Namen geben dem Leser einige Informationen und die Typen sind klar spezifiziert, aber die tatsächlichen Methodenaufrufe sind weniger sichtbar und (meiner Meinung nach) nicht so klar.
Ohne Verwendung lokaler Variablen: Es ist übersichtlicher und die Methodenaufrufe sind sichtbarer, aber Sie können weitere Informationen zu den zurückgegebenen Werten anfordern. Einige IDEs können dies jedoch anzeigen.
Drei weitere Kommentare:
Meiner Meinung nach kann das Hinzufügen von Code, der keine funktionale Verwendung hat, manchmal verwirrend sein, da der Leser feststellen muss, dass er tatsächlich keine funktionale Verwendung hat und nur zur "Dokumentation" dient. Wenn diese Methode beispielsweise 100 Zeilen lang wäre, wäre es nicht offensichtlich, dass die lokalen Variablen (und damit das Ergebnis des Methodenaufrufs) zu einem späteren Zeitpunkt nicht erforderlich sind, es sei denn, Sie lesen die gesamte Methode.
Das Hinzufügen der lokalen Variablen bedeutet, dass Sie deren Typen angeben müssen. Dies führt zu einer Abhängigkeit im Code, die ansonsten nicht vorhanden wäre. Wenn sich der Rückgabetyp der Methoden geringfügig ändern würde (z. B. wurde er umbenannt), müssten Sie Ihren Code aktualisieren, während Sie dies ohne die lokalen Variablen nicht tun würden.
Das Debuggen mit lokalen Variablen könnte einfacher sein, wenn Ihr Debugger keine von Methoden zurückgegebenen Werte anzeigt. Aber das Update dafür ist, die Mängel in den Debuggern zu beheben, nicht den Code zu ändern.
quelle
with
Aussagen. Es wären normale Formatierungskonventionen in Java.Hier gibt es eine Spannung von Motivationen. Die Einführung temporärer Variablen kann das Lesen von Code erleichtern. Sie können jedoch auch andere mögliche Umgestaltungen verhindern und erschweren, z. B. Extraktionsmethode und Temp durch Abfrage ersetzen . Diese letzteren Arten von Refactorings bieten, falls angebracht, häufig viel größere Vorteile als die temporäre Variable.
Zu den Beweggründen für diese letztgenannten Umgestaltungen schreibt Fowler :
Verwenden Sie also temporäre Dateien, wenn sie den Code besser lesbar machen, insbesondere, wenn dies für Sie und Ihr Team eine lokale Norm ist. Beachten Sie jedoch, dass es dadurch manchmal schwieriger wird, größere alternative Verbesserungen zu erkennen. Wenn Sie Ihre Fähigkeit entwickeln können, zu spüren, wann es sich lohnt, auf solche Zeiträume zu verzichten und sich dabei wohler zu fühlen, dann ist das wahrscheinlich eine gute Sache.
FWIW Ich persönlich habe es zehn Jahre lang vermieden, Fowlers Buch "Refactoring" zu lesen, weil ich mir vorstellte, dass es zu solchen relativ einfachen Themen nicht viel zu sagen gibt. Ich habe mich völlig geirrt. Als ich es schließlich las, änderte es meine täglichen Codierungspraktiken zum Besseren.
quelle
Nun, es ist eine gute Idee, lokale Variablen zu eliminieren, wenn Sie den Code dadurch besser lesbar machen können . Ihr langer Einzeiler ist nicht lesbar, aber dann folgt er einem ziemlich ausführlichen OO-Stil. Wenn du es auf so etwas wie reduzieren könntest
dann würde ich sagen, dass es wahrscheinlich eine gute Idee wäre. Vielleicht können Sie Hilfsmethoden einführen, um es auf etwas Ähnliches zu reduzieren. Wenn Code wie dieser mehrmals vorkommt, lohnt es sich möglicherweise.
quelle
Betrachten wir hier das Gesetz von Demeter . Im Wikipedia-Artikel zu LoD heißt es:
Eine der Konsequenzen der Befolgung dieses Gesetzes besteht darin, dass Sie vermeiden sollten, Methoden von Objekten aufzurufen, die von anderen Methoden in einer langen, gepunkteten Zeichenfolge zurückgegeben werden, wie im obigen zweiten Beispiel gezeigt:
Es ist wirklich schwierig herauszufinden, was dies tut. Um es zu verstehen, müssen Sie verstehen, was jede Prozedur tut, und dann entschlüsseln, welche Funktion für welches Objekt aufgerufen wird. Der erste Codeblock
zeigt deutlich, was Sie tun möchten: Sie erhalten ein PowerManager-Objekt, erhalten ein WakeLock-Objekt vom PowerManager und erhalten dann das wakeLock. Das obige Beispiel folgt Regel 3 von LoD - Sie instanziieren diese Objekte in Ihrem Code und können sie daher verwenden, um das zu tun, was Sie benötigen.
Vielleicht sollten Sie beim Erstellen von Software auch der Übersichtlichkeit halber schreiben, nicht der Kürze halber. 90% der gesamten Softwareentwicklung ist Wartung. Schreiben Sie niemals einen Code, den Sie nicht gerne pflegen würden.
Viel Glück.
quelle
Zu beachten ist, dass Code häufig in verschiedenen "Tiefen" gelesen wird. Dieser Code:
ist leicht zu "überfliegen". Es sind 3 Aussagen. Zuerst kommen wir mit einem
PowerManager
. Dann kommen wir mit einemWakeLock
. Dann haben wiracquire
diewakeLock
. Ich kann das sehr leicht erkennen, wenn ich mir den Anfang jeder Zeile ansehe. Einfache Variablenzuweisungen sind zum Teil sehr leicht als "Typ varName = ..." zu erkennen und überfliegen geistig das "...". Ebenso ist die letzte Aussage offensichtlich nicht die Form der Zuweisung, sondern es handelt sich nur um zwei Namen, so dass das "Wesentliche" sofort ersichtlich ist. Oft ist das alles, was ich wissen müsste, wenn ich nur versuchen würde zu antworten: "Was macht dieser Code?" auf einem hohen Niveau.Wenn ich einem subtilen Fehler nachjage, von dem ich denke, dass er hier ist, muss ich das natürlich viel genauer durchgehen und werde mich tatsächlich an die "..." erinnern. Die separate Anweisungsstruktur hilft mir jedoch immer noch dabei, eine Anweisung nach der anderen auszuführen (besonders nützlich, wenn ich mich eingehender mit der Implementierung der in jeder Anweisung aufgerufenen Dinge befassen muss. Wenn ich zurückkomme, habe ich "eine Einheit" vollständig verstanden. und kann dann mit der nächsten Anweisung fortfahren).
Jetzt ist alles eine Aussage. Die Struktur der obersten Ebene ist nicht so einfach zu überfliegen; In der Originalversion des OP hätte ich ohne Zeilenumbrüche und Einrückungen, um eine Struktur visuell zu kommunizieren, Klammern zählen müssen, um sie in eine Folge von 3 Schritten zu dekodieren. Wenn einige der mehrteiligen Ausdrücke ineinander verschachtelt und nicht als eine Kette von Methodenaufrufen angeordnet sind, könnte dies immer noch ähnlich aussehen. Daher muss ich vorsichtig sein, wenn ich dem vertraue, ohne Klammern zu zählen. Und wenn ich der Einrückung vertraue und nur bis zum letzten Punkt überfliege, was
.acquire()
sagt mir das alles ?Manchmal kann das aber auch das sein, was Sie wollen. Wenn ich Ihre Transformation auf halbem Wege anwende und schreibe:
Nun kommuniziert dies zu einem schnellen überfliegen "ein
WakeLock
, dann istacquire
es". Noch einfacher als die erste Version. Es ist sofort klar, dass es sich bei der erworbenen Sache um eine handeltWakeLock
. Wenn das Erhalten vonPowerManager
nur ein Unterdetail ist, das für den Punkt dieses Codes ziemlich unbedeutend ist, aber daswakeLock
ist wichtig, dann könnte es tatsächlich helfen, dasPowerManager
Zeug zu vergraben, so dass es natürlich ist, darüber hinweg zu schauen, wenn Sie nur versuchen, schnell ein zu bekommen Vorstellung davon, was dieser Code macht. Und nicht die Namensgebung in Verbindung steht , dass es wird nur einmal verwendet, und manchmal , das ist Was ist wichtig? (Wenn der Rest des Gültigkeitsbereichs sehr lang ist, muss ich alles lesen, um festzustellen, ob er jemals wieder verwendet wird. Die Verwendung expliziter Unterbereiche kann jedoch eine andere Möglichkeit sein, dies zu beheben, sofern Ihre Sprache dies unterstützt.)Daraus ergibt sich, dass alles vom Kontext und dem, was Sie kommunizieren möchten, abhängt. Wie beim Schreiben von Prosa in natürlicher Sprache gibt es immer viele Möglichkeiten, einen bestimmten Code zu schreiben, die hinsichtlich des Informationsgehalts grundsätzlich gleichwertig sind. Wie beim Schreiben von Prosa in natürlicher Sprache sollten Sie bei der Auswahl der Prosa im Allgemeinen keine mechanistischen Regeln anwenden, wie beispielsweise "lokale Variablen, die nur einmal vorkommen, entfernen". Eher wieWenn Sie sich dazu entschließen, Ihren Code aufzuschreiben, werden bestimmte Dinge hervorgehoben und andere weniger hervorgehoben. Sie sollten sich bemühen, diese Entscheidungen bewusst zu treffen (einschließlich der Entscheidung, aus technischen Gründen manchmal weniger lesbaren Code zu schreiben), basierend auf dem, was Sie tatsächlich hervorheben möchten. Denken Sie vor allem darüber nach, was Lesern helfen soll, die nur den Kern Ihres Codes (auf verschiedenen Ebenen) "verstehen" müssen, da dies weitaus häufiger vorkommt als ein sehr enges Lesen von Ausdruck zu Ausdruck.
quelle
getSystemService(POWER_SERVICE)
bekommt den Power Manager..newWakeLock
bekommt eine Wecksperre..acquire
erwirbt es. OK, ich kenne nicht alle Typen, aber ich kann das in der IDE herausfinden, wenn ich muss.return
Aus dem gleichen Grund möchte ich so schnell wie möglich von Methoden.Dies ist sogar ein Gegenmuster mit eigenem Namen: Train Wreck . Es wurden bereits mehrere Gründe genannt, um den Austausch zu vermeiden:
Überlegen Sie, ob diese Methode von anderen Objekten zu viel weiß. Die Verkettung von Methoden ist eine Alternative, mit der Sie die Kopplung verringern können.
Denken Sie auch daran, dass Verweise auf Objekte sehr billig sind.
quelle
Die gestellte Frage lautet "Sollten wir lokale Variablen entfernen, wenn wir können"?
Nein, du solltest nicht ausschließen, nur weil du kannst.
Sie sollten die Codierungsrichtlinien in Ihrem Shop befolgen.
Zum größten Teil erleichtern lokale Variablen das Lesen und Debuggen des Codes.
Mir gefällt, was du damit gemacht hast
PowerManager powerManager
. Für mich bedeutet Kleinschreibung, dass es sich nur um eine einmalige Verwendung handelt.Wenn Sie nicht sollten, ist, wenn die Variable teure Ressourcen halten wird. Viele Sprachen haben eine Syntax für eine lokale Variable, die bereinigt / freigegeben werden muss. In C # wird es verwendet.
quelle
using(new SQLConnection()) { /* ... */ }
es nicht auch legal wäre (ob es nützlich wäre, ist eine andere Sache :).Ein wichtiger Aspekt wurde in den anderen Antworten nicht erwähnt: Immer wenn Sie eine Variable hinzufügen, führen Sie einen veränderlichen Zustand ein. Dies ist normalerweise eine schlechte Sache, da es Ihren Code komplexer und damit schwieriger zu verstehen und zu testen macht. Natürlich ist das Problem umso kleiner, je kleiner der Gültigkeitsbereich der Variablen ist.
Was Sie wollen, ist eigentlich keine Variable, deren Wert geändert werden kann, sondern eine temporäre Konstante. Aus diesem Grund sollten Sie dies in Ihrem Code ausdrücken, wenn Ihre Sprache dies zulässt. In Java können Sie
final
und in C ++ können Sie verwendenconst
. In den meisten funktionalen Sprachen ist dies das Standardverhalten.Es ist richtig, dass lokale Variablen der am wenigsten schädliche Typ eines veränderlichen Zustands sind. Mitgliedsvariablen können viel mehr Probleme verursachen und statische Variablen sind noch schlimmer. Trotzdem finde ich es wichtig, in Ihrem Code so genau wie möglich auszudrücken, was er tun soll. Und es gibt einen großen Unterschied zwischen einer Variablen, die später geändert werden könnte, und einem bloßen Namen für ein Zwischenergebnis. Wenn Sie diesen Unterschied in Ihrer Sprache ausdrücken können, tun Sie es einfach.
quelle
getFoo()
. Wenn ich eine lokale Deklaration vermeide,if(getFoo() > 10) alert(getFoo());
erhalte ich möglicherweise Aber getFoo () gibt bei zwei verschiedenen Aufrufen möglicherweise unterschiedliche Werte zurück. Ich könnte eine Warnung mit einem Wert kleiner oder gleich 10 senden, was bestenfalls verwirrend ist und als Fehler auf mich zurückkommt. Diese Art von Dingen gewinnt mit der Parallelität an Bedeutung. Die lokale Zuordnung ist atomar.PowerManager
Instanz tun , nachdem du diese Methode aufgerufen hast ? Lassen Sie mich den Rest der Methode überprüfen .... mmm ok nein. Und diesesWakeLock
Ding hast du ... was machst du damit (scannt noch mal den Rest der Methode) ... mmm nochmal nichts ... ok also warum sind sie da? Oh ja, sollte besser lesbar sein ... aber ohne sie wirst du sie sicher nicht mehr benutzen, so dass ich den Rest der Methode nicht lesen muss.final
eine lokale Variable in einer Methode benötigt wird, ist Ihre Methode zu lang.