Beste Methode zum Formatieren einer if-Anweisung mit mehreren Bedingungen

87

Wenn Sie möchten, dass Code basierend auf zwei oder mehr Bedingungen ausgeführt wird, was ist der beste Weg, um diese if-Anweisung zu formatieren?

erstes Beispiel: -

if(ConditionOne && ConditionTwo && ConditionThree)
{
   Code to execute
}

Zweites Beispiel: -

if(ConditionOne)
{
   if(ConditionTwo )
   {
     if(ConditionThree)
     {
       Code to execute
     }
   }
}

Dies ist am einfachsten zu verstehen und zu lesen, wenn man bedenkt, dass jede Bedingung ein langer Funktionsname oder etwas anderes sein kann.

Guy Coder
quelle
Schade, dass niemand auf dieser Seite den Teilstring "schnell" oder "Leistung" erwähnt. Das bin ich hergekommen, um zu lernen.
Dreamspace Präsident

Antworten:

132

Ich bevorzuge Option A.

bool a, b, c;

if( a && b && c )
{
   //This is neat & readable
}

Wenn Sie besonders lange Variablen / Methodenbedingungen haben, können Sie diese einfach unterbrechen

if( VeryLongConditionMethod(a) &&
    VeryLongConditionMethod(b) &&
    VeryLongConditionMethod(c))
{
   //This is still readable
}

Wenn sie noch komplizierter sind, würde ich in Betracht ziehen, die Bedingungsmethoden separat außerhalb der if-Anweisung auszuführen

bool aa = FirstVeryLongConditionMethod(a) && SecondVeryLongConditionMethod(a);
bool bb = FirstVeryLongConditionMethod(b) && SecondVeryLongConditionMethod(b);
bool cc = FirstVeryLongConditionMethod(c) && SecondVeryLongConditionMethod(c);

if( aa && bb && cc)
{
   //This is again neat & readable
   //although you probably need to sanity check your method names ;)
}

IMHO Der einzige Grund für die Option 'B' wäre, wenn Sie elsefür jede Bedingung separate Funktionen ausführen müssen.

z.B

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}
Eoin Campbell
quelle
Ich mag das. Obwohl ich kein großer Fan der Methodenidee bin, es sei denn, die Methoden existieren bereits und geben einen booleschen Wert zurück.
Thomas Owens
2
Bewerten Sie im zweiten Beispiel nicht alles ohne Grund?
Odys
Ich würde das '&&' vor der Bedingung verwenden. Es ist schwierig, Bedingungen mit der gleichen Zeichenlänge wie im Beispiel zu haben.
Darkov
28

Andere Antworten erklären, warum die erste Option normalerweise die beste ist. Wenn Sie jedoch mehrere Bedingungen haben, sollten Sie eine separate Funktion (oder Eigenschaft) erstellen, die die Bedingungsprüfungen in Option 1 durchführt. Dies erleichtert das Lesen des Codes erheblich, zumindest wenn Sie gute Methodennamen verwenden.

if(MyChecksAreOk()) { Code to execute }

...

private bool MyChecksAreOk()
{ 
    return ConditionOne && ConditionTwo && ConditionThree;
}

Wenn die Bedingungen nur von lokalen Bereichsvariablen abhängen, können Sie die neue Funktion statisch machen und alles übergeben, was Sie benötigen. Wenn es eine Mischung gibt, geben Sie die lokalen Sachen ein.

Torbjørn
quelle
2
Ich fand dies am effektivsten und am
einfachsten
+1 Zuerst habe ich eine Augenbraue hochgezogen, aber das ist wirklich die beste Antwort imho. diesen Booleschen Wert isOkToDoWhateverals Eigenschaft zu haben, macht sehr viel Sinn.
grinch
1
Dies verschiebt jedoch den gleichen komplexen Zustand an eine andere Stelle, an der er auch lesbar sein muss, sodass wir damit wieder auf dem ersten Platz sind. Es geht nicht nur um die ifLesbarkeit von Anweisungen, sondern auch um die Lesbarkeit von Bedingungen.
Robert Koritnik
@RobertKoritnik Ich verstehe, was Sie sagen, aber ich glaube nicht, dass wir wieder auf dem ersten Platz sind, weil wir die Komplexität reduziert haben, die der Leser auf einmal berücksichtigen muss. Sie kann sich die Bedingungen ansehen, ODER sie kann sich den Code unter Verwendung der Bedingungen ansehen, bei denen die Bedingungen einen (hoffentlich) schönen Namen haben. Zumindest finde ich das oft leichter zu verstehen, aber manchmal ist es auch schön, alle Details an einem Ort zu haben. Wie immer kommt es darauf an.
Torbjørn
Toller Punkt, gute Methodennamen zu verwenden und die Logik umzugestalten.
JB Lovell
10

Das erste Beispiel ist "leichter zu lesen".

Eigentlich sollten Sie meiner Meinung nach nur die zweite verwenden, wenn Sie eine "else-Logik" hinzufügen müssen, aber für eine einfache Bedingung verwenden Sie die erste Variante. Wenn Sie sich Sorgen über die lange Dauer der Bedingung machen, können Sie immer die nächste Syntax verwenden:

if(ConditionOneThatIsTooLongAndProbablyWillUseAlmostOneLine
                 && ConditionTwoThatIsLongAsWell
                 && ConditionThreeThatAlsoIsLong) { 
     //Code to execute 
}

Viel Glück!

David Santamaria
quelle
9

Die Frage wurde gestellt und bisher beantwortet, als ob die Entscheidung nur aus "syntaktischen" Gründen getroffen werden sollte.

Ich würde sagen, dass die richtige Antwort darauf, wie Sie eine Reihe von Bedingungen innerhalb eines if auslegen , auch von der "Semantik" abhängen sollte . Die Bedingungen sollten also aufgeschlüsselt und danach gruppiert werden, welche Dinge "konzeptionell" zusammenpassen.

Wenn zwei Tests wirklich zwei Seiten derselben Medaille sind, z. Wenn (x> 0) && (x <= 100), setzen Sie sie in derselben Zeile zusammen. Wenn eine andere Bedingung konzeptionell weit entfernter ist, z. user.hasPermission (Admin ()) setzt es dann in eine eigene Zeile

Z.B.

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}
Interstar
quelle
7
if (   ( single conditional expression A )
    && ( single conditional expression B )
    && ( single conditional expression C )
   )
{
   opAllABC();
}
else
{
   opNoneABC();
}

Formatieren Sie mehrere bedingte Ausdrücke in einer if-else-Anweisung folgendermaßen:

  1. ermöglicht eine verbesserte Lesbarkeit:
    a. alle binären logischen Operationen {&&, ||} im zuerst gezeigten Ausdruck
    b. Beide bedingten Operanden jeder Binäroperation sind offensichtlich, da sie vertikal ausgerichtet sind.
    c. Operationen mit verschachtelten logischen Ausdrücken werden durch Einrücken offensichtlich gemacht, genau wie Verschachtelungsanweisungen in Klauseln
  2. erfordert explizite Klammern (nicht auf Vorrangregeln für Operatoren angewiesen)
    a. Dies vermeidet häufige statische Analysefehler
  3. ermöglicht ein einfacheres Debuggen
    a. Deaktivieren Sie einzelne einzelne bedingte Tests mit nur a //
    b. Setzen Sie kurz vor oder nach einem einzelnen Test-
    Ceg einen Haltepunkt ...
// disable any single conditional test with just a pre-pended '//'
// set a break point before any individual test
// syntax '(1 &&' and '(0 ||' usually never creates any real code
if (   1
    && ( single conditional expression A )
    && ( single conditional expression B )
    && (   0
        || ( single conditional expression C )
        || ( single conditional expression D )
       )
   )
{
   ... ;
}

else
{
   ... ;
}
Sean
quelle
Das ist meine Methode. Das einzige Problem, das ich habe, ist, dass ich noch keinen Code-Verschönerer gefunden habe, der dies als Option
anbietet
4

Das zweite ist ein klassisches Beispiel für das Pfeil-Anti-Muster. Ich würde es also vermeiden ...

Wenn Ihre Bedingungen zu lang sind, extrahieren Sie sie in Methoden / Eigenschaften.

Omar Kooheji
quelle
3

Der erste ist einfacher, denn wenn Sie ihn von links nach rechts lesen, erhalten Sie: "Wenn etwas UND etwas anderes UND etwas anderes DANN", was ein leicht verständlicher Satz ist. Das zweite Beispiel lautet "Wenn etwas DANN, wenn etwas anderes DANN, wenn etwas anderes DANN", was ungeschickt ist.

Überlegen Sie auch, ob Sie einige ORs in Ihrer Klausel verwenden möchten - wie würden Sie das im zweiten Stil tun?

RB.
quelle
1

Ich glaube, switch...caseAussage ist der beste Weg, um unter diesen Umständen ordentlichen Code zu schreiben, wenn die Programmiersprache dies unterstützt.

switch (//variable or Boolean) {
  case //Condition A:
  case //Condition B:
  case //Condition C:
    //Code to execute;
}
Kent
quelle
Es mag schön sein, aber es beseitigt den "Vorteil" der "Kurzschluss" / faulen Bewertung.
TheLibrarian
Diese Antwort ist einfach falsch und tatsächlich gefährlich. Die Frage betrifft einen konjunktiven Zustand. Switch-Anweisungen sind nur eine Lösung für disjunktive Bedingungen.
Egyik
0

In Perl können Sie dies tun:

{
  ( VeryLongCondition_1 ) or last;
  ( VeryLongCondition_2 ) or last;
  ( VeryLongCondition_3 ) or last;
  ( VeryLongCondition_4 ) or last;
  ( VeryLongCondition_5 ) or last;
  ( VeryLongCondition_6 ) or last;

  # Guarded code goes here
}

Wenn eine der Bedingungen fehlschlägt, wird sie nach dem Blockieren einfach fortgesetzt. Wenn Sie Variablen definieren, die Sie nach dem Block behalten möchten, müssen Sie sie vor dem Block definieren.

Brad Gilbert
quelle
1
Das sieht perlisch aus - im "es macht WAS?" Sinn;) Aber es ist tatsächlich lesbar, sobald Sie sich daran gewöhnt haben.
Piskvor verließ das Gebäude
-2

Ich bin schon lange mit diesem Dilemma konfrontiert und kann immer noch keine richtige Lösung finden. Meiner Meinung nach ist es nur ein guter Weg, zuerst zu versuchen, die Bedingungen vorher loszuwerden, damit Sie nicht plötzlich 5 davon vergleichen.

Wenn es keine Alternative gibt, dann, wie andere vorgeschlagen haben - zerlegen Sie sie in separate und kürzen Sie die Namen oder gruppieren Sie sie. Wenn z. B. alles wahr sein muss, verwenden Sie etwas wie "Wenn in einem Array von x kein Falsches ausgeführt wird".

Wenn alles fehlschlägt, gab @Eoin Campbell ziemlich gute Ideen.

Tiper Loc
quelle
Dies fügt den bereits vorhandenen Antworten nichts Neues hinzu.
Jerney
-4

Wenn die Bedingung sehr komplex ist, verwende ich den folgenden Stil (PHP-Beispiel aus dem wirklichen Leben):

if( $format_bool &&
    (
        ( isset( $column_info['native_type'] )
            && stripos( $column_info['native_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['driver:decl_type'] )
            && stripos( $column_info['driver:decl_type'], 'bool' ) !== false
        )
        || ( isset( $column_info['pdo_type'] )
            && $column_info['pdo_type'] == PDO::PARAM_BOOL
        )
    )
)

Ich glaube, es ist schöner und lesbarer als das Verschachteln mehrerer Ebenen von if(). Und in einigen Fällen wie diesen können Sie komplexe Zustände einfach nicht in Teile zerlegen, da Sie sonst dieselben Anweisungen im if() {...}Block viele Male wiederholen müssten .

Ich glaube auch, dass das Hinzufügen von "Luft" zum Code immer eine gute Idee ist. Es verbessert die Lesbarkeit erheblich.

CodeDriller
quelle