web-dev-qa-db-ja.com

16兆を超えるNPathの複雑さは現実的ですか?または、ツールを壊しましたか?

PHPMD( http://phpmd.org/ )を使用してPHPコード(1153行)の大きなチャンクを測定したところ、コードに16244818757303403077832757824のNPathの複雑さ。

私にとっては、それはとてつもなく大きな数のように見え、おそらくPHPMDが何らかの形で壊れていることを示唆しています。人間が作成したコードがNPathの複雑さを非常に高くすることは可能ですか?循環的複雑度は351です。

重要な可能性がある2つの詳細-

  1. これはHTMLと混合された手続き型コードであり、PHPMDはオブジェクト指向コードのみを測定します。これを回避するために、ファイル全体を単一の関数でクラスにラップしました。これは、ファイルの使用方法の代表です。

  2. このファイルは一連の入れ子になったswitchステートメントで構成されており、その中にはif..elseステートメントがたくさんあります。そのため、かなり複雑です。

編集

PHPMDが私に嘘をついているかどうかは疑っていないことを明確にしたいと思います。私はコードがひどい混乱であることを知っています。コードが本当にそれほど悪いものになる可能性があるのか​​と思います。答えはイエスのようです、それは非常に可能です。

13
Jez

これは完全に可能です。それぞれ10ケースの35個のスイッチケースコンストラクトがあると仮定します。これにより、各スイッチが次々に発生する場合、おおよそのサイクロマティック複雑度は350になります。最初のスイッチは10パスを提供します。 2番目のスイッチは別の独立した10パスを提供するため、ここまでのパスは10・10になります。 3番目のスイッチを使用すると、10・10・10 =10³のパスが取得され、10が取得されるまで続きます。35 合計パス!これは、1.6・10の結果よりもさらに高い28 これはおそらく、異なる分岐要因と、コードを通るパスの数を減らすネストされた制御フローステートメントが原因です。

与えられた循環的複雑度cの最悪のシナリオとして、最大2c コードを通る非循環パス(ここ:2351 = 4.6・10105)。

ツールの判断は明らかです。あなたが扱っているコードは、複雑で、テストも、保守も困難な混乱です。それをより小さな独立した機能に分割し、繰り返しを抽象化することを検討してください。例えば。 HTML生成をPHPスクリプトのメインロジックから分離できます。

24
amon

この説明 によると、NPathの複雑さは循環的複雑度において指数関数的です。

これらのステートメントが2つある場合、単純なifステートメントを使用すると、2つのステートメント条件のtrue/falseの4つの可能な組み合わせに対応する、コードを通る4つのルートになります。別のifステートメントを追加すると、8になります。

つまり、サイクロマティックとNPathの複雑さのすべてがifステートメントの長いリストに由来する場合、等式はNPath = 2^cyclomaticになります。それをあなたの数と比較すると、2 ^ 351 = 4.6 * 10 ^ 105であり、報告したNPathの複雑さよりはるかに高いです。

実際には不可能であるパスのカウントを回避するために、PHPMDがどのくらいの量を実行するのかわかりません(たとえば、2つの相互に排他的な条件が両方ともtrueと評価される)。おそらく手動で分析すると、多くのパスが実際には不可能であることが明らかになるため、コードはNPathメトリックを拡張するように記述されています。上記を続けるために、351個のifステートメントのリストがあり、実際には1つしか入力されていないことを確認できた場合、それをif ... elseステートメントのチェーンに変えて、NPathの複雑さを4.6 * 10から下げることができます。 ^ 105から353。

しかし、質問に含まれている情報だけで、そのような単純化がどれほど可能であるか、またはPHPMDによってすでに行われているのかがわからない場合、その数は現実的なようです。

5
Ben Aaronson