if / elseステートメントは、ケースの希少性またはそれらに対処する難しさによって整理されるべきですか?


18

私が今書いているコードの中には、次のようなものがあります。

if (uncommon_condition) {
    do_something_simple();
} else {
    do();
    something();
    long();
    and();
    complicated();
}

私の一部は、「それが書かれている方法で結構です。単純なケースが最初に、より複雑なケースが次に進むべきです」と考えています。しかし、別の部分は次のように述べています。「elseコードは、異常なケースを処理するifためであり、他のすべてのケースを処理するためです。」どちらが正しいですか、それとも望ましいですか?ifelse


4
条件の単純さ/理解しやすさで注文してください!残りは、オプティマイザー、分岐予測子、リファクタリングによって処理できます。
マルジャンヴェネマ14年

これが私たちが大金を支払われる理由です:これらの難しい決定をするために。

回答:


24

実行される可能性の順序。最も一般的で最も可能性の高い条件などを最初に確認する必要があります。

「それらの処理の難しさ」は、コード構造、抽象化などによって対処する必要があります。この例では、elseブロックを単一のメソッド呼び出しにリファクタリングできます。if句を同じ抽象レベルにする必要があります。

if ( ! LotteryWinner ) {
    GoToWorkMonday();
} else {
    PlanYearLongVacation();
}

6
パフォーマンスについて同意するかもしれません。しかし、再び、ほとんどのオプティマイザーと分岐予測子は完全にそれを処理できます。読みやすくするために、最も可能性の高いケースに、そうでないケースよりも大幅に多くの行がある場合に同意するかもしれません。しかし、私には、メソッドを使用するよりもメソッドを抽出する必要があることをすぐに示すでしょうnot。個人的に私はnot条件を避けることに集中します。それらは、「肯定的な」条件よりも理解するための認知負荷を誘発することが証明されており、コードの可読性/理解可能性に有害です。私はガードステートメントでのみそれらを使用する傾向があります。
マルジャンヴェネマ14年

2
@MarjanVenema、 "not" ingについてのあなたの主張を見ることができます。しかし、ダブルネガティブは本当の「ではない」WTFです。先日、コードでこれに遭遇しましたdoesNotAllowxxFiles = false。十分に悪いが、これを行うif(! doesNotAllowxxFiles)
レーダーボブ14年

うん、二重のネガ、andと組み合わせたネガおよび/またはor(sic!)、および名前にNotを含むmethod / varと組み合わせたネガは、毎回私の脳をひねります:
Marjan Venema 14年

何が起こっているのか理解できない場合は、次のようなことを行うと役立つことが多いと思います。simpleBool =(!(complexBool || randomfFlag))&&!randomFlag
TruthOf42

2
ガード条項(IFステートメントのTHEN部分には常に共通条件ではなく例外条件がある)の存在を除き、私はあなたに同意します。
ロバートハーヴェイ14年

5

読みやすさを高めてください。1つの方法は、長いコードブロックをelse部分に配置することです。

if (s == null)
     // short code
else 
     // long 
     // code
     // block

より読みやすい

if (s != null)
    // long
    // code
    // block
else
    // short code

2
なぜもっと読みやすいのですか?読みやすさの点で2つの間に違いはありません
ジョンデメトリオ

2
@JohnDemetriou Thenが短い場合、Elseはより見やすくなります。人々は最初に構造をスキャンし、次に意味を割り当てます。Elseを使用しないコードは、Elseを使用するコードとは異なるため、Elseをより見やすくする方がわかりやすいです。(雨が降っていない火曜日など、他のすべてのものが等しい)

4

固定されたルールなどはありませんが、使用方法について聞いたことがありますが、私はこのようにします

if(usual)
{
(more often)
}
else (unusual)
{
(rarely occurring)
}

しかし、両方が異なるプロパティを持つ同じ機能を持っている場合、1つの命令を保存できるように、通常ではなく通常よりも先に進んでください。


if(x == 0)  // 1
  {x = 1;}  // 2
else
  {x = 2;}  // 3

上記のコードの場合、アセンブリコードは次のようになります。

1. 000d 837DFC00        cmpl    $0, -4(%ebp)
   0011 7509            jne .L2

2. 0013 C745FC01        movl    $1, -4(%ebp)
   001a EB07            jmp .L3

    .L2:
3.001c C745FC02         movl    $2, -4(%ebp)

        .L3:

if内の条件がtrueの場合、フローは1-> 2(4命令)
if if内の条件がfalseの場合、フローは1-> 3(3命令)

そのため、if部分に異常またはまれにしか発生しないイベントを配置し、elseに通常の状態を配置して、毎回1​​つの命令を保存できるようにすることをお勧めします;-)


2

正反対のパターンはコードを読みやすくし、ネストされたifステートメントを削減または排除することがわかりました。これを「ガントレット」パターンと呼びます。(ストーリーテリングでは、ガントレットは最終タスクが完了する前に成功する必要がある一連の課題になります。)最初にエッジケースを処理することにより、コードの本体を簡潔かつ簡潔にすることができます。

if(gauntlet_1){ handle the first gauntlet condition }; 
if(gauntlet_2){ handle the second gauntlet condition };
...
// All preconditions (gauntlets) have been successfully handled

// Perform your main task here

そのため、「ハンドルガントレット」部分は、スローまたはリターンステートメントなどの制御の転送であるか、実際に障害を修正する必要があります。一部の人々は一連のif ... returnステートメントに眉をひそめますが、実際はそうではなく、実際にコードが読みやすくなると思います。

1
ガントレット条件が関数の成功を妨げるようなものである場合、すぐにエラーを返します。ガントレットの状態を処理できる場合は、可能な限りコード本体に入る前に処理します。私は主にネストされたIFステートメントを回避しようとしていますが、これは私の経験では、コーディングエラーの不明瞭でデバッグが難しい主な原因の1つです。
バイロンジョーンズ

0

私にとっては、実行するコードの複雑さよりも条件の方が重要です。最初に異常な条件をトラップし、その後より一般的な条件をトラップするように、条件を順序付ける必要があります。また、elseコードが本当に長く複雑な場合は、読者のために条件部分を明確に保つために、おそらくそのためのサブルーチンを作成します。


-1

決まったルールはありませんが、一般的にはこれに従います。まず、これを考慮に入れない設計パターンが欠落している場所を検討します。そうでない場合は、ifの条件が最も明確に理解されるように書きます。つまり、二重否定などを回避します。


-1

そのようなシナリオに関しては、大まかなルールはありません。しかし、場合によっては、ifブロックで正のコードまたは最も可能性の高いコードを記述し、elseブロックまたはデフォルトのケースでは省略できます。


-これは、すでに以前の回答で説明したものの上に何も提供していないprogrammers.stackexchange.com/a/223093/31260programmers.stackexchange.com/a/223520/31260
ブヨ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.