web-dev-qa-db-ja.com

長いif条件のPSR-2標準

この場合の標準は見つかりませんでした。

if ($a == $b && $b == $c && $c == $d && $g == $d) {

}

または

if (($a == $b && $b == $c) && ($c == $d && $g == $d)) {

}

Var-namesが長くなり、80文字を超えると想像してください。これをどのように処理すればよいですか?次のようになります。

if (
       $a == $b
    && $b == $c
    && $c == $d
    && $g == $d
) {

    }
47
user3631654

このケースには推奨/慣習はありません。ハルシオンがすでに述べたように、これは非常に例外的なケースです。

ただし、パラメーターの長いリストを使用した関数呼び出しには推奨事項があります。

引数リストは複数の行に分割することができ、各後続の行は1回インデントされます。その場合、リストの最初の項目は次の行になければならず、1行につき1つの引数のみが存在する必要があります。

<?php
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);

したがって、もしあなたのものに似たifステートメントを作成しなければならなかったら、私はこれをするでしょう:

if (
    $a == $b &&
    $b == $c &&
    $c == $d &&
    $g == $d
) {
    // do something
}

ご覧のとおり、これは自分が提案した解決策とほぼ同じですが、&&条件の後の演算子。

57
Nic Wortel

個人的に、私は好む

if ($a == $b
    && $b == $c
    && $c == $d
    && $g == $d
) {
    // code here...
}

各行では、二重アンパサンドで始まり、次のステートメントが他のステートメントとは別であることを示しています。行末にアンパサンドを付けると、行の長さが大きく異なる場合に、アンパサンドが目立たなくなる可能性があります。

例えば;

if ($a == $b && 
    $b == $c && 
    $thisisamuchlongerstatementbecauseofthisvar == $d && 
    $g == $d
) {
    // code here...
}

この場合、各行が二重アンパサンドで接続されていることを知るために、コードをさらにスキャンする必要があります。

50
Maurice

編集

1年後、コードを書き直してif文を短くすることを強くお勧めします。変数または関数呼び出しを通じて。

元の

私はこの状況に陥ったので、次の形式で行くことにしました。

if (
    $a == $b &&
    $b == $c &&
    $c == $d &&
    $g == $d) {
}

しかし、私はphpcbfを使用し、以前のコードを(PSR2標準に従って)変換しました:

if ($a == $b &&
    $b == $c &&
    $c == $d &&
    $g == $d) {
}

もっと知りたかったのですが、どこにも書かれていない場合、これが標準によって期待される動作であることをどのように知るのでしょうか?答えは簡単です。ケースは、標準によって次の文で考慮されます。

左括弧の後にスペースがあってはなりません。

これは、2番目のスニペットが、 php-fig で宣言されているように、PSR-2標準に準拠する唯一のスニペットである理由を説明しています。

12
tleb

主に読みやすく、バージョン管理の動作を改善するために、行の先頭に長いifステートメントを論理演算子で配置することを好みます。

他の回答でも言及されているように、長いif文があるのは通常コード臭です。しかし、時にはあなたはそれをしなければならないか、コードが既にそこにあり、あなたはそれを書き換えることができないので、それがすでに悪いことであるなら、それはさらに混乱しないようにするのに役立ちます。

また、これらのことは、異なる要素が非常に長い単一の「and」のみのifステートメントにも適用され、それでも複数行に分割する必要があります(たとえば、長い変数名またはクラス名)。

if (
    $something->getValue() === 'some_value'
    || (
        $something instanceof SomeClass
        && $something->has($someNumber)
        && $someNumber > 42
    )
) {
    // do something
}

読みやすさ:すべての論理演算子は垂直にグループ化されているため、各行にどの演算子があるかを即座に確認できます。あなたの目がコードをスキャンするとき、それはちょうどまっすぐ垂直に動くことができ、実際に余分な論理レベルがあるときだけ水平に動く必要があります。

オペレーターが行の終わりにいる場合、目が不規則な長さの行の間でランダムに前後に移動する必要があります。

バージョン管理でのより良い動作:if文の最後に余分な句が追加されると、これはバージョン管理で1行追加され、0が削除されます。

diff --git a/3.php b/3.php
index 367c57c..2a40c3a 100644
--- a/3.php
+++ b/3.php
@@ -6,6 +6,7 @@ 
    if (
         $something instanceof SomeClass
         && $something->has($someNumber)
         && $someNumber > 42
+        && $anotherCase
    ) {
     // do something

論理演算子を最後に配置すると、2行が追加され、1行が削除されます。これにより、有用な情報がわかりにくくなります.Gitで注釈を付けると、最後の変更のコミットメッセージが両方の行に表示されるため、演算子を追加した行のコミットメッセージを表示するには、前のバージョンに移動する必要があります。

diff --git a/4.php b/4.php
index f654780..2b9e0c5 100644
--- a/4.php
+++ b/4.php
@@ -5,7 +5,8 @@ 
    if (
        $something instanceof SomeClass &&
        $something->has($someNumber) &&
-       $someNumber > 42
+       $someNumber > 42 &&
+       $anotherCase
     ) {
     // do something
4
inwerpsel

私のお気に入りのアプローチは、次のようにIFステートメントから部分式を削除することです。

_$c1 = $a == $b;
$c2 = $b == $c;
$c3 = $c == $d;
$c4 = $g == $d;
if ($c1 && $c2 && $c3 && $c4) {
}
_

このアプローチにより、デバッグも容易になります。

2番目のケースは、 論理演算子の連想プロパティ であるため、最初のケースと同等です。したがって、_$a && $b && $c_は$a && ($b && $c)と同じ_($a && $b) && $c_と同じです。

3
Nicolas

私も最初にそれを好む:

if (   self::LOG_ALL
    || (    self::DEBUG__EXECUTION_TIME__IS_ENABLED
        && (self::DEBUG__EXECUTION_TIME__THRESHOLD_SECONDS < $trxDurinationSeconds)
       )
) {
    doSomething();
}
1
tol

異なる用語で操作について考えてみることをお勧めします。例えば:

if (count(array_unique([$a, $b, $c, $d, $g])) == 1)

おそらく、アルゴリズム全体をセットのより多くの操作として表現し、個々の変数の代わりに配列を使用し、上記のようにセットの論理操作を使用できることがわかるでしょう。これにより、大幅に異なるコードが読みやすくなります。

リファクタリングの別の例:

namespace My;

UnexpectedValueException::assertAllEqual($a, $b, $c, $d, $g);


class UnexpectedValueException extends \UnexpectedValueException {

    public static function assertAllEqual(/* $value, ... */) {
        $args = func_get_args();
        if (count(array_unique($args)) > 1) {
            throw new static(sprintf('[%s] are not all equal', join(', ', $args)));
        }
    }

}
1
deceze

私はこのスタイルでそれをすることを好む:

if (condition1
|| (condition2_1 
    && condition2_2
    && condition2_3)
&& (c3 && c4) {
    // do something
}

しかし、繰り返しますが、ifはできる限りシンプルにしてください。

たぶん大きな条件を複数のifに分けるのが良い考えです。

あなたの質問のために、配列を取り、すべての&&が満たされます。次に、私のメインコードであなたが好きになるだろう

$arr = [$a => $b, $b => $c, $c => $d];
// or you can create array of arrays [[$a, $b], [$b, $c] ...]

if (allTrue($arr))
    // do something
0
Lemures

新しい標準 PSR-12 (PSR-2を置き換えることを意味する)がこの質問を明確にしていることに言及する価値があります。

括弧内の式は、複数の行に分割できます(後続の各行は少なくとも1回インデントされます)。そうするとき、最初の条件は次の行になければなりません。閉じ括弧と開き括弧は、それらの間に1つのスペースを空けて独自の行に一緒に配置する必要があります。条件間のブール演算子は、両方の組み合わせではなく、常に行の先頭または末尾になければなりません。

<?php

if (
    $expr1
    && $expr2
) {
    // if body
} elseif (
    $expr3
    && $expr4
) {
    // elseif body
}

ソース: https://www.php-fig.org/psr/psr-12/#51-if-elseif-else

0
Ernesto Allely