Welche Schritte und Maßnahmen kann ich ergreifen, um tiefe Einrückungen in meinem Code zu verhindern?
Welche Schritte und Maßnahmen kann ich ergreifen, um tiefe Einrückungen in meinem Code zu verhindern?
Antworten:
Tiefes Einrücken ist normalerweise kein Problem, wenn jede Funktion / Methode in Ihrem Programm nur eine einzige Aktion ausführt. Gelegentlich es könnte zu nisten conditionals ein paar Ebenen tief notwendig sein, aber ich kann ehrlich sagen , dass ich nur ein paar Mal in 12+ Jahre tief eingekerbt Code Kodierung geschrieben habe.
Das Beste, was Sie tun können, ist Methoden zu extrahieren:
int Step1(int state)
{
if (state == 100)
{
return Step2(state);
}
else
{
return Step3(state);
}
}
int Step2(int state)
{
if (state != 100)
{
throw new InvalidStateException(2, state);
}
// ....
}
if
Bedingungen. Im Extremfall erhalten Sie ausführbaren Pseudocode.
else
Blöcke fallen zu lassen.
Vielleicht könnten Sie Schutzklauseln in Betracht ziehen ?
Anstatt von
public void DoSomething(int value){
if (someCondition){
if(someOtherCondition){
if(yetAnotherCondition){
//Finally execute some code
}
}
}
}
Tun
public void DoSomething(int value){
if(!(someCondition && someOtherCondition && yetAnotherCondition)){
return;
//Maybe throw exception if all preconditions must be true
}
//All preconditions are safe execute code
}
Wenn Sie jemals eine Chance bekommen, empfehlen wir Ihnen, Code Complete von Steve McConnell zu lesen. Er hat viele gute Ratschläge zu diesen Themen.
http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/ref=pd_sim_b_6
Weitere Informationen zu "Schutzklauseln" finden Sie unter: https://sourcemaking.com/refactoring/replace-nested-conditional-with-guard-clauses
Invertiere dein if
s.
Anstatt von:
if (foo != null)
{
something;
something;
if (x)
{
something;
}
something;
}
else
{
boohoo;
}
Ich würde schreiben:
if (foo == null)
{
boohoo;
return;
}
something;
something;
if (x)
{
something;
}
something;
Gleiches gilt für if
- else
Blöcke. Wenn else
kürzer / weniger verschachtelt ist, machen Sie sie wieder rückgängig.
Überprüfen Sie die Parameterwerte an einer Stelle
Überprüfen Sie alle Parameter auf unzulässige Werte, sobald Sie Ihre Methode eingeben, und vergewissern Sie sich dann, dass Sie sicher sind. Es sorgt für besser lesbaren Code, erspart Ihnen jedoch später das Aufstapeln von bedingten Blöcken und das Verteilen dieser Überprüfungen auf die gesamte Subroutine.
If
s am Anfang des Codes, die den Ausführungsfluss aufgrund einer nicht erfüllten Bedingung anhalten, werden auch als Schutzklauseln bezeichnet , wie @JasonTuran hervorhob. Und das scheint so nah wie möglich an einem eindeutigen Namen zu sein.
Normalerweise habe ich gesehen, dass tief eingerückter Code normalerweise problematischer Code ist. Wenn Sie mit diesem Problem konfrontiert sind, treten Sie zurück und prüfen Sie, ob Ihre Funktion zu viele Aufgaben erfüllt.
Zur Beantwortung Ihrer Frage, ob eine so tiefe Einrückung erforderlich ist, schlage ich vor, dass Sie sie dort lassen. Aus dem einfachen Grund, dass in einem solchen Code der Einzug hilfreich ist, da es sich wahrscheinlich um ein sehr langes Stück Code handelt.
Teilen Sie verschachtelte Komponenten (insbesondere wiederholte) in separate Funktionen auf (dies ist einfacher, wenn Ihre Sprache Closures unterstützt) oder ersetzen Sie eine Reihe von verschachtelten Schleifen durch eine Rekursion.
Ziehen Sie statt vier auch zwei Leerzeichen ein.
Ich sehe tiefe Einkerbungen nicht als ein kategorisches Problem, das beseitigt werden muss (noch sehe ich Refactoring als die wahre Antwort auf alles).
In der Regel schreibe ich anstelle von verschachtelten ifs gerne logische Anweisungen:
if (foo && bar && baz)
eher, als
if foo
if bar
if baz
Ich habe es selbst nicht geglaubt, aber laut Code Complete ist dies ein geeigneter Ort break
(wenn Ihr Team an Bord ist). Ich würde mir vorstellen, dass dies mit C ++ - Programmierern akzeptabler ist, wenn break
sie in switch
Anweisungen verwendet werden, als mit Delphi-Programmierern break
, wenn Sie keine Lust haben, eine while
Schleife zu schreiben .
Einrückung ist in der Tat ein Kampfgedanke. Was ich gelernt habe, ist, die Methode zuerst in Teile zu teilen und dann mit einem seltsamen Trick alle folgenden Teile zu überspringen, wenn ein Teil fehlschlägt. Hier ist ein Beispiel :
Anstatt von :
{if (networkCardIsOn() == true)
{if (PingToServer() == true)
{if (AccesLogin(login,pass) == true)
{if (nextCondition == true)
...
}
}
}
Ich schreibe derzeit:
{vbContinue = true;
if (vbContinue) {
vbContinue = networkCardIsOn();
if (vbContinue == false) {
code to Handle This Error();
}
}
if (vbContinue) {
vbContinue = PingToServer();
if (vbContinue == false) {
code to HandleThisError2();
}
}
if (vbContinue) {
vbContinue = AccesLogin(login,pass);
if (vbContinue == false) {
HandleThisErrorToo();
}
}
...
Auf den ersten Blick ist mir das seltsam vorgekommen, aber seit ich das benutze, haben sich die Wartungskosten halbiert und mein Gehirn ist am Ende des Tages kühler.
Tatsächlich besteht der durch diese "Technik" eingeführte Vorteil darin, dass die Codekomplexität wirklich geteilt wird, weil der Code weniger dicht ist.
Während Sie den Code lesen, müssen Sie sich an nichts über die vergangenen Bedingungen erinnern: Wenn Sie sich an der Stelle X im Code befinden, sind die vorherigen Schritte bestanden und erfolgreich.
Ein weiterer Vorteil ist, dass der "Fluchtweg und die Fluchtbedingung" von allen verschachtelten "if-else" vereinfacht wird.