前回Metrics.exe を使って実際にメトリックスを実施してみました。
今回はメトリックスの結果についての解説です。

Explanation

生成されたメトリックスの結果は下記のような XMLファイル でした。
生成元のコードについては、前回の記事を参照してください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?xml version="1.0" encoding="utf-8"?>
<CodeMetricsReport Version="10.0">
<Targets>
<Target Name="C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\CodeMetricsTest.exe">
<Modules>
<Module Name="CodeMetricsTest.exe" AssemblyVersion="1.0.0.0" FileVersion="1.0.0.0">
<Metrics>
<Metric Name="MaintainabilityIndex" Value="100" />
<Metric Name="CyclomaticComplexity" Value="2" />
<Metric Name="ClassCoupling" Value="0" />
<Metric Name="DepthOfInheritance" Value="1" />
<Metric Name="LinesOfCode" Value="1" />
</Metrics>
<Namespaces>
<Namespace Name="CodeMetricsTest">
<Metrics>
<Metric Name="MaintainabilityIndex" Value="100" />
<Metric Name="CyclomaticComplexity" Value="2" />
<Metric Name="ClassCoupling" Value="0" />
<Metric Name="DepthOfInheritance" Value="1" />
<Metric Name="LinesOfCode" Value="1" />
</Metrics>
<Types>
<Type Name="Program">
<Metrics>
<Metric Name="MaintainabilityIndex" Value="100" />
<Metric Name="CyclomaticComplexity" Value="2" />
<Metric Name="ClassCoupling" Value="0" />
<Metric Name="DepthOfInheritance" Value="1" />
<Metric Name="LinesOfCode" Value="1" />
</Metrics>
<Members>
<Member Name="Main(string[]) : void" File="D:\Software\Project\Source Code\Blog\BlogSamples\CodeMetricsTest\Program.cs" Line="11">
<Metrics>
<Metric Name="MaintainabilityIndex" Value="100" />
<Metric Name="CyclomaticComplexity" Value="1" />
<Metric Name="ClassCoupling" Value="0" />
<Metric Name="LinesOfCode" Value="0" />
</Metrics>
</Member>
<Member Name="Program()">
<Metrics>
<Metric Name="MaintainabilityIndex" Value="100" />
<Metric Name="CyclomaticComplexity" Value="1" />
<Metric Name="ClassCoupling" Value="0" />
<Metric Name="LinesOfCode" Value="1" />
</Metrics>
</Member>
</Members>
</Type>
</Types>
</Namespace>
</Namespaces>
</Module>
</Modules>
</Target>
</Targets>
</CodeMetricsReport>

ファイルを眺めていると

  • MaintainabilityIndex
  • CyclomaticComplexity
  • ClassCoupling
  • DepthOfInheritance
  • LinesOfCode

という単語が頻出しています。
Microsoftによれば、

  • MaintainabilityIndex -> 保守容易性指数
  • CyclomaticComplexity -> サイクロマティック複雑度
  • ClassCoupling -> クラス結合度
  • DepthOfInheritance -> 継承の深さ
  • LinesOfCode -> コード行

であると定義しています。
また、MSDNコード メトリックス値というページでは、上述の語を下記のように定義しています。

保守容易性指数 - コードの相対的な保守容易性を表す、0 ~ 100 のインデックス値を算出します。
値が大きいほど、保守容易性が優れていることを示します。
色分けしたコード評価を使用して、コード内の問題部分をすばやく識別することができます。
緑色の評価は 20 ~ 100 の範囲にあることを示し、コードの保守容易性が良好であることを示します。
黄色の評価は 10 ~ 19 の範囲にあることを示し、コードの保守容易性が中程度であることを示します。
赤の評価は 0 ~ 9 の範囲にあることを示し、保守容易性が低いことを示します。
サイクロマティック複雑度 - コードの構造上の複雑さを測定します。
これは、プログラムのフローにある、異なるコード パスの数を計算することで作成されます。
複雑な制御フローが含まれるプログラムでは、十分なコード カバレッジを実現するためにより多くのテストが必要となり、保守性が低下します。
メモ 場合によっては、Visual Studio 2010 のメソッドのサイクロマティック複雑度の計算が旧バージョンと異なります。
詳細については、「コード メトリックに関する問題のトラブルシューティング」で Visual Studio 2010 のコードの複雑度の計算における変更点についての説明を参照してください。
継承の深さ - クラス階層構造のルートまでのクラス定義の数を示します。
階層構造が深くなるにつれて、特定のメソッドおよびフィールドが定義または再定義されている場所を把握することがより困難になる場合があります。
クラス結合度 - パラメーター、ローカル変数、戻り値の型、メソッド呼び出し、ジェネリックまたはテンプレートのインスタンス化、基本クラス、インターフェイス実装、外部の型で定義されたフィールド、および属性による装飾を使用して、一意のクラスへの結合度を測定します。
適切なソフトウェア デザインでは、型およびメソッドの連携は高まり、結合性は低くなります。
結合性が高いということは、他の型への依存関係が多いために再利用や保守が困難なデザインであることを示します。
コード行 - コード内の行の概数を示します。
この数は IL コードに基づいているため、ソース コード ファイル内の正確な行数ではありません。
数が非常に大きい場合、型またはメソッドでの処理が多すぎるため、分割が必要であることを示すことがあります。
また、型やメソッドの保守が困難なことを示す場合もあります。

Conclusion

これらを踏まえて、サンプルである CodeMetricsTest.exe の結果を表に纏めてみました。

メトリックス項目 CodeMetricsTest.exe CodeMetricsTest Program Main(string[]) : void Program()
MaintainabilityIndex
(保守容易性指数)
100 100 100 100 100
CyclomaticComplexity
(サイクロマティック複雑度)
2 2 2 1 1
ClassCoupling
(クラス結合度)
0 0 0 0 0
DepthOfInheritance
(継承の深さ)
1 1 1 - -
LinesOfCode
(コード行)
1 1 1 0 1

極めてシンプルなコードのため結果も極めて良好です(当たり前) 結果を表に纏めるといろいろ見えてきます。

  • メトリックスの対象は、アセンブリ名前空間型のメンバという4つの単位で計測される
  • 型のメンバには「継承の深さ」のメトリックスが含まれない
  • サイクロマティック複雑度コード行等は、上位の単位は下位単位を内包した結果になっている
  • コード行はIL (Intermediate Language) を元にしているからソースと一致しない (Programコンストラクタに1行追加されている)

各メトリックス値を更にブレイクダウンする必要があるようです。
というわけで次回は 保守容易性指数 について、ソースコードを交えながら説明します。