複数の条件を持つifステートメントをフォーマットする最良の方法


88

ifステートメントをフォーマットする最良の方法である2つ以上の条件に基づいて実行するコードがある場合は、

最初の例:-

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

2番目の例:-

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

これは、各条件が長い関数名か何かである可能性があることを念頭に置いて理解し、読むのが最も簡単です。


このページの誰も「速い」または「パフォーマンス」という部分文字列について言及していないのは残念です。それは私が学ぶためにここに来たものです。
Dreamspace社長

回答:


132

私はオプションAを好みます

bool a, b, c;

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

特に長い変数/メソッド条件がある場合は、それらを改行するだけです

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

さらに複雑な場合は、ifステートメントの外で条件メソッドを個別に実行することを検討します

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オプション 'B'の唯一の理由elseは、条件ごとに実行する個別の関数がある場合です。

例えば

if( a )
{
    if( b )
    {
    }
    else
    {
        //Do Something Else B
    }
}
else
{
   //Do Something Else A
}

私はそれが好きです。私はメソッドのアイデアの大ファンではありませんが、メソッドが既に存在し、ブール値を返す場合を除きます。
Thomas Owens、

2
2番目の例では、理由なしにすべてを評価していませんか?
Odys

条件の前に「&&」を使用します。例と同じ文字長の条件を持つのは難しいです。
ダーコフ

28

他の回答は、なぜ最初のオプションが通常最良であるかを説明しています。ただし、複数の条件がある場合は、オプション1で条件チェックを実行する個別の関数(またはプロパティ)を作成することを検討してください。これにより、少なくとも適切なメソッド名を使用すると、コードが非常に読みやすくなります。

if(MyChecksAreOk()) { Code to execute }

...

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

条件がローカルスコープ変数のみに依存している場合、新しい関数を静的にして必要なすべてを渡すことができます。ミックスがある場合は、地元のものを渡します。


2
これが最も効果的で、後で条件を追加するのが簡単であることがわかりました
pbojinov

最初は+1に眉を上げましたが、これは本当に最良の答えです。そのブール値isOkToDoWhateverをプロパティとして持つことは、非常に理にかなっています。
2012年

1
しかし、これは同じ複雑な条件を他の場所に移動するだけでなく、読みやすくする必要があるため、これで元の状態に戻します。それだけではないのですifステートメント可読性ではなく、条件の読みやすさ。
Robert Koritnik 2016年

@RobertKoritnik私はあなたの言っていることを理解していますが、読者が一度に考慮しなければならない複雑さを減らしたので、私たちは正方形に戻るとは思いません。彼女は条件を見るかもしれません、あるいは、彼女は条件が(うまくいけば)良い名前を持っている条件を使ってコードを見るかもしれません。少なくとも私はこれを簡単に理解できることが多いと思いますが、すべての詳細を1か所にまとめておくとよい場合もあります。いつものように、状況によります。
Torbjørn

適切なメソッド名とロジックのリファクタリングを利用するのは素晴らしい点です。
JB Lovell 2017年

10

最初の例は、より「読みやすい」です。

実際、私の意見では、「elseロジック」を追加する必要があるときはいつでも2番目のものを使用する必要がありますが、単純な条件付きの場合は最初のフレーバーを使用します。長い状態が心配な場合は、常に次の構文を使用できます。

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

幸運を!


9

質問は尋ねられ、これまでのところ、決定は純粋に「構文」の根拠に基づいて行われるべきであるかのように答えられています。

if内でいくつかの条件をどのようにレイアウトするかについての正しい答えは、「セマンティクス」にも依存するべきだと私は言うでしょう。したがって、条件は「概念的に」一緒に行くものに従って分類され、グループ化されるべきです。

2つのテストが実際に同じコインの両面である場合。(x> 0)&&(x <= 100)の場合は、同じ行にまとめます。別の条件が概念的にはるかに遠い場合。user.hasPermission(Admin())を独自の行に配置します

例えば。

if user.hasPermission(Admin()) {
   if (x >= 0) && (x < 100) {
      // do something
   }
}

7
if (   ( single conditional expression A )
    && ( single conditional expression B )
    && ( single conditional expression C )
   )
{
   opAllABC();
}
else
{
   opNoneABC();
}

if-elseステートメントで複数の条件式を次のようにフォーマットします。

  1. 強化され、読みやすくするためにできます
    。最初に示されている式のすべての2項論理演算{&&、||}
    b。各バイナリ演算の両方の条件付きオペランドは、垂直方向に整列しているため明白
    です。入れ子にされた論理式の操作は、文を節の中に入れ子にするのと同じように、インデントを使用して明白になります
  2. 明示的な括弧が必要です(演算子の優先順位規則には依存しません)
    。これにより、一般的な静的解析エラーを回避できます
  3. デバッグが容易になり
    ます。
    a だけで個々の単一条件テストを無効にする// b。個々の
    テストセグの直前または直後にブレークポイントを設定します...
// 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
{
   ... ;
}

これが私の方法です。私の唯一の問題は、これをオプションとして提供するコード美容
ツール


3

最初のものは、左から右に読むと次のようになるので、より簡単です。「何かAND何かELSE AND何かELTHEN THEN」、これは理解しやすい文です。2番目の例は、「もしも何かが何かならTHEN何か他のならTHEN何か他のTHENなら」という読み方は不器用です。

また、句でいくつかのORを使用したい場合は、2番目のスタイルでどのように使用しますか?


1

switch...caseプログラミング言語がサポートしている場合、ステートメントは、この状況で整頓されたコードを書くための最良の方法だと思います。

switch (//variable or Boolean) {
  case //Condition A:
  case //Condition B:
  case //Condition C:
    //Code to execute;
}

それはいいかもしれませんが、それは「短絡」/遅延評価の「利点」を取り除きます。
TheLibrarian 2017

この答えは明らかに間違っており、実際には危険です。問題は、接続条件についてです。switchステートメントは、選言的条件のソリューションにすぎません。
egyik

0

Perlではこれを行うことができます:

{
  ( 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
}

いずれかの条件が失敗した場合は、ブロックの後に続行されます。ブロック後に保持したい変数を定義する場合は、ブロックの前に定義する必要があります。


1
それはPerlishに見えます-「それは何をしますか?」センス;)しかし、慣れれば実際には読みやすいです。
Piskvorが

-2

私は長い間このジレンマに直面してきましたが、まだ適切な解決策を見つけることができません。私の意見では、最初に条件を取り除くことを試みるのが唯一の良い方法なので、突然それらの5つを比較することはありません。

他に提案されているような代替手段がない場合は、別のものに分解して名前を短くするか、それらをグループ化します。たとえば、すべてがtrueでなければならない場合は、「xの配列にfalseがない場合は実行する」のようなものを使用します。

すべてが失敗した場合、@ Eoin Campbellはかなり良いアイデアを出しました。


これは、既存の回答に新しいものを追加するものではありません。
ジャーニー

-4

条件が本当に複雑な場合、私は次のスタイルを使用します(PHPの実際の例):

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
        )
    )
)

の複数のレベルをネストするよりも、見やすく読みやすいと思いますif()。そして、このようないくつかのケースでは、if() {...}ブロック内で同じステートメントを何度も繰り返さなければならないため、複雑な条件を分割することができない場合があります。

また、コードに「空気」を加えることは常に良い考えだと私は信じています。読みやすさが大幅に向上します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.