背景
JavaScriptコードのメトリクス測定がしたい。
JSでコードメトリクスといえば、Platoという優秀なビジュアライズツールがある。
しかし、それすら見に行かなくてもいいようにしたい。
具体的には、複雑度が閾値を超えるコードがpushされてきたら、CIが警告してくれるようにしたい。
使用するパッケージ
complexity-report
complexity-reportとは
CLIで複雑度計測。オプションで閾値チェックが可能。
インストール
npm install complexity-report --save-dev
実行
node ./node_modules/complexity-report/src/index.js <JSディレクトリまでのパス>
Platoとの併用
結論から言うと問題ない。
レポート生成と閾値チェックは異なるパッケージを用いることになってしまう。
とはいえ、Platoとcomplexity-reportはどちらも複雑度の計算にexcomplexというモジュールを利用しており、結果の整合性は問題ないはず。
依存関係をざっくり描くと以下の通り。
バージョンは以下のようになっている。
$ npm list --depth=0
...
├── complexity-report@2.0.0-alpha
...
├── plato@1.7.0
...
監視する複雑度
Cyclomatic Complexity(循環的複雑度)
概要
if, forなど条件分岐がどれだけあるかによって計算される
参考リンク
下限
0
上限
なし
閾値
Maintainability Index
参考リンク
下限
0
上限
100
※ただし、この値はマイクロソフトが0から100に正規化した計算式を利用した場合のレンジであり、元の計算式はマイナス無限大から171までの数値で表される。
※Platoは正規化した式でMaintainabilityを算出している。complexity-reportはどちらの式を使用するかオプションで選択できる。
概要
保守性。
SLOC(ステップ数)、Cyclomatic Complexity、Halstead Volume(後述)から算出される総合的な保守性。
Visual Studioではこれを利用して保守性を判断してくれる。その際の基準値は以下の通り。
あるいは http://www.ecs.csun.edu/~rlingard/comp589/ColemanPaper.pdf の論文では38〜49(原著では正規化前の値で65から85)となっている。
閾値
ファイル毎に50を超えないようにした。
監視しなかった複雑度
Halstead Difficulty
参考リンク
下限
0
上限
なし
概要
難易度。
学習コストや実装コストの観点から算出される値。演算子や変数の種類と総数から計算される。
いくつ以上が何というものではなく、閾値の基準設定が難しかったので採用を見送った。
実際使用しているコマンド
$ node ./node_modules/complexity-report/src/index.js -n -C 10 -M 50 <JSディレクトリまでのパス>
オプションの説明
-n, --newmi use the Microsoft-variant maintainability index (scale of 0 to 100)
-M, --minmi <maintainability index> specify the per-module maintainability index threshold
-C, --maxcyc <cyclomatic complexity> specify the per-function cyclomatic complexity threshold
Platoはnewmiを使っているので、数値を合わせたい場合はnオプションが必要。
CI連携
今回の目的。
コードは省略。
CircleCIで上記のコマンドを叩いてやれば、閾値判定でジョブを成功させたり失敗させたりできる。
実際の運用
- push時にCIのコンテナが上記のコマンドを叩く
- 成功/失敗の判定をSlackやGitHubに通知
- 失敗したら成功するようにリファクタリングする
まとめ
JSコードメトリクスの閾値チェック
- complexity-reportのインストール
- CIジョブ追加: push時に実行
- 失敗条件: Cyclomatic Complexityが11を超える関数またはMaintainability Indexが50を下回るファイルが検出された場合
JSのコードメトリクスのビジュアライズ
- Platoを使用
- CIジョブ追加: masterマージ時にレポートを生成
今回は、ES5コードで使用しているけれど、全く同じ手順でES6でも使用できるはず。