70

この方法:

boolean containsSmiley(String s) {
    if (s == null) {
        return false;
    }
    else {
        return s.contains(":)");
    }
}

同等に書くことができます:

boolean containsSmiley(String s) {
    if (s == null) {
        return false;
    }

    return s.contains(":)");
}

私の経験では、2 番目の形式がより頻繁に見られます。特に、より複雑なメソッド (このような終了点が複数ある場合) では、同じことが「スロー」と「リターン」にも当てはまります。しかし、最初の形式は間違いなく、コードの条件付き構造をより明確にします。どちらかを優先する理由はありますか?

(関連:関数には return ステートメントを 1 つだけ含める必要がありますか? )

4

23 に答える 23

93

そのelse場合、 は冗長になるだけでなく、関数のメイン コードに不要な余分なインデントを作成します。

于 2010-07-16T04:08:02.660 に答える
74

私の経験では、それはコードに依存します。何かに対して「ガード」している場合は、次のことを行います。

if (inputVar.isBad()) {
    return;
}

doThings();

要点は明らかです。そのステートメントが false の場合、関数を続行したくありません。

一方、複数のオプションを持つ関数もいくつかあり、その場合は次のように記述します。

if (inputVar == thingOne) {
    doFirstThing();
} else if (inputVar == secondThing) {
    doSecondThing();
} else {
    doThirdThing();
}

次のように書くこともできますが:

if (inputVar == thingOne) {
    doFirstThing();
    return;
}
if (inputVar == thingTwo) {
    doSecondThing();
    return;
}
doThingThree();
return;

実際には、コードが何を行っているかを最も明確に示す方法 (必ずしもコードのどのビットが最も短いか、またはインデントが最も少ないかということではありません) に帰着します。

于 2010-07-16T04:20:45.263 に答える
37

これはGuard Clauseと呼ばれるパターンです。アイデアは、ネストされた条件を減らして読みやすさを向上させるために、事前にすべてのチェックを行うことです。

リンクから:

double getPayAmount() {
    double result;
    if (_isDead) {
        result = deadAmount();
    } else {
        if (_isSeparated) {
            result = separatedAmount();
        } else {
            if (_isRetired) {
                result = retiredAmount();
            } else {
                result = normalPayAmount();
            }
        }
    }

    return result;
}

ガード句を使用すると、次の結果が表示されます。

double getPayAmount() {
    if (_isDead) return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetired) return retiredAmount();

    return normalPayAmount();
};
于 2010-07-16T04:19:21.227 に答える
8

あなたはこれをいたるところに見るでしょう:

if (condition) {
    return var;
}
// by nature, when execution reaches this point, condition can only be false,
// therefore, the else is unnecessary
return other_var;

ほとんどの場合、else 句の追加は、この場合不要であるだけでなく、多くの場合、コンパイラによって最適化されます。

コンピューターがこのコードをどのように考えるかを考えてみてください (機械語の観点から、デモ用にここでは擬似コードに簡略化しています)。

0x00: test [condition]
0x01: if result of test was not true, goto [0x04]
0x02: push [var] onto stack
0x03: goto [0x05]
0x04: push [other_var] onto stack
0x05: return from subroutine

コード (これも疑似コードであり、アセンブリではありません) は、条件に対してまったく同じように動作しif/then/elseます。

多くの人は、プログラマーが自分のコードを通る可能性のあるすべてのパスを考えなければならないため、関数の複数の出口点を持つことは悪い習慣であり、混乱を招くと考えています。別のプラクティスは次のとおりです。

return (condition) ? var : other_var;

これによりコードが簡素化され、新しい終了ポイントは作成されません。

于 2010-07-16T04:24:44.283 に答える
7

私は次のように書くのが好きです:

boolean containsSmiley(String s) {
    return s != null && s.contains(":)");
}
于 2010-07-16T04:15:13.890 に答える
4

else冗長です。また、IDE (Eclipse) や分析ツール (FindBugs など) によっては、警告またはエラーとしてフラグが立てられる場合があるため、その場合、プログラマーはそれを削除する可能性があります。

于 2010-07-16T04:15:32.980 に答える
4

コーディング スタイルに関する「議論」と同様に、正解はありません。これらの考慮事項を適用することを好みます。

  1. コードはすべての状況で期待どおりに機能しますか。(驚き最小の原則)

  2. 次の開発者 (私自身または他の誰か) は、それが何をしているのか、またその理由を理解できるでしょうか。

  3. 変化に対するコードの脆弱性。

  4. 必要に応じてシンプルであり、それ以上ではありません。つまり、エンジニアリングの過不足はありません。

上記の条件を満たしたことに満足したら、残りは一般的に一致します。

于 2010-07-16T06:15:33.647 に答える
3

他の誰かがおそらくこれをすでに指摘していますが、文字列が期待される場所では一般的に null 値を使用しないことをお勧めします。誰かが null 値を渡すのを防ぐために本当にチェックが必要な場合は、アサート (開発時) または単体テスト (デプロイ) を使用できます。

boolean containsSmiley(String s) {
    assert s != null : "Quit passing null values, you moron.";
    return s.contains(":)");
}

私は一般的な経験則に切り替えました:決してありません。これまで。外部 API 呼び出しが明示的に要求しない限り、null 値を渡します。2 番目: 外部メソッドが null 値を返す可能性がある場合は、適切な null 以外の値 (空の文字列など) に置き換えるか、適切なチェックを追加します。if (thing == null)繰り返しのチェックにうんざりしています。

しかし、それは少し的外れです。トップ句とガード句に短い条件を付けて、プログラム フローで絶対に到達できない場合は else を削除するのが好きです。

于 2010-07-16T11:09:27.700 に答える
2

それはもっといいから。'{''}'を使用していくつかのレベルのネストを作成することもできますが、実際には誰もそれを実行しません。

于 2010-07-16T08:26:56.250 に答える
2

それは宗教的な議論であり、結局のところ問題ではありません。状況によっては、最初の形式の方が読みやすいとさえ主張します。に大量のコードがある場合はif-elseif-elseif-else、一目でデフォルトの戻り値を確認する方が簡単です。

if (s == null) {
    return false;
}
else if (s.Contains(":))")) {
    return true;
}
else if (s.Contains(":-(")) {
    return false;
}

return s.contains(":)");
于 2010-07-16T04:18:31.650 に答える
2

オッカムの剃刀は「必要以上に実体を増やしてはならない」という原則です。

于 2010-07-16T04:19:33.737 に答える
2

ステートメントは、ifnull 値を受信しないという契約/期待をチェック/強制しています。そのため、達成しようとしていることの実際のロジックとは関係がないため、関数の残りの部分から分離することをお勧めします (ただし、このケースは非常に単純です)。

ただし、ほとんどの場合、コードの意図をできるだけ明示することを好みます。他の人が読みやすいように関数を再構築できることがある場合は、それを実行してください。プロのプログラマーとしてのあなたの目標は、あなたの後にあなたのコードを保守しなければならない人々のためにプログラミングすることです (2 年後のあなた自身も含めて...)。彼らを助けるためにできることは何でもやる価値があります。

于 2010-07-16T04:22:17.707 に答える
1

else を持つことは正しいことであり、ロジックと実行可能性の点では何も問題はありませんが、関数が if/else スコープの外に return ステートメントを持たない最初の WTF の瞬間を避けたいと思っています。

于 2010-07-16T04:17:58.977 に答える
0

プログラマーの意図についての証拠をもたらす次のいずれかを書くのと同じだからです。

boolean containsSmiley(String s) {
    if (s == null)   // The curly braces are not even necessary as the if contains only one instruction.
        return false;

    return s.contains(":)");
}

またはこれでも:

boolean constainsSMiley(String s) {
    return string.IsNullOrEmpty(s) ? false : s.Contains(":)");
}

これらの 2 つの形式は次のとおりです。

  1. よりエレガント。
  2. 読みやすい;
  3. 読書プログラマーにとってよりスリムで迅速です。
于 2010-07-16T08:37:13.477 に答える
0

まあ、理由のいくつかは単なる慣例ですが、上記の形式には1つの利点があります...

return ステートメントをコーディングするときは、最後のステートメントをデフォルトの戻り値にするのが一般的です。これは主にリファクタリング中に役立ちます。else 句は他の構造に巻き込まれる傾向があり、誤ってツリーの奥深くに移動する可能性があります。

于 2010-07-16T05:37:59.810 に答える
0

最初の形式は単純に冗長ではありません。値を返すと、現在の関数のスコープを自動的に離れて呼び出し元に戻るため、その後のコードは IF ステートメントが true と評価されない場合にのみ実行されます。その後、何かを返します。

于 2010-07-16T04:09:30.593 に答える
0

私は読みやすさを主張します。コードの動作を理解しようとしてコードの画面をスキャンしている場合、それは開発者に対する視覚的なプロンプトです。

...しかし、私たち全員がコードに非常によくコメントしているので、それは本当に必要ではありませんよね? :)

于 2010-07-16T04:09:46.053 に答える
0

私の意見では、2番目の方がより理にかなっています。これは、スイッチのように、より「デフォルト」のアクションとして機能します。他の出口点のいずれにも一致しない場合は、それを実行します。あなたはそこにelseを本当に必要としません。関数全体が if と elseif のみである場合、else は 1 つの巨大な条件であるため、そこでは意味があります。複数の条件とその中で実行される他の関数がある場合は、最後にデフォルトの return が使用されます。

于 2010-07-16T04:10:55.150 に答える
0

ご覧のとおり、読みやすさについては、人によって意見が異なります。コードの行数が少ないほどコードが読みやすくなると考える人もいます。他の人は、2 番目の形式の対称性により読みやすくなると考えています。

私の見解は、おそらく、両方の見解が正しいということです...それらを保持している人々にとっては. そして当然のことながら、誰もが最適に読めるコードを書くことはできません。したがって、最善のアドバイスは、義務付けられたコーディング標準で行うように指示されていることに従い (これについて何か述べられている場合)、通常は常識を働かせることです。(もしあなたが、彼のやり方が「正しい」と主張する騒々しい愚痴に悩まされているなら... ただ流れに乗ってください。)

于 2010-07-16T04:22:43.480 に答える
0

そのような状況でelseが使用されている場合、Eclipseにはオプションの(デフォルトではオフになっている)警告があるためです;)。

于 2010-07-16T05:00:04.663 に答える
0

メンテナンスの観点から、複数の出口ポイントよりも 1 つの出口ポイントを優先します。最終結果は、n 個の終了ポイントではなく、1 つの終了ポイントで変更 (または装飾) できます。

于 2010-07-16T05:46:12.827 に答える
0

よりシンプル/短い場合の 2 番目の形式。これは必ずしも明確であるとは限りません。私はあなたが最も明確だと思うことをすることをお勧めします..個人的に私は書きます.

static boolean containsSmiley(String s) { 
    return s != null && s.contains(":)"); 
} 
于 2010-07-16T06:03:47.437 に答える