web-dev-qa-db-ja.com

効率的でクリーンなコードの条件の場合の注文

これは純粋に設計上の問題であり、例は私が求めていることを説明するために単純であり、トピックをカバーする例を提供するには、より複雑なコードの置換が多すぎます。 私はこの例を特に参照していません。例を使用して、私が何を参照しているかを説明しています。

Ifステートメントで、コーディング規約と、さらに重要なことには効率の観点から、条件を順序付ける好ましい方法はありますか?

そのような単純な例では、効率は問題になりませんが、コードのレビュー自体は求めていませんが、概念の理解は求めています。

2つの選択肢:
1。

public double myStuff(int i)
{
    // check for an invalid number of tourists
    if (i > 0)
    {
        // do something here

        return doubleSomething;
    } else
    {
        return Double.NaN;
    }
}

2。

public double myStuff(int i)
{

    if (i <= 0)
    {
        return Double.NaN;

    } else
    {

        {
            // do something here

            return doubleSomething;
        }

Ifステートメントがより複雑になり、ネストされる可能性がある場合、どのような順序で条件に対処する必要がありますか?

6
user208372

大きなifブロックに関しては、最適化は実際には問題ではありません。条件の計算も同様に簡単であると仮定すると、コンパイラーはそれらをどのように構成しても、ほぼ同じ結果を生成します。

私が使用したい1つのテクニックは、「ガードステートメント」を使用して、メソッド本体の上部で無効な入力をすぐにチェックすることです。このようにして、残りのメソッドは、引数がすでに有効であるという前提でフォーマットできます。

public double myStuff(int i, SomeOtherArgument widget) {
    // Perform any simple checks for invalid data right away and
    // fail fast if something smells bad.
    if (i <= 0)
        return Double.NaN;
    if (widget == null)
        throw new IllegalArgumentException();

    // If the stuff you've done above this line is trivial, there's no reason
    // to wrap the rest of the method body in a big else block. It's just noise.

    return doABunchOfWork();
}
14
Brant Bobby

たとえ効率が複雑であったりネストされていても、通常、ifステートメントを構造化するための効率は本当の関心事ではありません。他よりも効率が悪い可能性のあるifステートメントをネストする方法はありますが、コードが1回だけ実行され、5ナノ秒かかりすぎると、違いがあることに気付くことさえできなくなります。

この種のことが、特に一部のネストされたループの最も内側のループにある場合、プログラムの実行時間に実際の違いをもたらす可能性があります。ただし、遅いプログラムに対処する最良の方法は、それを測定し、ほとんどの時間を費やしている場所を見つけることです。そのため、そのスポットがネストされたifステートメントと関係があるかどうかにかかわらず、そのスポットをより効率的にすることができます。 。

Ifステートメント(特にネストされたものや複雑なもの)で問題になるのは、読みやすさです。複雑なネストされたifステートメントから判読不能な混乱を作り出すことは非常に簡単であり、コードを読み取るのが難しいほど、コードが正しいことを確認したりデバッグしたりすることが難しくなります。

単純なifステートメントの場合は、状態が狂ってしまわないようにしてください。複雑な条件を回避できない場合は、フォーマットを使用して明確にするか、ヘルパー関数を使用して条件を評価してください。

混乱:

if(a <= 5 && b > 10 && c < 4 && b <= 100
   && a > 2 && c > 1)

より良いフォーマット:

if( (a > 2)  && (a <= 5)   &&
    (b > 10) && (b <= 100) &&
    (c > 1)  && (c < 4) )

ヘルパー関数:

if( withinLimits(a, b, c) )

また、ダブルネガティブを避けるようにしてください。 「それが間違った発言ではないとは言えない」とは読みにくい。 「それは間違っている」は読みやすく、同じことを意味します。シングルネガティブはそれほど悪くはありませんが、代わりにポジティブなものを述べることで、物事を少し明確にすることができます。

ネストされたifステートメントの場合は、ネスト方法によって異なります。

このような場合:

if(a) {
  if(b) {
    if(c) {
      something;
    }
  }
}

次のようなものに置き換えることができます。

if(a && b && c) {
  something;
}

Ifステートメントの複雑な入れ子がある場合、それはおそらく混乱です。それを正確にクリーンアップする方法は、正確に何であるかによって異なります。決定テーブルを作成することは可能かもしれません-決定の基礎となるものと結果の決定であるエントリーを表すインデックスを持つ配列です。その場合は、ifステートメントをまったく使用せずに答えを調べるだけです。

3
Michael Shaw

複合条件の場合、Javaでは条件評価が遅延するという事実を考慮することを検討できます。つまり、プログラムは、条件付きステートメントを実行する必要があるかどうかを判断できるまで、(サブ)条件のみを評価します。

たとえば、c1とc2の2つの条件があり、c2の評価に時間がかかるためc1をすばやく評価できる場合は、if(c1 and/or c2)よりもif(c2 and/or c1)を優先して、グローバル条件が尊重されているかどうかをより迅速に判断できます。同様に、好む

if(c1){
   if(c2){
      (...)
   }
}

if(c2){
   if(c1){
      (...)
   }
}

最悪の場合、それは何も変更せず、最良の場合、テストを惜しみません。

これは一般的な原則です。条件の1つが事実上常に真であるという事実を考慮することもできます。その場合、最初にOR構成に配置するので、2番目の条件をテストすることは実質的にありません。興味深い場合があります。条件がある場合、条件の順序を決めるのが難しくなります。時間の消費と価値の確率を同時に検討する。

条件の順序を変更する前に、条件に副作用がないことを確認する必要があります。変更しないと、プログラムの動作が変更される場合があります。

0
mgoeminne