12

これはマイナーなスタイルの質問ですが、コードに追加した読みやすさはすべて重要です。

あなたが持っている場合:

if (condition) then
{
   // do stuff
}
else
{
   // do other stuff
}

その方が良いか、次のようにするかをどのように判断しますか。

   if (!condition) then
   {
     // do other stuff
   {
   else
   {
     // do stuff
   }

私のヒューリスティックは次のとおりです。

  1. 条件をポジティブに保ちます(読むときの暗算が少なくなります)
  2. 最も一般的なパスを最初のブロックに入れる
4

23 に答える 23

18

私は最も一般的なパスを最初に置くことを好みます。また、入れ子の削減を強く信じているので、可能な限り他の方法を選択する代わりに、中断、継続、または戻ります。私は通常、肯定的な条件に対してテストするか、否定的な条件を肯定的に反転することを好みます。

if (condition)
    return;

DoSomething();

私は、else の使用を大幅に減らすことで、コードがより読みやすく保守しやすくなり、else を使用する必要がある場合は、ほとんどの場合、より構造化された switch ステートメントの優れた候補になることがわかりました。

于 2008-10-03T12:26:13.063 に答える
4

2 つの (矛盾する) 教科書の引用:

if/else の最短句を一番上に置く

-- アレン・ホルブ、「自分の足を撃つには十分なロープ」、p52

通常の場合は、else の後ではなく if の後に置きます

--Steve McConnell、「Code Complete、第 2 版」、p356

于 2008-10-03T12:55:46.483 に答える
3

私は最初のものを好みます。条件はできるだけ単純にする必要があり、条件外と ! 条件のどちらがより単純であるかがかなり明白である必要があります。

于 2008-10-03T12:24:42.630 に答える
3

あなたの流れ次第です。多くの関数では、前提条件を使用します。

bool MyFunc(variable) {
    if (variable != something_i_want)
        return false;

    // a large block of code
    // ...
    return true;
}

ケースごとに何かをする必要がある場合は、フォーマットを使用ますif (positive_clause) {} else {}

于 2008-10-03T12:28:36.850 に答える
3

コードがエラー状態をチェックする場合、そのコードを最初に配置し、「成功」コードを 2 番目に配置することを好みます。概念的には、これにより関数呼び出しとそのエラー チェック コードが一緒に保持されます。これらは関連しているため、私には理にかなっています。例えば:

  if (!some_function_that_could_fail())
  {
     // Error handling code
  }
  else
  {
     // Success code
  }
于 2008-10-03T12:31:24.177 に答える
3

可能な場合は正の if 句を使用することについて、Oli に同意します。

これを絶対にしないでください:

if (somePositiveCondition)
else {
    //stuff
}

私が働いていたある場所でこれをよく見て、コーダーの1人がどのように機能しないかを理解していないのではないかと思っていました...

于 2008-10-03T12:31:58.670 に答える
3

データの検証を検討しているときは、条件を「ホワイト リスト」にしようとしています。つまり、何を受け入れるかをテストします。

if DataIsGood() then
   DoMyNormalStuff
else
   TakeEvasiveAction

逆ではなく、次のように退化する傾向があります。

if SomeErrorTest then
  TakeSomeEvasiveAction
else if SomeOtherErrorCondition then
  CorrectMoreStupidUserProblems
else if YetAnotherErrorThatNoOneThoughtOf then
  DoMoreErrorHandling
else
  DoMyNormalStuff
于 2008-10-03T13:02:50.353 に答える
2

ソフトウェアは知識の獲得です。何かを行う方法についての誰かの知識をエンコードしています。

ソフトウェアは、問題の「自然」に適合する必要があります。疑問がある場合は、他の人に聞いて、実際に何を言っているのか、何をしているのかを確認してください。

「一般的な」ケースが何もしないという状況はどうですか? じゃあ何

if( common ) {
    // pass
}
else {
    // great big block of exception-handling folderol
}

それともこれをしますか?

if( ! common ) {
    // great big block of except-handling folderol
}

「常にポジティブ」なルールは、最初に望むものではありません。次のようなルールをもっと見たいと思います。

  1. 常に自然 -- 英語のように (または、組織内の一般的な言語が何であれ) 読む必要があります。
  2. 可能な場合は、一般的なケースを最初に表示して、一般的に見えるようにします。
  3. 可能であれば正論理を使用してください。負の論理は、一般的にそのように言われている場合、または一般的なケースが何もしない場合に使用できます。
于 2008-10-03T12:57:45.763 に答える
2

これがまさにあなたが探しているものではないことはわかっていますが...多くの開発者は「ガード句」、つまりメソッドからできるだけ早く抜け出す否定的な「if」ステートメントを使用しています。その時点で、本当に「他」はありません。

例:

if (blah == false)
{
    return; // perhaps with a message
}

// do rest of code here...

あなたがあなたのCPUを破壊しているとあなたに言うハードコアなc / c ++ /アセンブリの人がそこにいます!!! (多くの場合、プロセッサは「真」のステートメントを優先し、次に行うことを「プリフェッチ」しようとします...したがって、理論的には「偽」の条件はパイプをフラッシュし、マイクロ秒遅くなります)。

私の意見では、「より優れた」(より理解しやすい) コードが、マイクロ秒の CPU 時間よりも勝る段階に来ています。

于 2008-10-03T12:39:22.930 に答える
2

2 つのパスの 1 つが非常に短く (1 ~ 10 行程度)、もう 1 つがはるかに長い場合、ここで説明した Holub ルールに従い、短いコードを if に配置します。これにより、コードを確認するときに 1 つの画面で if/else フローを確認しやすくなります。

それが不可能な場合は、条件をできるだけ単純にするように構成します。

于 2008-10-03T13:01:57.470 に答える
2

単一の変数の場合、not 演算子は十分に単純であり、命名の問題がより関連し始めていると思います。

変数に not_X という名前を付けないでください。必要に応じて、シソーラスを使用して反対の名前を見つけてください。次のようなひどいコードをたくさん見てきました

if (not_dead) {
} else {
}

明らかな代わりに

if (alive) {
} else {
}

次に、正常に使用できます(非常に読みやすく、コードブロックを反転する必要はありません)

if (!alive) {
} else {
}

より多くの変数について話している場合、最良のルールは条件を単純化することだと思います。しばらくすると、プロジェクトは次のような状態になる傾向があります。

if (dead || (!dead && sleeping)) {
} else {
}

翻訳すると

if (dead || sleeping) {
} else {
}

条件がどのように見えるか、およびそれらを単純化する方法に常に注意を払ってください。

于 2008-10-03T12:47:51.007 に答える
1

真と偽の両方の条件がある場合は、正の条件を選択します-これにより混乱が減り、一般的にコードが読みやすくなると思います。

一方、Perlなどの言語を使用している場合、特にfalse条件がエラー条件または最も一般的な条件のいずれかである場合は、条件がない限りコードブロックを実行する「unless」構造を使用できます。真(つまり、ifの反対):

unless ($foo) {
    $bar;
}
于 2008-10-03T14:05:57.543 に答える
1

まず第一に、そもそも「else」の使用を避ける方がよい状況を脇に置きましょう (そのような状況が実際に存在し、そのような場合を判断することはおそらく別のトピックであることに誰もが同意することを願っています)。

したがって、「else」句が必要であると仮定しましょう。

読みやすさ/わかりやすさには、少なくとも 3 つの重要な要件または規則が課せられると思いますが、残念ながらこれらはしばしば互いに競合します。

  1. 最初のブロック (「if」ブロック) が短いほど、「if-else」構造全体を把握しやすくなります。「if」ブロックが十分に長い場合、「else」ブロックの存在を見落としやすくなります。

  2. 「if」パスと「else」パスが論理的に非対称である場合 (「通常の処理」と「エラー処理」など)、スタンドアロンの「if-else」構造では、どちらのパスが最初でどちらが 2 番目かはあまり重要ではありません。 . ただし、複数の「if-else」構造が互いに近接している場合 (ネストを含む)、およびそれらすべての「if-else」構造が同じ種類の非対称性を持っている場合、これらの非対称パスを配置することが非常に重要になります。一貫して。

    繰り返しますが、すべてに対して「if ... 正常なパス ... else ... 異常なパス」、またはすべてに対して「if ... 異常なパス ... else ... 正常なパス」にすることができますが、そうすべきではありません。これら 2 つのバリアントの混合になります。

    他のすべての条件が等しい場合、通常のパスを最初に置くことは、ほとんどの人間にとっておそらくより自然です (美学よりも心理学に関するものだと思います:-)。

  3. 通常、否定で始まる式は、そうでない式よりも読みにくく、理解しにくくなります。

したがって、これら 3 つの競合する要件/ルールがあり、本当の問題は、どれが他のものよりも重要かということです。アレン・ホルブにとって、ルール #1 はおそらく最も重要なものです。Steve McConnell にとっては、ルール 2 です。しかし、これらの規則の 1 つだけを単一のキードラインとして実際に選択できるとは思いません。

ここで私の個人的な優先事項をすでに推測していると思います (上記のルールの順序から :-)。

私の理由は簡単です:

  • ルール 1 は無条件であり、回避することはできません。ブロックの 1 つが長すぎて画面からはみ出す場合は、「else」ブロックにする必要があります。(いいえ、「if」または「else」ブロックの行数を減らすためだけに関数/メソッドを機械的に作成するのは良い考えではありません! 各ブロックには、論理的に正当化できる最小限の行数が既にあると想定しています。 )

  • ルール 2 には、複数の「if-else」構造、すべてが同じ種類の非対称性など、多くの条件が含まれます。したがって、多くの場合には適用されません。

    また、次の興味深い現象をよく観察します: 規則 2 が適用され、それが適切に使用されている場合、実際には規則 1 と競合しません! たとえば、「通常と異常」の非対称性を持つ「if-else」ステートメントが多数ある場合、すべての「異常」パスは「通常」パスよりも短くなります (またはその逆)。この現象を説明することはできませんが、コードの構成が良好であることを示しているにすぎないと思います。言い換えれば、ルール 1 と 2 が競合している状況を見るたびに、「コードのにおい」を探し始めます。そしてリファクタリング後 - 多田!ルール #1 とルール #2 の間で選択するのにこれ以上苦労する必要はありません:-)

  • 最後に、ルール #3 は範囲が最小であるため、重要度が最も低くなります。

    また、他の同僚がここで言及しているように、このルールを「だます」のは非常に簡単です (たとえば、「if(!enabled)...」の代わりに「if(disabled),,,」と書く)。

誰かがこの作品の意味を理解できることを願っています...

于 2008-10-31T09:54:29.653 に答える
1

私にとっては、条件によって異なります。たとえば、次のようになります。

if (!PreserveData.Checked)
{  resetfields();}

私は、自分がロジックをどのようにしたいのかを自分自身に語りかけ、それを頭の中で小さな声にコード化する傾向があります。

于 2008-10-03T12:29:54.820 に答える
1

通常、if / else ブロックを切り替えることなく、条件を肯定的にすることができます。

変化する

   if (!widget.enabled()) {
     // more common 
   } else {
     // less common 
   }

   if (widget.disabled()) {
     // more common 
   } else {
     // less common
   }
于 2008-10-03T13:05:13.407 に答える
1

インテル Pentium 分岐予測は、「if」ケースの命令をプリフェッチします。代わりに「else」分岐をたどると、命令パイプラインがフラッシュされ、ストールが発生します。

パフォーマンスを重視する場合: 最も可能性の高い結果を 'if' 句に入れます。

個人的には次のように書きます。

if (expected)
{
   //expected path
}
else
{
   //fallback other odd case
} 
于 2008-10-03T13:33:26.813 に答える
0

私は通常、最初に肯定的な結果(つまりメソッド)を置くので、次のようになります。

if(condition)
{
doSomething();
}
else
{
System.out.println("condition not true")
}

ただし、メソッドを使用するために条件がfalseである必要がある場合は、次のようにします。

if(!condition)
{
doSomething();
}
else
{
System.out.println("condition true");
}
于 2012-07-16T13:54:35.943 に答える
0

最も可能性の高いケースを常に最初に置く必要があります。より読みやすいだけでなく、より高速です。これは、switch ステートメントにも適用されます。

于 2008-10-03T14:50:28.093 に答える
0

if ステートメントの設定方法に関しては、私は恐ろしいです。基本的に、探しているものに基づいて設定したため、すべてが異なります。

if (userinput = null){
destroyViolently();
} else {
実際に何かをする;
}

またはおそらく

if (1+1=2) {
do stuff;のようなもの
} 他の {
爆発暴力();
}

if/else ステートメントのどのセクションが実際に機能するかは、私の悪い癖です。

于 2008-10-03T15:38:16.500 に答える
0

原則として、一方が他方よりも著しく大きい場合は、大きい方をifブロックにします。

于 2008-10-03T12:32:36.717 に答える
0
  1. 共通パスを最初に置く
  2. ネガティブなチェックをポジティブなものに変える ( !full == empty)
于 2008-10-03T12:32:46.047 に答える
0

私は常に最も可能性の高いものを最初に保ちます。

Perl には、それを支援する追加の制御構造があります。if の逆。

unless (alive) {
     go_to_heaven;
} else {
     say "MEDIC";
}
于 2008-10-03T13:40:34.037 に答える
0

複数の出口点が必要な場合は、それらを最初に置き、明確にします。

if TerminatingCondition1 then
  Exit
if TerminatingCondition2 then
  Exit

これで、通常の作業を進めることができます:

if NormalThing then
  DoNormalThing
else
  DoAbnormalThing
于 2008-10-03T12:54:13.443 に答える