Hudson+phpcpdで継続的に重複コードをチェックする

 2010/09/27
このエントリーをはてなブックマークに追加

Hudson等を使った継続的インテグレーションでは、テストの自動実行の他にも、ドキュメントの自動作成、コーディング規約の自動チェック、重複コードのチェック(DRY原則のチェック)等を行うことができるし、実行するべきである。 今回は、PHP+Hudsonの環境でコードの重複を継続的にチェックできるようにしてみた。

phpcpd

PHPでコードの重複を検査するには、phpcpdというツールを使うのが定番である。 phpcpdはpearコマンドでインストール可能だ。 なお、phpcpdを利用するためには、pearが1.9.1以上である必要がある。

インストール手順

pear upgrade pear
pear channel-discover pear.phpunit.de
pear channel-discover components.ez.no
pear install phpunit/phpcpd

使い方

phpcpd 対象ディレクトリ名

こんな結果が出る。この場合では、6.72%の重複コードがあることが分かる。

phpcpd 1.3.1 by Sebastian Bergmann.

Found 128 exact clones with 4775 duplicated lines in 101 files:

 - lib/session/PublicSessionHandler.class.php:28-119
    lib/session/AdminSessionHandler.class.php:28-119

(略)

  - lib/components/StringUtil.php:1173-1181
    lib/components/StringUtil.php:1316-1324

6.72% duplicated lines out of 71028 total lines of code.

ただし、Smarty等によってコンパイルされたPHPコード等の自動生成のコードは類似性が高いので除外してみると良いかもしれない。

Smartyのコンパイルディレクトリ等特定のディレクトリを除く方法は

phpcpd --exclude /path/to/exclude 対象ディレクトリ名

とすれば良い。除外対象が複数ある場合は、複数個の–excludeオプションを指定する 今扱っているプロジェクトのコードでSmartyを除いて重複チェックをかけてみたところ、1.40%だった。

PMD-CPD互換のXML形式で出力したければ、

phpcpd --log-pmd /path/to/output.xml 対象ディレクトリ名 

とする。

Hudsonの自動チェックに組み込む方法

phpcpdとHudsonを連携させるためには、HudsonのDRYプラグインを使う。

DRYプラグインのインストール

まず、Hudsonのプラグインの管理画面で、DRYプラグインをインストールする。

インストールが終わったらHudsonを再起動。

プロジェクトの作成

既にプロジェクトが存在する場合は、設定画面を開く。DRYプラグインのインストールによって以下のような項目が追加になっているはずだ。 この重複コード分析の集計にチェックを入れる

phingのbuild.xmlの設定

Hudsonでphpプロジェクトを扱う際はphingを使うのが定石。でphingの設定ファイルである、build.xmlに以下の内容を追記する。(パスは自分のプロジェクトに置き換えること)

<target name="cpd">
  <exec command="phpcpd --log-pmd /path/to/hudson/jobs/projectname/workspace/reports/cpd.xml --exclude /path/to/exclude /path/to/target" />
</target>

また、ここで、新たにcpdというターゲットを追加したので、プロジェクトの設定画面のビルドの設定欄にcpdをターゲットとして追加する。

以上で準備完了だ。

Hudson+phpcpdの画面

今回はEコマース用のアプリケーションである。EC-CUBEを解析の材料に使ってみた。 Hudsonでの解析時間は1分も掛からない。

各ディレクトリ毎の重複度合いがグラフで表示される。赤い箇所は重要度が高い重複。

フォルダ内の各ファイルの重複度合いがグラフで表示される。

ファイル単位でのチェック結果。何行重複しているか、何箇所あるか等が分かる。

具体的な重複箇所をソースコードをハイライトして表示できる。

どう使うか?

プロジェクト開始時点で、これを組み込めるのであれば、初期の段階からとにかく継続的に実行して、プロジェクトのソースの中に、コピーペーストコードが散在しないように、継続的に監視するべきだ。(コーディング規約のチェック等も同様)

レガシーコードの場合は、この重複チェックのジョブだけを別プロジェクトとして切りだして定期的に実行しつつ、重複度の高いところに修正をかける際に、都度リファクタリングをしていくことになるだろう。(但しリファクタリングするためには自動テストでガードされていることが大前提である)

 2010/09/27
このエントリーをはてなブックマークに追加