PHPプログラムの複雑度をPHPMDで客観的に測定する
プログラムが複雑になると、テストケースが増大し、保守性が低くなることは直感的・経験的に理解できますが、この複雑度を客観的に測定する方法として循環的複雑度(Cyclomatic complexity)があります。PHPでは、PHPMDを使って循環的複雑度を測定することができます。
インストール
PHPMDをインストールする方法はいくつかありますが、ここでは簡単な phpmd.phar
を利用する方法を紹介します。 phpmd.phar
を利用するためには、最新版をダウンロードして実行権限を付与するだけです。
$ wget -c http://static.phpmd.org/php/latest/phpmd.phar -O phpmd $ chmod +x phpmd
なお、 phpmd.phar
を実行するためには php-bz2
が必要なので、インストールされていない場合はインストールしておきます。次に示すのは Ubuntu 16.04 で apt を使ってインストール例です。
$ sudo apt install php-bz2
以下を実行してPHPMDのバージョン情報が表示されることを確認します。
$ ./phpmd --version PHPMD 2.5.0
複雑度の基準
それでは早速PHPMDで循環的複雑度を測ってみますが、その前に複雑度の基準について説明します。PHPMDのドキュメントによると、複雑度は以下のように分類されます。
数値 | 複雑度 |
---|---|
1~4 | 低 |
5~7 | 中 |
8~10 | 高 |
11以上 | 非常に高い |
https://phpmd.org/rules/codesize.html#cyclomaticcomplexity
デフォルトではPHPMDがレポートを出力する閾値は10となっているため、複雑度がそれより低い場合はレポートを出力しません。今回は確認のため複雑度が低くてもレポートを出力するようにPHPMDのルールセットを変更します。ルールセットを変更するには以下のようなXMLを ruleset.xml
というファイル名で保存します。reportLevel
を 1 に設定するのがポイントです。
<?xml version="1.0"?> <ruleset xsi:nonamespaceschemalocation="http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:schemalocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://pmd.sf.net/ruleset/1.0.0" name="PHPMD rule set"> <rule ref="rulesets/codesize.xml/CyclomaticComplexity"> <properties> <property value="1" name="reportLevel"></property> </properties> </rule> </ruleset>
プログラム例
それでは簡単なプログラムを書いてPHPMDを実行してみます。まずは次のようなプログラムを sample1.php
というファイル名で保存します。
<?php function sample1() { echo "Hello, world."; }
次のコマンドを実行します。
$ ./phpmd sample1.php text ruleset.xml sample1.php:2 The function sample1() has a Cyclomatic Complexity of 1. The configured cyclomatic complexity threshold is 1.
Cyclomatic Complexity of 1
が出力されたので、循環的複雑度は 1 であることが確認できます。
次に、プログラムを少し複雑にしてみます。次のようなプログラムを sample2.php
というファイル名で保存します。
<?php function sample2($format) { if ($format === 'xml' || $format === 'text' || $format === 'html') { echo "valid format."; } else { echo "invalid format."; } }
$ ./phpmd sample2.php text ruleset.xml sample2.php:2 The function sample2() has a Cyclomatic Complexity of 4. The configured cyclomatic complexity threshold is 1.
Cyclomatic Complexity of 4
が出力されたので、循環的複雑度は 4 であることが確認できます。
このプログラムを in_array()
を使うように変更してみます。
<?php function sample2($format) { if (in_array($format, array('xml', 'text', 'html'), true)) { echo "valid format."; } else { echo "invalid format."; } }
$ ./phpmd sample2.php text ruleset.xml sample2.php:2 The function sample2() has a Cyclomatic Complexity of 2. The configured cyclomatic complexity threshold is 1.
循環的複雑度は 2 になりました。つまり、先ほどの in_array()
を使わないバージョンより、 in_array()
を使うバージョンの方が循環的複雑度が小さくなったことを意味します。
まとめ
循環的複雑度はあくまで指標のひとつです。循環的複雑度が小さいプログラムの可読性や効率が必ず高いとは限りません。しかしながら、プログラムの複雑度を計測することで、プログラムを変更した後の複雑度の変化を客観的に知ることができます。プログラミングの際に循環的複雑度を意識し、計測することで、よりよいソフトウェアを開発するためのヒントになるのではないでしょうか。
- 作者: Andrew Hunt,David Thomas,村上雅章
- 出版社/メーカー: オーム社
- 発売日: 2016/10/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (5件) を見る