2

私はコンピューター サイエンスを勉強している初心者のプログラマーであり、ループ内で return ステートメントを使用することは良いプログラミングの習慣ではなく、避けるべきだと何度も言われてきました。最近では、すべてがどのように機能するかを学ぶために Java ライブラリーのコードをたくさん読んでいますが、ループ内の return ステートメントがいたるところにあることに驚きました。

ループで return ステートメントを使用することを避けるべき理由を誰かに説明してもらえますか?

ありがとう!

4

8 に答える 8

7

ほとんどの人は、メソッドを見て、単一の出口点を想定するのが好きです。ループの途中でリターンを補間すると、フローが少し分割され、この仮定が妨げられます。そのため、多くの人が「きれいではない」という議論をします。本当に汚いことは何もありませんが、プログラムの「人間」の読者は、その流れをより明確に理解するために、メソッドをより深く掘り下げる必要があります。あなたの論理の流れを理解するために人々がしなければならない精神的な推論の量を減らすためにあなたができることは何でも良いことと考えられています。

メソッドの内部を読まずにメソッドを一瞥し、メソッドが何を実行し、どこで終了するかを全体的に理解できれば、作成者は良い仕事をしました。問題は、最初はうまくいくことを意味する方法が時間の経過とともに成長し、メンテナがそれを理解するために演習で複数の状態を精神的に調整することを余儀なくされるときに発生します。

良い例は、一部の人が良い習慣と見なしている古典的なガード条項です。これは、続行する前に状態またはパラメーターの有効性をチェックする方法です。メソッドに間違ったものが与えられた場合、続行したくありません。この偽のコードを参照してください:

public void doSomethingCool(Object stuff) {
  if(weWereNotExpectingThis(stuff)) return; //guard clause

  while(somethingHappens()) {
      doSomethingCool();
  }
  return;
}

誰かがやって来て、「かっこいい!メソッドの途中でreturnステートメントを使用しても大丈夫です!」と言います。彼らは変更を加え、それは次のようになります。

public void doSomethingCool(Object stuff) {
  if(weWereNotExpectingThis(stuff)) return; //guard clause

  while(somethingHappens()) {
    if(somthingHasChanged()) return; //because my team likes early exits, Yay!
    else {
      doSomethingCool();
    }
  }
  return;
}

まだそれほど粗末ではありませんが、ますます多くの変更が加えられ、最終的には次のようになります。

public void doSomethingCool(Object stuff) {
  if(weWereNotExpectingThis(stuff)) return; //guard clause

  while(somethingHappens()) {
    if(somthingHasChanged()) return;
    else if(weDetectNewInput()) {
      doSomethingCool();
    } else {
      doSomethingBoring();
      if(weDetectCoolInput()) {
        doSomethingCool();
        continue;
      }
      return;
    }
  }
  return;
}

これで、これがどこに向かっているのかがわかります。どこにジャンプするのか、何が起こっているのかを一目で理解するのは難しい。

于 2012-04-03T20:23:29.517 に答える
6

それはすべて「クリーンなコード」に要約されます。その声明は、人によって異なることを意味します。メソッドの下部に1つのreturnステートメントがあると、クリーンと見なされます。それは主観的です。

そうは言っても、メソッドは複数のreturnステートメントを持つことができ、それでもクリーンであると見なすことができます。それはすべてあなたとあなたのチームの許容度に依存し、さらに重要なことに、あなたの上級開発者はクリーンだと考えています。

許容できる返品習慣と判読不能/バグが発生しやすいコードとの間の境界線を越えると、定量化するのは困難です。次のように整理された方法

method {

 if(!x) return;

  for(...) {
    if (x && y) return

    for(...) {
        if (z) return;
    }
  }

  if (a) return;

  ...
  return;
}

あなたがそれをどのように見ても、ほとんどきれいではありません。

言い換えると、returnステートメントが多すぎるとコードの臭いが発生するため、問題のコードを別の外観にする必要があります。

于 2012-04-03T20:03:02.837 に答える
2

他の回答についてはまだコメントできないため、新しい回答を投稿せざるを得ません。どんな哲学も「常に」正しいと言うことに、私は細心の注意を払います。それはすべてトレードオフに関するものです。2 番目の return ステートメントを追加することで、プログラム フローを管理するために break ステートメントとブール値フラグを不必要に使用することを避けることができる場合、それはおそらく正しいことです。

ただし、他のコメンターは、return ステートメント、ブレーク、およびフラグの Web は「コードのにおい」であると示唆しています。メソッドをより小さく、よりモジュール化された部分に分解できるかどうかを確認してください。

于 2012-04-03T21:54:35.920 に答える
2

ループ内の return ステートメントが長い間推奨されない理由は、構造化プログラミングと呼ばれるパラダイムのためです。これは基本的に、プログラム内の実行の流れが単純で、どこからでも簡単にたどることができることを意味します。当時、GOTO はまだ広く使用されており、コードの可読性に悪夢を抱いていました。それに対する反発の一部として、コードのすべてのブロックには終了点が 1 つだけあるべきであり、ジャンプは条件付き分岐、ループ、および関数呼び出しだけにすべきであるとよく言われました。多くの人は今でもこれを信じており、その結果、ループ内の break ステートメント、例外、および return ステートメントを嫌います。

私自身の見解では、コードの特定のチャンクが何をするのかを理解できることの方が、その実行の流れを正確に追うことができるよりも重要です。(私は関数型言語でプログラミングすることが多く、そうでないときでも関数型スタイルでコードを書こうとします。) そのため、ループ内の return ステートメントは問題ないと思います。最終的には好みの問題です。

于 2012-04-03T20:13:52.227 に答える
1

「シングルリターン」の宗教に固執する人々は、ループから抜け出すために非常に長い時間を費やし、復帰する時が来たことを示すフラグを設定します。

このような警告を受け取る最善の方法は、時期尚早に戻る正当な理由があるかどうか、またはコードの構造を考える際に怠惰を示しているかどうかを考えることです。

于 2012-04-03T20:05:52.447 に答える
1

目的がクリーンなコードと可読性である場合、IMHO の最善のアプローチは、その場で関数を終了することreturnですreturn

そして、これはおそらく関数の些細な例では明らかではありませんが、本当に複雑な作業を行う関数では、1) 何が起こっているのかを理解しやすくなります 2) 読みやすくなります 3) IMO エラーが発生しにくくなります-バグが検出され、できるだけ早く修正が必要な場合があります。最後に1 つ保持するreturnと、「手早く汚い」修正を行うとコードが壊れる可能性があることを何度も見てきました。

しかし、これは私の個人的な意見です。

于 2012-04-03T21:00:59.283 に答える
0

多くの人がそれをよりクリーン(そしてより安全なスタイル)と考える理由は、関数がますます複雑になると(アプリケーションが大きくなるにつれて関数が複雑になることがよくあります)、関数の途中の出口点を追跡するのが難しくなり、混乱を招き、微妙なバグが発生する可能性があります。

ただし、すべての「ルール」と同様に、関数の途中での戻りが、最後まで待機した結果として発生する可能性のあるif(!error)ブロックよりもはるかにクリーンな例外とケースがあります。

于 2012-04-03T20:06:24.613 に答える
0

昔は、コンパイラと VM を混同する可能性がありましたが、それほどではなくなったため、通常は安全な方法です。人々はまた、あなたが本当に優れたプログラマーであれば、同じことを行うためのよりエレガントな方法を見つけることができるという一般的な「貧弱な実践」の議論をしていると思います。

乾杯

于 2012-04-03T20:03:59.810 に答える