8

次のコードスニペットを考えると、かなりの違いはありますか?

public boolean foo(int input) {
   if(input > 10) {
       doStuff();
       return true;
   }
   if(input == 0) {
       doOtherStuff();
       return true;
   }

   return false;
}

対。

public boolean foo(int input) {
   if(input > 10) {
      doStuff();
      return true;
   } else if(input == 0) {
      doOtherStuff();
      return true;
   } else {
      return false;
   }
}

または、このコードでは、単一出口の原則の方が優れているでしょうか...

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

目に見えるパフォーマンスの違いはありますか?あるものが他のものより多かれ少なかれ保守可能/読みやすいと思いますか?

4

9 に答える 9

9

2番目の例では、両方の条件が相互に排他的であると非常に明確に述べています。
最初のものでは、それはそれほど明確ではなく、(ありそうもない)イベントでinput両方のifの間に割り当てが追加されると、ロジックが変更されます。
将来誰かがinput = 02番目のifの前に追加するとします。
もちろん、これが発生する可能性は低いですが、ここで保守性について話している場合、if-elseは相互に排他的な条件があることを明確に示していますが、ifの束はそうではなく、それらはifのように相互に依存していません-その他のブロック。

編集:この特定の例では、return句が相互排他性を強制していることがわかりましたが、ここでも、保守性と可読性について話しています。

とにかく、パフォーマンスについては、これがJavaでコーディングされている場合、2、3のifブロックのパフォーマンスを気にする必要はありません。これは、非常に遅いハードウェアにCが組み込まれている場合、おそらくJavaではありません。

于 2010-04-20T19:06:47.083 に答える
4

あなたの意図を最もよく表すフォームを使用してください。

ただし、物事がこれほど単純な場合は、単一出口の原則に従わないでください。混乱を招くだけです。

于 2010-04-20T19:03:55.057 に答える
4
  • 最初に:

    誰かが最終的に、何らかの奇妙な理由で、あなたが見ていないときに、特定の奇妙な条件下でこのメソッドを失敗させるいくつかのaddステートメントを追加します。誰もが(または最悪の場合、1人の人が)4時間を費やします。ソースコードを監視し、アプリケーションをデバッグして、最終的に途中に何かがあることを発見しました。

  • 2つ目は間違いなく優れており、このシナリオを防ぐだけでなく、これまたはこれ以上を明確に述べるのにも役立ちます。

    私たちが書くすべてのコードifが最大で10行の範囲内にある場合、これは実際には問題ではありませんが、残念ながらそうではありません。何らかの理由でif本体の長さが200行を超える必要があると考えるプログラマーが他にもいます。 。 とりあえず。

  • 私は3番目が好きではありません、それは私に戻り変数を探すことを強制します、そしてそれはreturnキーワードを見つけるのがより簡単です

速度性能に関しては、それらは(ほぼ)同一です。心配しないでください。

于 2010-04-20T19:31:56.753 に答える
1

最後の例では、これを行わないでください。

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

しかし、これ(Javaのfinalの使用に注意してください):

public boolean foo(int input) {
   final boolean toBeReturned;    // no init here
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   } else {
      toBeReturned = false;
   }
   return toBeReturned;
}

そうすることで、意図が明確になり、これは「意図によるプログラミング」をサポートするIDEの天の恵みです(部分的なASTでも、潜在的なエラーを確認するために「コンパイル」する必要はありません。優れたIDEは、不完全なソースを実際に調べることができます。時間とあなたに即時の警告を与えます)。

このようにして、戻り値を初期化することを忘れないでください後で別の条件が必要だと判断した場合、これは素晴らしいことです。

IntelliJ IDEA(バージョン4かそこら、ずっと前)を使い始めて以来、私はこれを常に行っています。これにより、多くのばかげた注意散漫の間違いを防ぐことができました...

一部の人々は、これはそのような単純なケースには多すぎるコードであると主張しますが、それは完全に要点を欠いています:要点は、コードが読みやすく、後で誤ってtoBeReturnedを割り当てることを忘れることなく、簡単に拡張できるように意図を明確にすることですそして、後の節から戻ることを誤って忘れることなく、追加することができます。

それ以外の場合、「簡潔さ」がゲームの名前である場合、私は次のように書きます。

public boolean foo(int a) {
  return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false; 
}

doStuffとdoOtherStuffの両方がtrueを返す場合。

于 2010-04-20T19:49:46.413 に答える
0

バージョン#1と#2は#3よりも高速かもしれませんが、パフォーマンスの違いはごくわずかだと思います。私はむしろ読みやすさに焦点を当てたいと思います。

個人的には、バージョン#2を使用することはありません。#1と#3の間で、問題のケースで最も読みやすいコードを生成するものを選択します。コードの分析が難しくなるため、メソッド内の多くの出口点は好きではありません。ただし、一部の特殊なケースでは、すぐに終了してメインのケースに進むと、流れが明確になる場合があります。

于 2010-04-20T19:10:28.293 に答える
0

2つの例が類似していない場合は、このケースを考えてみてください。

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        }
        System.out.println("do some other intermediary stuff");
        if (input == 0) {
            // doOtherStuff();
            return true;
        }

        return false;
    }

対。

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        } 
        //System.out.println("doing some intermediary stuff... doesn't work");
        else if (input == 0) {
            // doOtherStuff();
            return true;
        } else {
            return false;
        }
        return false;
    }

最初のアプローチはおそらくより柔軟ですが、両方のは異なる状況で使用されます。

パフォーマンスに関しては、正気のプログラマーによってコーディングされた通常のJavaアプリケーションの場合、考慮すべき違いはごくわずかだと思います:)。

于 2010-04-20T19:12:23.493 に答える
0

あなたの場合、2番目のifは、最初のifが失敗した場合にのみ呼び出されるため、ここではそれほど重要ではありませんが、最初のifが何かを実行して戻ってこなかった場合、2番目のif(これは常にfalse)は、それがない限りテストされます。 else-ifにありました。

つまり、if-else-ifとif-ifの違いが重要な場合もありますが、これはその1つではありません。

例:これを試してから、elseを削除してから試してください。2つの異なる出力が得られます。

int someNumber = 1;
if(someNumber < 5)
{
    someNumber += 5;
    Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
    Console.WriteLine("Second call.");
}
于 2010-04-20T19:13:19.263 に答える
0

意味的に—いいえ。パフォーマンス面では、これはコンパイラーに依存します。つまり、両方の条件が同時に真になることができないことを検出できるかどうかです。私は標準のSunコンパイラができるに違いない。シングルエグジットの原則を使用するかどうかは、好みによって異なります。私は個人的にそれが嫌いです。

于 2010-04-20T19:05:42.810 に答える
-1

最初のスニペットと2番目のスニペットの間には、実際には違いはありません。ただし、3番目のスニペットは非常に非効率的です。メソッドのコードの最後の行までプログラムの制御を呼び出し元に戻すのを待つため、処理能力/メモリを浪費しますが、最初の2つのコードスニペットは、条件の1つが真であると判断するとすぐに制御を返します。

于 2010-04-20T19:05:46.590 に答える