9. Using Software Metrics to Ensure Maintainability
プロジェクトガバナンスに利用できるソフトウェアメトリクス。コードの結合、アーキテクチャの侵食、コードの複雑さ、設計品質などを評価するためのメトリクス。
9.1 The Case for Using Metrics
メトリクスの最も良い活かし方は、メトリクスベースのフィードバックループを運用すること。これによって常に品質基準を満たしている状態にできる。
システムの初期の段階からからこれに取り組んでいなかった場合は、達成可能なゴールから始める。そして徐々にゴールの基準を上げていく。
エントロピー(構造侵食)は最終的に「巨大な泥団子」や循環依存を増やすことにつながる。
循環依存関係があると、コードの一部を切り離してテストをすることが困難になる。
循環依存関係解消のためには、コードの依存関係を分析するためのメトリクスを使用する。「最も大きな循環グループの要素数」のしきい値を決めてアラートする。そこから、依存性逆転の原則 (SOLID原則のD: Dependency inversion principle)に従い、プログラムの重要な部分が重要でない部分に依存しないように設計する。
Sonargraph-Explorer はそのための有用なツール。
9.2 Why Are Metrics Not More Widely Used?
メトリクスベースのフィードバックループがほとんど使われない理由
- メトリクスやその使い方をよく理解していない。
- メトリクスを収集するツールがあまり知られていない。言語サポートが限られている。
- コンテキストの理解と一定のレベルの専門知識がなく、正しいメトリクスを選ぶことができない。
- 技術的負債に苦しんでいて、このような改善プロセスに時間が避けない。
- メトリクスベースのルールのの自動化が大変。
9.3 Tools to Gather Metrics
メトリクスを収集するための無料ツール。
- 一部言語は無料。商用版はより多くの機能が利用可能
- サイズと複雑さのメトリクスを提供
- Java, C#, Pythonは無料。商用版は変更履歴メトリクスとC/C++もサポート
- 結合度、循環、サイズ、複雑さのメトリクス
9.4 Useful Metrics
9.4.1 Metrics to Measure Coupling and Structural Erosion
結合と構造侵食を計測するメトリクス。
平均コンポーネント依存値 (Average Component Dependency: ACD) は、依存関係グラフからランダムに選択された要素が平均して直接または間接的に何個の要素に依存するか。システムがどれだけ密に結合しているかを把握できる。
伝搬コスト (Propagation Cost: PC)は、システムがどれだけ緊密に結合しているか。ACDをノード数で割ることで算出できる。ACDを正規化した値。
システムの規模が小さい場合 (n<500) はPCが高くてもあまり注意する必要はない。
システムが中規模 (500 ≤ n < 5,000) であれば、PCが20%以上なら注意が必要。50%以上なら深刻。
システムが大規模 (n ≥ 5,000) であれば、PCが10%でも注意する必要がある。
循環依存性を確認するのに特化したメトリクス
- 最大循環グループの要素数
- 最大循環グループのサイズ
- 相対的循環度 (Relative Cyclicity): システムが循環依存関係によってどの程度影響を受けているか。
構造負債指数 (Structual Debt Index: SDI): システムが循環依存関係を解消する困難さを表す指標。
保守性レベル (Maintainability Level: ML): コンポーネント構造やパッケージ・名前空間構造を考慮した依存関係の度合い。機能コンポーネントごとに分離されているかの判断に使われる。
9.4.2 Metrics to Measure Size and Complexity
サイズと複雑さを計測するメトリクス。コードの保守性を維持するために重要
LOC (Lines Of Code): 1ファイルあたりの行数。800LOC程度に抑えるのがおすすめ。
循環複雑度 (Cyclomatic Complexity): メソッドや関数を通過する実行経路の数。24を超えるとエラー率が急速に増えるので、15以下にするのがおすすめ。
インデントの数: 最大インデントレベルは4にするのがおすすめ。
9.4.3 Change History Metrics
変更履歴から得られるメトリクス。
変更頻度: 頻度が高いファイルは設計が不安定である可能性が高い。
コードチャーン: ある期間内に対象のファイルに行がどれだけ追加削除されたか。これも設計の不安定さを測ることができる。
著者数: ある期間内に何人が変更を加えたか。特定の人への知識の偏りの度合いを表す。
頻繁に変更される複雑なファイルは多くの依存関係を持ち構造侵食が生まれる可能性を秘めている。リファクタリングチャンス。
9.4.4 Other Useful Metrics
その他の役立つメトリクス。
コンポーネントランク: Googleのページランクのように依存関係から人気のクラスを見つける。新しくプロジェクトに参加し人はコンポーネントランクからコードを読み始めるのが良い。
LCOM (Lack of Cohesion of Methods): クラス内のすべてのフィールドとメソッドの依存関係グラフから算出。クラスが単一責任原則に違反していないかを把握する。
9.5 Architectural Fitness Functions
アーキテクチャ適応度関数には、3つの特性と保守性を優先させる。
保守性を計測するための適応度関数の例。
- 保守性レベルのしきい値を75%以上に設定する。
- 相対的循環度について、パッケージ/名前空間レベルでの閾値を0%とし、コンポーネントレベルの閾値を4%以下とする。
- コンポーネントの構造負債指数の閾値を150以下とする。
9.6 How to Track Metrics over Time
フィードバックループを作るためには自動化されたビルドで1日1回メトリクスを収集してツールに流し込むのが重要。
9.7 A Few Golden Rules for Better Software
より良いソフトウェアを作るための黄金律
- 強制力のあるアーキテクチャモデルを組織で持って、開発者はそれに沿ってシステムのアーキテクチャ設計をする。
- 名前空間・パッケージレベルでの循環的依存関係を避ける。
- ソースファイル・クラスレベルでの循環的依存関係を制限する。
- コードの重複を避ける。
- ソースファイルのサイズを800LOCに制限する。
- 最大インデントを4、修正循環複雑度15に制限する。