Manchmal kann eine if
Anweisung ziemlich kompliziert oder lang sein. Aus Gründen der Lesbarkeit ist es daher besser, komplizierte Aufrufe vor dem zu extrahieren if
.
zB das:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
das mögen
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
(vorausgesetzt, das Beispiel ist nicht so schlecht, es dient nur zur Veranschaulichung. Stellen Sie sich andere Aufrufe mit mehreren Argumenten usw. vor.)
Aber mit dieser Extraktion habe ich die Kurzschlussbewertung (SCE) verloren.
- Verliere ich wirklich jedes Mal SCE? Gibt es ein Szenario, in dem der Compiler "es optimieren" und dennoch SCE bereitstellen darf?
- Gibt es Möglichkeiten, die verbesserte Lesbarkeit des zweiten Snippets beizubehalten, ohne SCE zu verlieren?
Antworten:
Eine natürliche Lösung würde so aussehen:
Dies hat den Vorteil, dass es leicht zu verstehen ist, auf alle Fälle anwendbar ist und ein Kurzschlussverhalten aufweist.
Dies war meine anfängliche Lösung: Ein gutes Muster in Methodenaufrufen und for-Schleifenkörpern ist das Folgende:
Man erhält die gleichen guten Leistungsvorteile der Kurzschlussbewertung, aber der Code sieht besser lesbar aus.
quelle
if
" ist auch ein Zeichen dafür, dass Ihre Funktion oder Methode zu groß ist und in kleinere aufgeteilt werden sollte. Es ist nicht immer der beste Weg, aber sehr oft!b2
richtig und Sie würden bekommensomeConditionAndSomeotherConditionIsTrue
, nicht super aussagekräftig. Außerdem muss ich während dieser Übung eine Reihe von Variablen auf meinem mentalen Stapel behalten (und tbh, bis ich aufhöre, in diesem Bereich zu arbeiten). Ich würde mich für dieSJuan76
Lösung Nummer 2 entscheiden oder einfach das Ganze in eine Funktion einbauen.Ich neige dazu, Bedingungen in mehrere Zeilen aufzuteilen, dh:
Selbst wenn Sie mit mehreren Operatoren (&&) arbeiten, müssen Sie nur die Einrückung für jedes Klammerpaar vorantreiben. SCE setzt immer noch ein - es müssen keine Variablen verwendet werden. Das Schreiben von Code auf diese Weise machte es mir schon seit Jahren viel besser lesbar. Komplexeres Beispiel:
quelle
Wenn Sie lange Ketten von Bedingungen haben und einige der Kurzschlüsse beibehalten möchten, können Sie temporäre Variablen verwenden, um mehrere Bedingungen zu kombinieren. Wenn Sie Ihr Beispiel nehmen, wäre es möglich, z
Wenn Sie einen C ++ 11-fähigen Compiler haben, können Sie Lambda-Ausdrücke verwenden , um Ausdrücke zu Funktionen zu kombinieren, ähnlich wie oben:
quelle
1) Ja, Sie haben keine SCE mehr. Sonst hättest du das
funktioniert auf die eine oder andere Weise, je nachdem, ob es
if
später eine Aussage gibt. Viel zu komplex.2) Dies basiert auf Meinungen, aber für einigermaßen komplexe Ausdrücke können Sie Folgendes tun:
Wenn es viel zu komplex ist, besteht die offensichtliche Lösung darin, eine Funktion zu erstellen, die den Ausdruck auswertet und aufruft.
quelle
Sie können auch verwenden:
und SCE wird funktionieren.
Aber es ist nicht viel lesbarer als zum Beispiel:
quelle
b = b || otherComplicatedStuff();
und @SargeBorsch nimmt eine Bearbeitung vor, um SCE zu entfernen. Vielen Dank, dass Sie mich über diese Änderung @Ant informiert haben.Ich denke nicht, dass eine solche Optimierung erlaubt ist;
OtherComplicatedFunctionCall()
könnte insbesondere einige Nebenwirkungen haben.Ich ziehe es vor, es in eine Funktion oder eine Variable mit einem beschreibenden Namen umzugestalten. Dadurch bleiben sowohl die Kurzschlussbewertung als auch die Lesbarkeit erhalten:
Und wenn wir
getSomeResult()
basierend aufSomeComplicatedFunctionCall()
und implementierenOtherComplicatedFunctionCall()
, können wir sie rekursiv zerlegen, wenn sie noch kompliziert sind.quelle
Nein, tust du nicht, aber es wird anders angewendet:
Hier wird der Compiler nicht einmal ausgeführt,
OtherComplicatedFunctionCall()
wennSomeComplicatedFunctionCall()
true zurückgegeben wird.Hierbei können beide Funktionen werden ausgeführt werden, da sie in gespeichert werden müssen ,
b1
undb2
. Ff wirdb1 == true
dannb2
nicht ausgewertet (SCE). WurdeOtherComplicatedFunctionCall()
aber schon ausgeführt.Wenn
b2
es nirgendwo anders verwendet wird, ist der Compiler möglicherweise intelligent genug, um den Funktionsaufruf im if zu integrieren, wenn die Funktion keine beobachtbaren Nebenwirkungen aufweist.Kommt darauf an. Haben Sie brauchen
OtherComplicatedFunctionCall()
wegen der Nebenwirkungen oder die Performance - Einbußen der Funktion auszuführen ist minimal , dann sollten Sie den zweiten Ansatz zur besseren Lesbarkeit verwenden. Andernfalls bleiben Sie beim ersten Ansatz bei SCE.quelle
Eine andere Möglichkeit, die kurzschließt und die Bedingungen an einem Ort hat:
Sie können die Schleife in eine Funktion einfügen und die Funktion eine Liste von Bedingungen akzeptieren lassen und einen booleschen Wert ausgeben.
quelle
Sehr seltsam: Sie sprechen von Lesbarkeit, wenn niemand die Verwendung von Kommentaren im Code erwähnt:
Darüber hinaus gehe ich meinen Funktionen immer einige Kommentare voraus, über die Funktion selbst, über ihre Eingabe und Ausgabe, und manchmal füge ich ein Beispiel hinzu, wie Sie hier sehen können:
Offensichtlich kann die für Ihre Kommentare zu verwendende Formatierung von Ihrer Entwicklungsumgebung abhängen (Visual Studio, JavaDoc unter Eclipse, ...).
Ich gehe davon aus, dass Sie mit SCE Folgendes meinen:
quelle
Die Lesbarkeit ist erforderlich, wenn Sie in einem Unternehmen arbeiten und Ihr Code von einer anderen Person gelesen wird. Wenn Sie ein Programm für sich selbst schreiben, liegt es an Ihnen, ob Sie die Leistung für verständlichen Code opfern möchten.
quelle