技術的負債を無くす具体的な施策～循環的複雑度を超お手軽に求める～

はじめに
===============================================
巷ではよく技術的負債について以下のような議論がなされます。

* 技術的負債を残さないためにどうすればよいか
* 技術的負債が起こす問題はなにか

けれど、結局、技術的負債は往々に残ってしまうものです。

技術的負債を残さないための施策の多くは、
「テストコードを書こう！」
「継続的にCIを回そう！」
「ソースコードの品質チェックを重点的にやろう！」
といったキャンペーンを行うことで解消しよういったものがほとんどで、
それらは開発者やレビュアの能力や時間に限りがあるためだと私は感じます。

そこで、本投稿では、
「技術的負債の対象になるソースを検知する。なおかつ超簡単に。」
という具体的な方法を紹介したいと思います。
ただ、あくまで参考指標という点はご留意願いたいと思います。


具体的な方法
==============================================
具体的な方法としてmaven-pmd-pluginでソースチェックを行い、その結果（循環的複雑度）をcsv出力してチェックします。

事前準備（MavenとJavaのインストール）
----------------------------------------------
最新版は以下（詳細は割愛）
以下は大体の方が実行環境をもっていると思うのため事前準備はほぼ不要な認識です。

* [Java](https://java.com/ja/download/)
* [Maven](http://maven.apache.org/download.cg)

手順①：pom.xmlを作成
----------------------------------------------
以下のファイルpom.xmlの名称で適当なディレクトリに保存
以下をコピペして文字コードはUTF-8で保存して下さい.

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>pmd.example</groupId>
	<artifactId>pmd-example</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<name>maven-pmd-plugin</name>

	<!-- 実行方法(コード解析):mvn pmd:pmd-->
	<!-- 実行方法(重複解析):mvn pmd:cpd-->
	<build>
		<!-- check target directory -->
		<sourceDirectory>checkSrc</sourceDirectory>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-pmd-plugin</artifactId>
				<version>3.5</version>
				<configuration>
					<!-- default pmd format xml -->
					<sourceEncoding>${src.encoding}</sourceEncoding>
					<targetDirectory>${outputDir}</targetDirectory>
					<format>${pmd.format}</format>
					<!--
						Rule Set list
						http://pmd.sourceforge.net/pmd-4.3.0/rules/index.html
						Rule Set setting XML
						http://grepcode.com/file/repo1.maven.org/maven2/net.sourceforge.pmd/pmd/5.0.1/rulesets/java/codesize.xml
					-->
					<rulesets>
						<!-- default Rule Set -->
						<!-- <ruleset>/rulesets/java/basic.xml</ruleset> -->
						<!-- <ruleset>/rulesets/java/unusedcode.xml</ruleset> -->
						<!-- <ruleset>/rulesets/java/imports.xml</ruleset> -->
						<!-- include rule Set -->
						<ruleset>/rulesets/java/codesize.xml</ruleset>
					</rulesets>
					<excludeRoots>
						<excludeRoot>**/test/**</excludeRoot>
						<excludeRoot>**/example/**</excludeRoot>
					</excludeRoots>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<reporting>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-pmd-plugin</artifactId>
				<version>3.5</version>
			</plugin>
		</plugins>
	</reporting>
	
	<properties>
		<src.encoding>UTF-8</src.encoding>
		<pmd.format>csv</pmd.format>
		<outputDir>${basedir}/target</outputDir>
	</properties>

</project>

```

手順②：チェック対象のソースをchecksrcディレクトリ配下にコピー
--------------------------------------
pom.xmlファイルを保存したディレクトリにcheckSrcというディレクトリを作成して、チェック対象のファイルを保存。
それで以下コマンドをpom.xmlファイルをカレントディレクトリにして実行

手順③：コマンド実行
-------------------------------------
```sh:コマンドプロンプト
mvn pmd:pmd
```

するとtarget配下に、pmd.csvファイルが作成されます。

結果
------------------------------------
pmd.csvは以下のように出力できます。
あとは、これをExcelでソースして分析するなり、DBに取り込んで解析すればヤバイソースを書く人の傾向なども見えてきます。
継続的にチェックするならタスク化してしまえば完了です。

| Problem |    Package     |                   File                   | Priority | Line |                                  Description                                  |  Rule set |             Rule             |
|---------|----------------|------------------------------------------|----------|------|-------------------------------------------------------------------------------|-----------|------------------------------|
|       1 | jp.co.hogehoge | C:\Project\test\pmd\checkSrc\Sample.java |        3 |   18 | The class 'Sample' has a Cyclomatic Complexity of 101 (Highest = 100).        | Code Size | CyclomaticComplexity         |
|       2 | jp.co.hogehoge | C:\Project\test\pmd\checkSrc\Sample.java |        3 |   18 | The class 'Sample' has a Modified Cyclomatic Complexity of 47 (Highest = 46). | Code Size | ModifiedCyclomaticComplexity |
|       3 | jp.co.hogehoge | C:\Project\test\pmd\checkSrc\Sample.java |        3 |   18 | The class 'Sample' has a Standard Cyclomatic Complexity of 47 (Highest = 46). | Code Size | StdCyclomaticComplexity      |
|       4 | jp.co.hogehoge | C:\Project\test\pmd\checkSrc\Sample.java |        3 |   24 | Avoid really long methods.                                                    | Code Size | ExcessiveMethodLength        |
|       5 | jp.co.hogehoge | C:\Project\test\pmd\checkSrc\Sample.java |        3 |   24 | The method 'checkInput' has a Cyclomatic Complexity of 100.                   | Code Size | CyclomaticComplexity         |


諸々の解説
==============================================================

循環的複雑度（CyclomaticComplexy）とは
-----------------------------------------------
端的にいえば、if文やfor文、whileやCASE文など分岐が発生する数+１です。
つまりは、それはテストケースが必要な数であり、
循環的複雑度の値に応じて、そのプログラムのバグ混入率は、下表のようになるとされています。

| 循環的複雑度 |        複雑さの状態        | バグ混入確率 |
|--------------|----------------------------|--------------|
| 10以下       | 非常に良い構造             | 25％         |
| 30以上       | 構造的なリスクあり         | 40％         |
| 50以上       | テスト不可能               | 70％         |
| 75以上       | いかなる変更も誤修正を生む | 98％         |

※因みに、注意として、上記のソースコードチェックでは循環的複雑度は10以上のものしか検知されません。
（デフォルト設定で、codesize.xmlを修正すれば変更できます。）

以下はPMDの公式HPの循環的複雑度の算出方法になります
＜http://pmd.sourceforge.net/pmd-4.3.0/rules/codesize.html#CyclomaticComplexity＞

```java:循環的複雑度野求め方(PMDのHPより抜粋)
// Cyclomatic Complexity = 12
public class Foo {
1   public void example()  {
2       if (a == b)  {
3           if (a1 == b1) {
                fiddle();
4           } else if a2 == b2) {
                fiddle();
            }  else {
                fiddle();
            }
5       } else if (c == d) {
6           while (c == d) {
                fiddle();
            }
7        } else if (e == f) {
8           for (int n = 0; n < h; n++) {
                fiddle();
            }
        } else{
            switch (z) {
9               case 1:
                    fiddle();
                    break;
10              case 2:
                    fiddle();
                    break;
11              case 3:
                    fiddle();
                    break;
12              default:
                    fiddle();
                    break;
            }
        }
    }
}
```


PMDを採用している理由
----------------------------------------------
他のソースチェックツールと違って、以下がお手軽な理由と感じています
例えば、大きな利点は以下です。

* ビルドが不要
* セットアップが簡単(Maven pluginなので、mavenがsourceを探してきてくれる)
* CSV出力できる(xml形式だとparseが面倒だが、それも不要)

コピペソースのチェックもできます
----------------------------------------------
コマンドを以下に変えれば、checkDir配下のソースのうちコピペソースのチェックもできます。

```:コマンドライン
mvn pmd:cpd
```
※因みにCPDとは、copy paste detectorのことです。


PMDを用いた循環的複雑度以外のソースチェック
----------------------------------------------
上記例は、循環的複雑度をルールセットにもつCode SizeというPMDのソースチェックを利用しましたが、他にも様々なソースチェックを行うことができます。
pom.xmlのrulesets部分を変更すれば、その他のソースチェックも実行できます。

* [PMDルールセット（日本語解説）](http://www.limy.org/program/java/pmd/)