はじめに
一つのクラスへ処理を追加し続けると、注文登録、メール送信、売上集計、請求書作成など、目的の異なる処理が混在することがあります。
すべて注文に関係する処理であっても、役割や変更される理由が異なれば、クラスの目的は分かりにくくなります。
このようなクラスやモジュール内部のまとまりを評価する考え方が、凝集度です。
この記事で分かること
- 凝集度とは何か
- 高い凝集度と低い凝集度の違い
- 凝集度が設計へ与える影響
- 凝集度を判断する方法
- 凝集度を高める際の注意点
凝集度とは
凝集度とは、一つのクラスやモジュールに含まれる処理やデータが、共通する目的にどれだけまとまっているかを表す考え方です。一つの目的を実現するために、関係する処理やデータが集まっている状態は、凝集度が高いといえます。
反対に、異なる目的を持つ処理が一か所へ集められている状態は、凝集度が低いといえます。凝集度は、クラスの大きさや処理数だけでは判断できません。複数の処理があっても、一つの目的を実現するために必要な処理であれば、まとまりのある設計です。
高い凝集度と低い凝集度の違い
| 観点 | 高い凝集度 | 低い凝集度 |
|---|---|---|
| 目的 | 一つの目的にまとまっている | 複数の目的が混在している |
| 変更理由 | 同じ理由で変更されやすい | 異なる理由で変更される |
| データ | 関連するデータを扱う | 処理ごとに異なるデータを扱う |
| 理解 | 役割を説明しやすい | 役割を説明しにくい |
| 変更影響 | 対象を限定しやすい | 無関係な処理へ影響しやすい |
| テスト | 確認する目的が明確 | 複数の目的が混在する |
凝集度の高いクラスは、「何を担当するクラスか」を具体的に説明できます。
凝集度の低いクラスは、「注文に関する処理」「利用者を管理する処理」のように、広い言葉でしか説明できない傾向があります。
凝集度が高いと何が良いのか
役割を理解しやすくなる
一つの目的に関係する処理がまとまっていれば、クラス名やモジュール名から役割を把握しやすくなります。修正する場所を探す場合も、どこに対象の処理があるか判断しやすくなります。
変更の影響を限定しやすくなる
関連する処理がまとまっていれば、仕様変更の対象を追いやすくなります。異なる目的の処理が混在していると、一つの機能を変更するだけでも、関係のない処理を壊していないか確認しなければなりません。
テスト対象を整理しやすくなる
役割が明確であれば、そのクラスが何を正しく行えばよいか判断できます。入力と結果の関係が一つの目的に沿っているため、テストする範囲も明確になります。
注文処理で凝集度を考える例
例えば、OrderManagerというクラスが、次の処理を呼び出して調整するだけでなく、それぞれの詳細な処理まで内部に持っているとします。
- 注文を登録する
- 在庫を更新する
- 注文完了メールを送信する
- 月次売上を集計する
- 請求書を作成する
これらはすべて注文に関係しています。
しかし、在庫管理のルール、メールの文面、集計条件、請求書の形式は、それぞれ異なる理由で変更されます。複数の処理を順番に呼び出す調整役であること自体は、凝集度が低いとは限りません。
問題は、在庫、通知、集計、請求という異なる目的の詳細まで、同じクラスが担当していることです。目的ごとに整理すると、次のようになります。
| 設計単位 | 主な目的 |
| 注文処理 | 注文の登録と状態変更を管理する |
| 在庫管理 | 在庫の引当てと戻入れを管理する |
| 通知処理 | 注文結果を利用者へ通知する |
| 売上集計 | 注文データから売上を集計する |
| 請求処理 | 請求内容と請求書を作成する |
分割の目的は、クラス数を増やすことではありません。
異なる目的を分け、それぞれが何を担当するのか明確にすることです。
クラスの責務が曖昧になる背景については、責務が曖昧なクラスはなぜ生まれるのかで説明しています。
凝集度を判断する四つの問い
目的を一文で説明できるか
「このクラスは何をするものか」を、具体的な一文で説明できるか確認します。
「さまざまな処理を管理する」のような説明しかできない場合は、複数の目的が混在している可能性があります。
含まれる処理は同じ目的に関係しているか
処理同士が、一つの目的を実現するために協調しているか確認します。同じ業務分野に関係しているだけでは、十分なまとまりとはいえません。
同じデータや状態を扱っているか
クラス内の処理が、共通するデータや状態を利用しているか確認します。一部の処理でしか使用しないデータが増えている場合は、別の役割が混ざっている可能性があります。
同じ理由で変更されるか
一つの仕様変更によって、クラス内の処理が一緒に変更されるか確認します。異なる理由で個別に変更される処理が混在している場合は、分割を検討します。「同じ理由で変更されるか」は、凝集度を判断するための実務的な目安です。
変更理由を基準に、処理をまとめるか分けるか判断する考え方は、共通化とは?「とりあえず共通化」が設計を壊す理由を解説で詳しく説明しています。
ただし、四つすべてを満たすことを、機械的な合格条件とするものではありません。クラスの目的を中心に、扱うデータや変更理由を補助的な手掛かりとして判断します。
凝集度の代表的な分類
凝集度には、まとまり方による分類があります。
| 種類 | まとまり方 | 凝集度 |
| 機能的凝集 | 一つの明確な機能を実現する | 高い |
| 逐次的凝集 | 前の処理結果を次の処理が利用する | 比較的高い |
| 通信的凝集 | 同じデータを扱う処理が集まる | 比較的高い |
| 手続的凝集 | 同じ手順で実行する処理が集まる | 中程度 |
| 時間的凝集 | 同じ時期に実行する処理が集まる | 低い |
| 論理的凝集 | 似た処理を条件分岐で切り替える | 低い |
| 偶発的凝集 | 関係のない処理が集まる | 最も低い |
分類名を暗記することが目的ではありません。
何を基準に処理が集められているかを確認し、一つの明確な目的へ近いほど凝集度が高いと理解することが重要です。
凝集度は高ければ高いほどよいのか
凝集度を高めることは重要ですが、クラスを細かく分ければよいわけではありません。処理を一つずつ別のクラスへ分けると、単純な機能を実現するために多くのクラスを呼び出す必要があり、依存関係が複雑になることがあります。
分割するときは、処理数ではなく、目的や変更理由の違いを基準にします。内部は一つの目的にまとめ、外部との依存は必要以上に増やさないことが重要です。クラスやモジュール同士の依存の強さは、結合度という考え方で評価します。
まとめ
凝集度とは、クラスやモジュール内部の処理やデータが、共通する目的にどれだけまとまっているかを表す考え方です。一つの目的を実現する処理がまとまっているほど、凝集度は高いと判断できます。凝集度が高い設計は、役割を理解しやすく、変更の影響を限定しやすく、テストする範囲も明確になります。
ただし、クラスを小さくすること自体が目的ではありません。目的や変更理由の違いを見極め、意味のある単位へまとめることが重要です。

コメント