こんにちは、リサーチパネルの佐々木です。
今回は循環的複雑度(Cyclomatic Complexity)を使って、レガシーコードの変遷を追ってみようと思っています。というのも、リサーチパネルで動いているコードはVGの中では古い方(所謂レガシーコードってやつ)で、日々そんなコードと格闘しています。
今回は循環的複雑度(Cyclomatic Complexity)を使って、レガシーコードの変遷を追ってみようと思っています。というのも、リサーチパネルで動いているコードはVGの中では古い方(所謂レガシーコードってやつ)で、日々そんなコードと格闘しています。
そこで何か良いものがないかと思ったところで、循環的複雑度(Cyclomatic Complexity)って測定で計ってみようかと思い、あるプロジェクト(社内システム)の過去コードをほじくり返して、その辺を数値を今回計ってみます。(たぶん、どんどん複雑度が増しているんだろうなと思いつつ...)
ソースコードの一部の循環的複雑度は、ソースコード内の線形独立な経路の数である。実際、if文やfor文のような分岐点のないソースコードの場合、その複雑度は 1 であり、そのコードには1つの経路しかない。コードに1つのif文が含まれていれば、コードには2つの経路があることになる。つまり、一方はif文での条件が真となる場合の経路で、もう一方はそれが偽となる場合の経路である。
循環的複雑度 - Wikipedia
ちなみに対象プロジェクトは PHP で書いているので、計測にはphpmd (PHP Mess Detector)を使ってみようと思います(単に使ってみたかった...)。phpmdは、潜在的なバグになりそうなコードを洗い出してくれるツールで、巨大なメソッドや未使用な変数を指摘してくれます。
ということで、今回のその中の循環的複雑度(それ以外も出すことできますが)を出してみたいと思います。なお、数値のレベルとしては、phpmd では以下のようになっています。
循環的複雑度(CC) | 状態 |
---|---|
1-4 | 複雑度が低 |
5-7 | 複雑度が中程度 |
8-10 | 複雑度が高 |
11- | 複雑度がとても高い |
他にも、以下のような考え方もあるので、その辺の数値も使って分類してみたいと思います。(11辺りから少しずつ気を付けた良さそうですね。)
循環的複雑度(CC) | 状態 |
---|---|
1-10 | シンプルなプログラム。リスク小 |
11-20 | やや複雑なプログラム。リスク中 |
21-50 | 複雑なプログラム。リスク大 |
51- | テスト不可能なプログラム。リスク特大 |
ただ、デフォルトだと10以上を閾値として結果を出すため、問題のないレベルも出力するようにruleset.xmlを作成し、phpmdの実行結果を集計してみました。(phpmdの詳しい使い方は他に譲ります)
- ruleset.xml
<!--?xml version="1.0"?--> <ruleset xsi:nonamespaceschemalocation=" http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:schemalocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://pmd.sf.net/ruleset/1.0.0" name="sample PHPMD rule set"> <rule ref="rulesets/codesize.xml/CyclomaticComplexity"> <properties> <property value="1" name="reportLevel"> </property></properties> </rule> </ruleset>
- 実行コマンド
phpmd <対象プロジェクトディレクトリ> text ruleset.xml
結果は...
徐々に複雑度の高いプログラムが増えてきているようですね。あと、複雑なものはそのまま残り続けているようです。自分が対象プロジェクトの改修を進めようとする際、どうしても複雑なプログラムは触りたくないし、修正する時も継ぎ接ぎ的な改修になっていた気がします。
こういった複雑なコードは、意識的にリファクタリングをかけていかないと、恐らく残り続けてしまうので、その辺りを改善するには、
- テストコードを書く
- 複雑なコードの場合は経路が増えテスト自体が書きづらくなるので、テストをしやすくしようとするとシンプルになっていく。
- 定常的にチェックする仕組みを作る
- 「リリース前のコードレビューする」や「CIなどで日々計測・警告をする」といった仕組み作ることで、早めに複雑なコードを除いていく。
といったところでしょうか。これらの対応が良いか検証まではできてないのですが、VG全体としてはこういった流れは強くなっていると感じています(きっと)。
今回phpmdを使って計りましたが、これはコードのある一側面を計測したものですし、全てのプロジェクトで同じ状態になるわけではないでしょうが、コードの質を保つ一指標として見ても良いのかと思っています。
今回phpmdを使って計りましたが、これはコードのある一側面を計測したものですし、全てのプロジェクトで同じ状態になるわけではないでしょうが、コードの質を保つ一指標として見ても良いのかと思っています。
今後もレガシーコードと戯れつつ、モダンなコードへの変遷をどこかで報告できればと思っています!