私はプログラミングが初めてで、制御構造ロジックを順序付ける正しい方法があるかどうか疑問に思っています。
最も可能性の高いケースを最初にチェックする方がより自然に思えますが、いくつかの制御構造は、false をすべてチェックして true に到達しない限り機能しないと感じています (論理的推論?)。
この「否定的な」見方に適応するのは難しいでしょう。すべてが真実であると仮定して、私はより肯定的な見方を好みます :)
私はプログラミングが初めてで、制御構造ロジックを順序付ける正しい方法があるかどうか疑問に思っています。
最も可能性の高いケースを最初にチェックする方がより自然に思えますが、いくつかの制御構造は、false をすべてチェックして true に到達しない限り機能しないと感じています (論理的推論?)。
この「否定的な」見方に適応するのは難しいでしょう。すべてが真実であると仮定して、私はより肯定的な見方を好みます :)
McConnellのCodeCompleteには、このトピックに関する優れた議論があります。私が強くお勧めする本です。とにかく、関連する議論は初版またはページの706-708ページにあります。第2版の749-750(台座に感謝)。その本から:
最も速く、最も真実である可能性が高いものが最初に実行されるようにテストを配置します。通常のケースを簡単に通り抜けることができ、非効率な場合は、例外を処理する必要があります。
条件ステートメントの値に加えて、考慮すべきことがあります。たとえば、コードのブロックのサイズが大幅に異なる場合は、見やすくするために小さなブロックを最初に配置することをお勧めします。(大きなブロックが本当に大きい場合は、リファクタリングするか、別のメソッドに引き出す必要があるかもしれません。)
if( condition is true ) {
do something small;
} else {
do something;
and something else;
. . .
and the 20th something;
}
条件の範囲内で、はい、式の一部がfalseになると式の評価を停止する言語がいくつかあります。これは、コードにある種のis-definedロジックを含める場合に覚えておくことが重要です。言語が式全体を評価する場合は、次のようにする必要があります。
if( variable is defined ) {
if( variable == value ) {
...
}
}
これではなく:
if( (variable is defined) && (variable == value) ) {
...
}
私はあなたの条件を設計するための「正しい」方法はないと思います。コーディング標準がある会社で働いている場合は、それが標準に含まれているかどうかを確認する必要があります。(私が最後に働いた場所では、妥当な数の標準が定義されていましたが、条件付きロジックの記述方法は指定されていませんでした。)
一般的に、私は最初に予期しない項目をチェックするので、プログラムの例外的な流れに対処する必要があります。
そうすれば、通常のプログラムフローの「セットアップ」を開始する前に、例外/中止操作をスローできます。
この質問も参照してください:
私は、読者が取り入れる必要のある情報の量を最小限に抑えるように条件を構成することを目指しています。ポジティブを証明するためにネガティブをテストする方が簡単な場合があります。
例-2つの日付の期間が2つの日付の別の期間と交差するかどうかを確認するテストは、2つの期間が交差しないテストとして記述しやすいです。
ほとんどの場合、読みやすさは実行速度よりも重要です。したがって、次のアプローチを使用して、理解しやすいように最適化しようとします。
すべての「アサーション」チェックは前もって行われます。これにより、すべての誤ったケースが最初から処理されることが保証されます。これは、null ポインター チェックでは特に重要です。
if(arg == null){ 新しい IllegalArgumentException() をスローします。// 厳しい (正しい) } // また if(arg == null){ 引数 = ""; // 寛容 (怠惰) }
次に、各 if ステートメントで 1 つの条件のみをチェックしようとします。それ以外の
if(条件1 &&条件2) { ... } そうしないと { ... }
私は一般的に好む
if(条件1) { if(条件2) { ... } そうしないと { ... } } そうしないと { ... }
このアプローチは、ブレークポイントの設定が簡単で、ロジックがより明確になります。
私は否定を避けます。それ以外の
if(! 条件) { ...あ... } そうしないと { ...ば... }
物事はより良く再配置されます
if(条件) { ...ば... } そうしないと { ...あ... }
最後に、ブール値の結果を返すすべてのメソッドには、結果の意味を示す「肯定的な」名前を付ける必要があります。
boolean checkSomething(Something x){ ... } // 悪い -- 結果は? boolean isSomethingInvalid(Something x){ ... } // 良いですが ... boolean isSomethingValid(Something x){ ... } // 最高、「精神的否定」なし
単純な「はい」または「エラー」の質問の場合は、通常、エラー処理ブランチが else 句になるように構成します。はいまたはいいえの質問である場合 (つまり、どちらの分岐もエラーではない)、それは純粋にどちらがより自然に感じられるかについての判断です。コードの中心部を実行する前に行う必要があるテストがたくさんある場合、通常、ネガティブ テストが最初に来て、それに続くコード (関数から戻る、ブレークする、または続行する) をスキップするように構造化しようとします。ループ)。
どちらか/または。しかし、私は一般的に「ネガティブ」アプローチを使用します。
もし何か) {
}
これは質問の範囲から少し外れていますが、一般的には、メソッドがすばやく失敗することも必要です。このため、コードの後半まで引数を使用しない場合でも、メソッドの先頭ですべての引数の検証を行う傾向があります。これは可読性を損ないますが、メソッドが非常に長い場合のみです (表示するには画面をスクロールする必要があります)。もちろん、それ自体がコードの匂いであり、リファクタリングされる傾向があります。
一方、チェックが単純ではなく、とにかくチェックするだけの別のメソッドにそれを渡す場合は、現在のメソッドでチェックインするコードを繰り返しません。ほとんどのものと同様に、バランスがあります。
(コンテキスト: Java)
READABILITY1: コードのより小さなブロックに解決される条件が最初に実行されます
if (condition) {
smallBlock();
} else {
bigBlockStart();
........
bigBlockEnd();
}
READABILITY2: 否定記号に気付かない方が簡単なため、肯定的な主張が最初に行われます
意味をなす: Assert.blabla() を使用してメソッドのすべての前提条件をアサートし、メソッドが行うことに対してのみ条件を使用します。