iT邦幫忙

DAY 16
6

逐步提昇PHP技術能力系列 第 16

逐步提昇PHP技術能力 - 開發工具 : 使用pdepend / phpmd 等工具檢測程式碼品質

今天不寫code,來看看怎樣利用一些工具來檢測PHP原始碼的品質。

自己比較常拿來參考的metric,除了coding style之外,常用的有LOC(lines of code)、CCN(Cyclomatic Complexity Number)等,就來看看這些工具怎麼用...其實都還蠻簡單的。
參考:

  1. http://pdepend.org/
  2. http://phpmd.org/

首先來安裝一下PDepend。PDepend現在也支援使用composer安裝,只要在require-dev中加上一條:"pdepend/pdepend":"版本"就可以,例如:

{
    "require":{
    },
    "require-dev": {
        "phpunit/phpunit":"~3.7.5",
        "phpunit/php-invoker":"~1.1.0",
        "phpunit/phpunit-selenium":"~1.3.2",
        "pdepend/pdepend":"~1.1"
    }
}

修改過composer.json之後,執行composer update就可以安裝好。不過安裝完之後,pdepend的執行檔會放在vendor目錄中,為了方便執行,可以做一下ln:

> ln -s vendor/pdepend/pdepend/src/bin/pdepend

然後就可以執行。首先來執行所有的測試,然後產出xml格式的報表:

Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./pdepend --summary-xml=result.xml ~/Dropbox/Shared/b2c/src/class/GLF
PHP_Depend @package_version@ by Manuel Pichler

Parsing source files:
..........                                                      10

Executing CyclomaticComplexity-Analyzer:
...                                                             64

Executing ClassLevel-Analyzer:
..                                                              55

Executing CodeRank-Analyzer:
                                                                14

Executing Cohesion-Analyzer:
....                                                            90

Executing Coupling-Analyzer:
...                                                             68

Executing Hierarchy-Analyzer:
..                                                              58

Executing Inheritance-Analyzer:
                                                                18

Executing NPathComplexity-Analyzer:
...                                                             64

Executing NodeCount-Analyzer:
..                                                              44

Executing NodeLoc-Analyzer:
..                                                              54

Generating pdepend log files, this may take a moment.

Time: 00:01; Memory: 11.75Mb

然後就會產出result.xml檔:

<?xml version="1.0" encoding="UTF-8"?>
<metrics generated="2013-10-16T22:23:22" pdepend="@package_version@" ahh="0.4" andc="0.44444444444444" calls="100" ccn="79" ccn2="81" cloc="116" clsa="0" clsc="9" eloc="550" fanout="3" leafs="7" lloc="342" loc="714" maxDIT="1" ncloc="598" noc="9" nof="0" noi="1" nom="30" nop="4" roots="2">
  <files>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Acl/AclChecker.php" cloc="7" eloc="13" lloc="8" loc="23" ncloc="16"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Acl/AclRuleLogin.php" cloc="7" eloc="12" lloc="7" loc="21" ncloc="14"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Base/EventEmitter.php" cloc="13" eloc="20" lloc="12" loc="35" ncloc="22"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Controllers/Index.php" cloc="13" eloc="34" lloc="30" loc="56" ncloc="43"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Controllers/Shop.php" cloc="31" eloc="212" lloc="122" loc="252" ncloc="221"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Controllers/ViewCourses.php" cloc="13" eloc="159" lloc="96" loc="187" ncloc="174"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Web/Controller.php" cloc="11" eloc="62" lloc="40" loc="76" ncloc="65"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Web/MysmartyView.php" cloc="7" eloc="19" lloc="13" loc="27" ncloc="20"/>
    <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Web/View.php" cloc="7" eloc="13" lloc="9" loc="21" ncloc="14"/>
  </files>
  <package name="GLF\Acl" cr="0.15" noc="2" nof="0" noi="1" nom="6" rcr="0.15">
    <class name="AclChecker" ca="0" cbo="0" ce="0" cis="2" cloc="0" cr="0.15" csz="3" dit="0" eloc="8" impl="0" lloc="4" loc="11" ncloc="11" noam="0" nocc="0" nom="2" noom="0" npm="2" rcr="0.15" vars="1" varsi="1" varsnp="0" wmc="2" wmci="2" wmcnp="2">
      <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Acl/AclChecker.php"/>
      <method name="__construct" ccn="1" ccn2="1" cloc="0" eloc="3" lloc="1" loc="3" ncloc="3" npath="1"/>
      <method name="check" ccn="1" ccn2="1" cloc="0" eloc="5" lloc="3" loc="5" ncloc="5" npath="1"/>
    </class>
    <class name="AclRuleLogin" ca="0" cbo="0" ce="0" cis="2" cloc="0" cr="0.15" csz="3" dit="0" eloc="7" impl="1" lloc="3" loc="10" ncloc="10" noam="0" nocc="0" nom="2" noom="0" npm="2" rcr="0.2775" vars="1" varsi="1" varsnp="0" wmc="2" wmci="2" wmcnp="2">
      <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Acl/AclRuleLogin.php"/>
      <method name="__construct" ccn="1" ccn2="1" cloc="0" eloc="3" lloc="1" loc="3" ncloc="3" npath="1"/>
      <method name="check" ccn="1" ccn2="1" cloc="0" eloc="4" lloc="2" loc="4" ncloc="4" npath="1"/>
    </class>
  </package>
  <package name="GLF\Base" cr="0.15" noc="1" nof="0" noi="0" nom="2" rcr="0.15">
    <class name="EventEmitter" ca="0" cbo="0" ce="0" cis="2" cloc="0" cr="0.15" csz="3" dit="0" eloc="15" impl="0" lloc="8" loc="18" ncloc="18" noam="0" nocc="0" nom="2" noom="0" npm="2" rcr="0.15" vars="1" varsi="1" varsnp="0" wmc="5" wmci="5" wmcnp="5">
      <file name="/Users/fillano/Dropbox/Shared/b2c/src/class/GLF/Base/EventEmitter.php"/>
      <method name="on" ccn="2" ccn2="2" cloc="0" eloc="6" lloc="3" loc="6" ncloc="6" npath="2"/>
      <method name="emit" ccn="3" ccn2="3" cloc="0" eloc="9" lloc="5" loc="9" ncloc="9" npath="3"/>
    </class>
  </package>
.....

每一個量測的mertic都是用簡稱,例如loc、ccn等,可以參考他的說明:http://pdepend.org/documentation/software-metrics/index.html

除了各個品質量測的資料,他也可以產出一些圖表,例如:

Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./pdepend --overview-pyramid=result.svg ~/Dropbox/Shared/b2c/src/class/GLF
PHP_Depend @package_version@ by Manuel Pichler

Parsing source files:
..........                                                      10

Executing Coupling-Analyzer:
...                                                             68

Executing CyclomaticComplexity-Analyzer:
...                                                             64

Executing Inheritance-Analyzer:
                                                                18

Executing NodeCount-Analyzer:
..                                                              44

Executing NodeLoc-Analyzer:
..                                                              54

Generating pdepend log files, this may take a moment.

Time: 00:00; Memory: 11.50Mb

這樣就會把一些概要的品質量測數據圖以svg的格式輸出:

等等。

如果想直接抓出一些程式碼的缺陷,而不只是看到冷冰冰的數據....還有一些不錯的工具,例如PHP MESS Detector。他也可以透過Composer來安裝:

{
    "require":{
    },
    "require-dev": {
        "phpunit/phpunit":"~3.7.5",
        "phpunit/php-invoker":"~1.1.0",
        "phpunit/phpunit-selenium":"~1.3.2",
        "pdepend/pdepend":"~1.1",
        "phpmd/phpmd":"~1.5"
    }
}

同樣透過composer update安裝好以後,把它link到方便執行的地方:

> ln -s vendor/phpmd/phpmd/src/bin/phpmd

然後就可以透過./phpmd來執行。他需要用三個參數:

  1. 目錄或檔案,以逗號分隔
  2. 報告格式,可以使用的格式有:xml, txt, html
  3. 指定要檢測的規則集合,包含:cleancode, codesize, controversial, design, naming, unusedcode

執行後,結果會從stdout輸出,所以可以把它重導到檔案。例如想要輸出成html格式,指定用codesize規則集合,可以這樣執行:

Feng-Hsu-Pingteki-MacBook-Air:2-3a fillano$ ./phpmd ~/Dropbox/Shared/b2c/src/class/GLF html codesize > phpmd.html

然後可以用瀏覽器檢視輸出的結果:

指出的問題,也是一個超連結,指向phpmd文件中的說明:

例如在一個方法中,可能的執行路徑超過200,就會被指出有問題。這通常是程式邏輯比較複雜,容易發生錯誤,所以最好拆開或想辦法降低複雜度。

跟pdepend比較起來,phpmd更容易上手,而且他的說明很直接,如果對於這些品質量測不是那麼熟悉,phpmd應該會比較好用。

=====

除了這兩個工具,還有像是php code_sniffer可以找出程式碼違背coding standard的問題。php copy/paste detector可以檢查出程式碼中是否有使用copy/paste的地方,通常有這樣的問題,需要把重複的程式碼做成共用的函數或方法。通常更進一步改善的方式是做重構,不過這會需要花一些時間學習,而且最好要熟悉設計模式才容易下手執行就是了XD


上一篇
逐步提昇PHP技術能力 - 開發工具 : 使用Selenium進行整合測試
下一篇
逐步提昇PHP技術能力 - 開發工具 : 使用phing來讓專案建置過程自動化
系列文
逐步提昇PHP技術能力30

1 則留言

0
fillano
iT邦超人 1 級 ‧ 2013-10-17 20:40:51

偷偷測試一下...

&lt;pre class="c" name="code">
&lt;span style="color: green;">test&lt;/span>

我要留言

立即登入留言