PHPで冗長化したコードを自動で検出してコードの最適化に使える「PHPCPD」
2009年04月09日-
PHPで冗長化したコードを自動で検出してコードの最適化に使える「PHPCPD」。
プログラムが大きくなってくると、同じような処理を違う場所で何度もやっているということがあります。

ソースコードのファイル数が多くなってくるとそれを探すのは大変ですが、その冗長部分を自動で検出できるPHP Copy Paste Detector(CPD)のご紹介。
使い方の流れが書かれていたので、試してみました(Windows上で実施)
PHPCPDをPEARコマンドでインストールする
1) channel-discover でpearチャネル追加
Windowsの場合はコマンドプロンプトを開いて、pear コマンドを実行。Unix系でも同様にpearコマンドを実行
> pear channel-discover pear.phpunit.de
Adding Channel "pear.phpunit.de" succeeded
Discovery of channel "pear.phpunit.de" succeeded
2) phpunit/phpcpd をインストール
PEAR 1.7.1以降が必要なので、それ以下の場合は、pear upgrade PEAR でアップグレードしておきます。
> pear channel-discover components.ez.no
> pear install phpunit/phpcpd
downloading phpcpd-1.1.1.tgz ...
Starting to download phpcpd-1.1.1.tgz (8,078 bytes)
.....done: 8,078 bytes
install ok: channel://pear.phpunit.de/phpcpd-1.1.1
と、インストールは以上で簡単ですね。
PHPCPDを使う
3) phpcpd コマンドを使う
インストールが終わったら、phpcpdコマンドが使えるので以下のように実行します。
引数には、解析したいプログラムディレクトリを指定します。
> phpcpd ./phpbb
今回は、PHPで有名なオープンソースプログラムの phpBB を解析にかけてみました。
結果を見てみましょう。
> phpcpd ./phpbb
phpcpd 1.1.1 by Sebastian Bergmann.
Found 49 exact clones with 1330 duplicated lines in 42 files:
- includes/acp/acp_attachments.php:254-272
includes/acp/acp_board.php:535-553
- includes/acp/acp_database.php:1542-1562
includes/acp/acp_database.php:1636-1656
- includes/acp/acp_styles.php:828-851
includes/acp/acp_styles.php:1184-1207
- includes/acp/auth.php:461-472
includes/acp/auth.php:547-558
- includes/acp/auth.php:32-38
includes/auth.php:40-46
...( 省略 )
0.78% duplicated lines out of 171326 total lines of code.
表示の説明をすると、以下の2ファイルの、それぞれ254?272行と、535-553行が被っているということになります
- includes/acp/acp_attachments.php:254-272
includes/acp/acp_board.php:535-553
49箇所のコピペが42ファイルで、1330行も見つかりました。
171326行分の1330行ということで、0.78% が重複しているという結果が出ました。
実際に開いてみてファイルを比べてみるとどうでしょうか
includes/acp/acp_attachments.php
foreach ($display_vars['vars'] as $config_key => $vars)
{
if (!is_array($vars) && strpos($config_key, 'legend') === false)
{
continue;
}
includes/acp/acp_board.php
foreach ($display_vars['vars'] as $config_key => $vars)
{
if (!is_array($vars) && strpos($config_key, 'legend') === false)
{
continue;
}
インデントの数は違えど、きちんと検出してくれています。
また、phpcpdでは、検出の条件も指定できます。
例えば、デフォルトでは、5行以下や、70トークン以下の共通部分については、無視してしまいます。
行数の指定を--min-lines 4でオプション指定すると4行以下を無視する、という風に無視の条件をゆるく出来ます。
トークンに関しては、--min-tokens 40 のようにして同様に指定することが可能です。
より多くの冗長コードを見つけたい場合に使えるでしょう。
> phpcpd --min-lines 4 --min-tokens 40 ./phpbb のようにして実行します。
共通部分は、関数やクラスに出来る部分は出来るだけ共通化して冗長性を少なくし、コードのメンテナンス性を高める手助けになりそうなツールですね。
で、この機能を提供している部分はクラスになっているので、他のツールに組み込んだりするのも簡単かも。
phpcpd の中身は以下のように、たったの2行です。
<?php
require 'PHPCPD/TextUI/Command.php';
PHPCPD_TextUI_Command::main();
XML形式での重複部分出力が出来たりもするようなので、別言語から使ったりPHPからrequireせずに読み込んだり出来ますね。
phpcpd --log-pmd projectPhpcpd.xml ./adminphpBBほどの規模になってしまうと、重複が大きくて直すのが大変かもしれませんが、あまりプログラムの大きくないうちに、これを走らせてできるだけ冗長化をなくす努力をしておくと、メンテナンス性が高まって後々に楽になりそうですね。こうしたツールがないと、冗長を調べるのは大変というか不可能に近いところがあるので覚えておくとよいかも。
関連エントリ
最新のブログ記事(新着順)
- 15000以上のいい感じの線形アイコン「Lineicons」
- CSSやTailwindでのCSSスニペットライブラリ「CSS Snippets Library」
- AIを使ってサイトマップが作れる「Octopus.do」
- ライブラリ依存のないモーダルオープンライブラリ「Blendy」
- 個性的な明朝フリーフォント「築豊初号明朝OFL」
- CSSで太陽が差し込むようなアニメーション実装
- 可愛くアニメーションする「beautifully crafted animated icons」
- アイソメトリックなアイコンがアイコンがPNG,SVGでゲットできる「Isoicons」
- ユニークなカタカナフォントtorisippo
- 美しいメッシュグラデーションをCSSで簡単に取得できる「MSHR」
- 過去のエントリ