web-dev-qa-db-ja.com

長いif条件をフォーマットする最も読みやすい方法?

長い曲がりくねったif状態は、可能な限り回避する必要がありますが、場合によっては、それらすべてを記述してしまうこともあります。非常に単純な条件であっても、関連するステートメントが非常に冗長になる場合があるため、条件全体が非常に長くなります。それらをフォーマットする最も読みやすい方法は何ですか?

if (FoobarBaz::quxQuux(corge, grault) || !garply(waldo) || fred(plugh) !== xyzzy) {
    thud();
}

または

if (
    FoobarBaz::quxQuux(corge, grault)
 || !garply(waldo)
 || fred(plugh) !== xyzzy
) {
    thud();
}

または

if (FoobarBaz::quxQuux(corge, grault)
    || !garply(waldo)
    || fred(plugh) !== xyzzy) {
    thud();
}

または

thudable = FoobarBaz::quxQuux(corge, grault);
thudable ||= !garply(waldo);
thudable ||= fred(plugh) !== xyzzy;

if (thudable) {
    thud();
}

または他の好み?

45
deceze

多くの場合、長いif条件はリファクタリングが必要なコードの兆候ですが、回避できない場合もあります。それらの場合、私は最初の方を好みます:

if (bar || baz || quux) { ... }

何が起こっているのかを1行でわかるからです。ただし、可能であれば、次のようなことをしたいと思います。

function foo() {
  return bar || baz || quux;
}

if (foo()) { ... }
32
user8

継続を示すために演算子を最後に残すのが好きです:

if (the_function_being_called() != RETURNCODE_SUCCESS &&
    the_possibly_useful_recovery_strategy() == RETURNCODE_EPICFAIL &&
    this_user_has_elected_to_recieve_error_reports)
{
    report_error();
}
21
AShelly

私は意味のある変数名の大ファンです:

const bool isInAStrangeCondition =
    FoobarBaz::quxQuux(corge, grault) ||
    !garply(waldo) ||
    fred(plugh) !== xyzzy;

if (isInAStrangeCondition) {
    thud();
}

または、上記のように、関数としてリファクタリングします。

12

厄介な部分式、またはそれらすべてをブール変数として取り出します。次に、「if」ステートメントのトップレベルのブール論理を明確にすることができます。私が行っているような作業では、必ずしもORやANDで処理されているわけではありません。

bool goodblah = some_mess < whatever;
bool frobnacious = messy_crud != junky_expression;
bool yetanother = long_winded_condition;

if (goodblah || (frobnacious && yetanother))   {
    ...
}

これは、デバッガーで特に役立ちます。デバッガーでは、 'if'を実行する前にすべてのブール値を確認できます。

7
DarenW

演算子を新しい行の先頭に揃える傾向があるので、用語を組み合わせる方法を覚えています(長いロジックと長い演算の両方)。このような:

if (first_attempt(data) == SUCCESS
    || (reusable(data) && second_attempt(data) == SUCCESS)
    || (still_reusable(data) && third_attempt(data) == SUCCESS))
  return SUCCESS;

これが機能するのは、2スペースずつインデントするか、複数行の述語をさらにインデントするように環境を設定した場合のみです。

6
Hoa Long Tam

私は以下のファンです。

if (really_long_expression && another_really_really_long_expression && 
            another_very_long_expression_OMG_id_it_long){
    bugs();
}

このように、それはまだif式のように見え、分割されたif式ではありません。インデントは、それが前の行の続きであることを示すのに役立ちます。

また、開始ブラケットが前の行の終わりになるまでインデントして、想定どおりにif式の終わりになるようにすることもできます。

0
EpsilonVector