Aus dem Code Complete- Buch stammt das folgende Zitat:
"Setzen Sie den Normalfall nach dem
if
anstatt nach demelse
"
Was bedeutet, dass Ausnahmen / Abweichungen vom Standardpfad in den else
Fall gestellt werden sollten.
Aber der Pragmatic Programmer lehrt uns, "früh abzustürzen" (S. 120).
Welche Regel soll ich beachten?
if
Zweige zurückkehrt, verwenden Sie ihn zuerst. Und vermeiden Sie denelse
Rest des Codes, den Sie bereits zurückgegeben haben, wenn die Vorbedingungen fehlgeschlagen sind. Code ist einfacher zu lesen, weniger Einrückungen ...Antworten:
Bei "Früh abstürzen" geht es nicht darum, welche Codezeile früher in Textform kommt. Es weist Sie an, Fehler im frühestmöglichen Verarbeitungsschritt zu erkennen , damit Sie nicht versehentlich Entscheidungen treffen und Berechnungen auf der Grundlage eines bereits fehlerhaften Zustands durchführen.
In einem
if
/else
-Konstrukt wird nur einer der Blöcke ausgeführt, daher kann weder von einem "früheren" noch von einem "späteren" Schritt gesprochen werden. Wie man sie bestellt, ist daher eine Frage der Lesbarkeit, und "frühzeitig scheitern" geht nicht in die Entscheidung ein.quelle
if/else
Konstrukten spielt es wahrscheinlich keine Rolle. Aber diejenigen, die in einer Schleife oder mit vielen Anweisungen in jedem Block aufgerufen werden, können schneller ausgeführt werden, wenn die häufigste Bedingung zuerst vorliegt.Wenn Ihre
else
Anweisung nur Fehlercode enthält, sollte dieser höchstwahrscheinlich nicht vorhanden sein.Anstatt dies zu tun:
mach das
Sie möchten Ihren Code nicht tief verschachteln, nur um die Fehlerprüfung einzuschließen.
Und wie alle anderen bereits gesagt haben, sind die beiden Ratschläge kein Widerspruch. Bei der einen geht es um die Ausführungsreihenfolge , bei der anderen um die Codereihenfolge .
quelle
if
und einen außergewöhnlichen Fluss in den Block nach zu setzenelse
, nicht gilt, wenn Sie keinen habenelse
! Guard-Anweisungen wie diese sind die bevorzugte Form zur Behandlung von Fehlerbedingungen in den meisten Codierungsstilen.Sie sollten beiden folgen.
Der Hinweis "Crash early" / fail early bedeutet, dass Sie Ihre Eingaben so schnell wie möglich auf mögliche Fehler prüfen sollten.
Wenn Ihre Methode beispielsweise eine Größe oder Anzahl akzeptiert, von der angenommen wird, dass sie positiv ist (> 0), bedeutet dies, dass Sie zu Beginn der Methode auf diese Bedingung testen, anstatt darauf zu warten, dass der Algorithmus Unsinn erzeugt Ergebnisse.
Die Empfehlung, den Normalfall an die erste Stelle zu setzen, besagt, dass beim Testen auf eine Bedingung der wahrscheinlichste Pfad an erster Stelle stehen sollte. Dies hilft bei der Leistung (da die Verzweigungsvorhersage des Prozessors häufiger zutrifft) und der Lesbarkeit, da Sie keine Codeblöcke überspringen müssen, um herauszufinden, was die Funktion im Normalfall tut.
Dieser Ratschlag gilt nicht wirklich, wenn Sie auf eine Vorbedingung testen und sofort aussteigen (mithilfe von Asserts oder
if (!precondition) throw
Konstrukten), da es keine Fehlerbehandlung gibt, die beim Lesen des Codes übersprungen werden muss.quelle
if(cond){/*more likely code*/}else{/*less likely code*/}
schneller abläuft alsif(!cond){/*less likely code*/}else{/*more likely code*/}
aufgrund der Verzweigungsvorhersage. Ich würde denken, dass die Verzweigungsvorhersage weder aufif
dieelse
Aussage noch auf die Aussage voreingenommen ist und nur die Geschichte berücksichtigt. Wennelse
es also wahrscheinlicher ist, dass etwas passiert, sollte es in der Lage sein, dies genau so gut vorherzusagen. Ist diese Annahme falsch?Ich denke , @JackAidley hat es bereits gesagt , aber lassen Sie mich es so formulieren:
ohne Ausnahmen (zB C)
Im normalen Code-Fluss haben Sie:
In dem Fall "Fehler früh" lautet Ihr Code plötzlich:
Wenn Sie diese Muster erkennen - ein
return
in einemelse
(oder auchif
) Block, überarbeiten sie sofort so dass der Code in Frage stellt nicht einen hatelse
Block:In der echten Welt…
Dies vermeidet zu tiefes Verschachteln und erfüllt den Fall „Früh ausbrechen“ (hilft dabei, den Verstand und den Code-Fluss sauber zu halten) und verletzt nicht das „wahrscheinlichere
if
Teil in das Teil einfügen “, da es einfach keinenelse
Teil gibt .C
und aufräumenInspiriert von einer Antwort auf eine ähnliche Frage (die das falsch verstanden hat), gehen Sie wie folgt vor, um mit C aufzuräumen. Sie können dort einen oder zwei Austrittspunkte verwenden, hier einen für zwei Austrittspunkte:
Sie können sie zu einem Exit-Punkt zusammenfassen, wenn weniger Aufräumarbeiten erforderlich sind:
Diese Verwendung von
goto
ist völlig in Ordnung, wenn Sie damit umgehen können; Der Ratschlag, nicht zu verwenden,goto
richtet sich an Personen, die noch nicht selbst entscheiden können, ob eine Verwendung gut, akzeptabel, schlecht, Spaghetti-Code oder etwas anderes ist.Ausnahmen
Das oben Gesagte handelt von Sprachen ohne Ausnahmen, die ich selbst sehr bevorzuge (ich kann die explizite Fehlerbehandlung viel besser und mit viel weniger Überraschung anwenden). Igli zitieren:
Aber hier ist ein Vorschlag, wie Sie es in einer Sprache mit Ausnahmen gut machen und wann Sie sie gut verwenden möchten:
Fehlerrückgabe trotz Ausnahmen
Sie können die meisten frühen
return
s durch das Auslösen einer Ausnahme ersetzen . Allerdings , Ihr normaler Programmablauf, dh jeden Code Fluss in dem das Programm nicht begegnen, na ja, eine Ausnahme ... eine Fehlerbedingung, etc. zu jagen, wird nicht alle Ausnahmen erhöhen.Das bedeutet, dass…
… Ist okay, aber…
… ist nicht. Grundsätzlich ist eine Ausnahme kein Kontrollflusselement . Dies lässt Operations auch komisch aussehen („diese Java ™ -Programmierer weisen uns immer darauf hin, dass diese Ausnahmen normal sind“) und kann das Debuggen behindern (z. B. die IDE anweisen, bei jeder Ausnahme einfach zu brechen). Ausnahmen erfordern häufig, dass die Laufzeitumgebung den Stapel abwickelt, um Rückverfolgungen usw. zu erzeugen. Es gibt wahrscheinlich weitere Gründe dafür.
Das läuft auf Folgendes hinaus: Verwenden Sie in einer Sprache, die Ausnahmen unterstützt, alles, was der vorhandenen Logik und dem vorhandenen Stil entspricht und sich natürlich anfühlt. Wenn Sie etwas von Grund auf neu schreiben, vereinbaren Sie dies frühzeitig. Wenn Sie eine Bibliothek von Grund auf neu schreiben, denken Sie an Ihre Konsumenten. (Verwenden Sie es niemals
abort()
in einer Bibliothek.) Aber was auch immer Sie tun, lassen Sie als Faustregel keine Ausnahme auslösen, wenn der Betrieb danach normal (mehr oder weniger) fortgesetzt wird.Allgemeine Hinweise Ausnahmen
Versuchen Sie zunächst, alle programminternen Ausnahmen zu verwenden, die vom gesamten Entwicklerteam vereinbart wurden. Grundsätzlich planen sie. Verwenden Sie sie nicht im Überfluss. Manchmal ist sogar in C ++, Java ™, Python eine Fehlerrückgabe besser. Manchmal ist es nicht so; benutze sie mit Gedanken.
quelle
goto fail;
in der Identität verborgen bleibt.Meiner Meinung nach ist 'Guard Condition' eine der besten und einfachsten Möglichkeiten, Code lesbar zu machen. Ich hasse es wirklich, wenn ich
if
am Anfang der Methode sehe und denelse
Code nicht sehe , weil er nicht auf dem Bildschirm ist. Ich muss nach unten scrollen, nur um zu sehenthrow new Exception
.Setzen Sie die Schecks an den Anfang, damit der lesende Code nicht die gesamte Methode überspringen muss, sondern immer von oben nach unten scannen muss.
quelle
(@mirabilos Antwort ist ausgezeichnet, aber hier ist, wie ich über die Frage denke, um zu der gleichen Schlussfolgerung zu gelangen :)
Ich denke daran, dass ich (oder jemand anderes) später den Code meiner Funktion liest. Wenn ich die erste Zeile lese, kann ich keine Annahmen über meine Eingabe treffen (außer denjenigen, die ich sowieso nicht überprüfe). Mein Gedanke ist also: "Okay, ich weiß, dass ich Dinge mit meinen Argumenten anstellen werde. Aber zuerst wollen wir sie bereinigen." Ich sehe den Normalfall nicht als etwas Bedingtes, ich möchte betonen, dass er normal ist.
quelle
Diese Art der Bedingungsreihenfolge hängt von der Kritik des betreffenden Codeabschnitts und davon ab, ob Standardeinstellungen verwendet werden können.
Mit anderen Worten:
A. Kritischer Abschnitt und keine Standardeinstellungen => Frühzeitig fehlschlagen
B. unkritischer Abschnitt und Standardwerte => Standardwerte im anderen Teil verwenden
C. Zwischenfälle => je nach Bedarf einzeln entscheiden
quelle