技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Checkstyle の Metrics 近辺の内容を日本語で分かり易く

checkstyle.sourceforge.net

個人的にチェックスタイルでもっとも素晴らしいチェックの項目群だと思うのだけど、これで引っかかると、意味が理解できなくて直すの止める人とか、「チェックが開発の邪魔だ」とか言ってくる人が多いので、なるだけ分かり易くメモしておく。

BooleanExpressionComplexity

要するに && とか || を繋げすぎた条件式なんてバグるんだから書くんじゃないというチェック。
この数値は、条件結合数( ||&& の数 )で単純増加する。

個人的にここの 3 位が好み。
人間の脳みそは 同時に 5 個位しか処理できない そうですよ。

パラメータ

名称 意味 初期値
max 最大で許容する複雑度の数字 3
tokens チェックする演算子 && & || | ^

ClassDataAbstractionCoupling

中で使用(new とか)しているクラス数チェック。

何より、論理クラスをたくさん import しておいて、見通しが効くのかって問題がある。
これで何がわかるかというと、クラス保守のしやすさ(当たり前だけど、たくさん依存してるクラスなんてテスト書けないぞ)。
もっというと、数字が大きい=そのクラス色々やりすぎてないか?設計粒度おかしくない?って話

パラメータ

名称 意味 初期値
max 最大で許容するクラス数 7
excludedClasses チェック対象外クラス(こいつらは論理ロジックではないので、無視する) HashMap, ArrayList, String, float, TreeSet, List, Boolean, Void, Override, Short, IllegalArgumentException, UnsupportedOperationException, HashSet, void, Character, IndexOutOfBoundsException, byte, double, Double, LinkedList, Float, Byte, SortedMap, Long, Throwable, Object, Class, Map, IllegalStateException, Set, StringBuilder, SuppressWarnings, SortedSet, long, RuntimeException, Deprecated, NullPointerException, Queue, SecurityException, FunctionalInterface, TreeMap, Deque, int, Exception, Integer, SafeVarargs, StringBuffer, boolean, char, short, ArrayIndexOutOfBoundsException
excludeClassesRegexps チェック対象外クラスの正規表現。Voクラスなんかの設定をしておくと吉 ^$
excludedPackages チェック対象外パッケージ。ユーティリティパッケージでも指定しておくと吉 {}

ClassFanOutComplexity

参照しているクラス数。

ClassDataAbstractionCoupling に似ているが、こっちはファイル単位で参照してるクラス数のカウント。
あくまで参照のカウントなので、中でインスタンス化してるかは問題ではなくて、メソッドの返り値を使ったとかそういうレベルでもカウントされる。

ClassDataAbstractionCoupling に比べると数字が上がり易くなる傾向はあるが、この値が大きいということは、把握すべきクラス数が多いことを意味してる。
あんまし大きいと、テストコードが書きにくくなる。

個人的にもこれはデフォルトくらいでよい

パラメータ

名称 意味 初期値
max 最大で許容するクラス数 20
excludedClasses チェック対象外クラス(こいつらは論理ロジックではないので、無視する) HashMap, ArrayList, String, float, TreeSet, List, Boolean, Void, Override, Short, IllegalArgumentException, UnsupportedOperationException, HashSet, void, Character, IndexOutOfBoundsException, byte, double, Double, LinkedList, Float, Byte, SortedMap, Long, Throwable, Object, Class, Map, IllegalStateException, Set, StringBuilder, SuppressWarnings, SortedSet, long, RuntimeException, Deprecated, NullPointerException, Queue, SecurityException, FunctionalInterface, TreeMap, Deque, int, Exception, Integer, SafeVarargs, StringBuffer, boolean, char, short, ArrayIndexOutOfBoundsException
excludeClassesRegexps チェック対象外クラスの正規表現。Voクラスなんかの設定をしておくと吉 ^$
excludedPackages チェック対象外パッケージ。ユーティリティパッケージでも指定しておくと吉 {}

CyclomaticComplexity

循環的複雑度とよく言われる。

10 超えたら、汚すぎて読めないっていって、レビュー突っ返していいレベル(だと個人的に思ってる)。
関数型プログラミングやってる連中だと、これで 5 行くとか、よほどの理由があるかさもなくばバカかと思われる。

if とか while とかを使うことで発生する、処理分岐数の概算値。
具体的には boolean 式 1 個単位でカウントしてる

公式曰く「テストコードを書く前提なら、1-4 に抑えたい。5-7 ならかろうじてテストできるんじゃない?8-10 も行ったらリファクタを検討すべき。」

著作権法はプログラムにするとバグりやすい って話の中で、ドワンゴ CTO の人が、以下のように言及してる。

循環的複雑度が75を超えるとバグの混入確率は98%、「いかなる変更も誤修正を生む」状態になる

個人的見解なら 5 超えたらテストコード書きたくない時点でクソコードだと断じたい。

パラメータ

名称 意味 初期値
max 最大許容する分岐数 10
switchBlockAsSingleDecisionPoint switch 分岐はcase含めて 1 とカウントするか?(false では case ごとにカウント) false
tokens チェック項目 while do for if switch case catch ?(三項演算子) && ||

JavaNCSS

コメント化されてないソースのステートメント(処理)数カウンタ。

公式曰く:

理論的根拠:大きすぎるメソッドやクラスは読みにくく、維持するのに費用がかかります。 NCSSの数値が大きいということは、メソッドやクラスが、より小さな単位に分解されるべき責任や機能を多すぎることを意味します。

個人的には methodMaximum = 20, classMaximum = 500 位の設定がテストしやすいのでオススメ。
関数型言語やってる人なら多分この位でいけるはず。

パラメータ

名称 意味 初期値
methodMaximum 1メソッドあたりの最大ステートメント 50
classMaximum 1クラスあたりの最大ステートメント 1500
fileMaximum 1 ファイルあたりのステートメント 2000

NPathComplexity

Cyclomatic complexity(循環的複雑度)に近しい計算。
ただし、こちらの数字はネストすると単純カウントではなくて、条件分岐なら条件式の複雑性、三項演算は +2 補正とか、もう少し厳密に計算されれる。

1988年のAT&Tベル研究所でのいくつかの情報源の経験的な数ベース

ただ、「やりすぎてロジックの明瞭性を損なうなよ」とは checkstyle 公式の言。
個人的には 100 は超えたくない。

名称 意味 初期値
max NPathの最大許容値 200

ということで、主要なものの説明。