凝集度(Cohesion)

2024/09/30に公開

こんにちは、沙代です。
綺麗な構造のプログラムを書きたいなと思った時、ありますよね。綺麗ってなんだろう
今日は初めて凝集度という言葉を学んだので、それを自分なりにまとめてみようと思います。


今回参考にさせていただいた本
ソフトウェアアーキテクチャの基礎 エンジニアリングに基づく体系的アプローチ

凝集度

凝集度(Cohesion)とは、モジュールの要素がどの程度そのモジュールに収まっているかの度合いを指す。言い換えれば、凝集度とはモジュール内の要素同士の関連度を示す指標だ。[1]

モジュールという袋があって、その中や外に要素があるイメージでしょうか。もう少し読み進めてみます。

関連する要素がすべて一箇所にまとまっている状態が、凝集したモジュールの理想だ。まとまりをそれよりも細かくしてしまうと、モジュール間の呼び出しによって要素を結合しないと、有益な結果が得られなくなってしまうからだ。[1]

なるほど。どこまでをモジュールの一区切りにするかを判断するにあたって、凝集度は良い判断材料になりそうですね。
あまりまだよく分からないですが、結合度の概念の反対みたいな気もします。
モジュール間の呼び出しがいっぱいあるとデバッグやマネジメントが大変そうですものね。

凝集度の観点からの分類

本文中には、7つの凝集度の分類が挙げられていますが、ちょっと長くなってしまいそうなので、今回は触れずにおきます。

LCOM (Lack of Cohesion Methods)

LCOM (Lack of Cohesion Methods, メソッドの凝集度の欠如)は、モジュールの構造的な凝集度を計測するメトリクスだ。[1]

調べてみると、LCOMにはLCOM1~LCOM4の4世代がありそうです。

ここでは、LCOM1を見てみようと思います。

特定のフィールドにアクセスしていないメソッドがあればPが1つ増え、逆にアクセスしているメソッドがあればQが1つ減るとのこと。
LCOM1の値が高いほど、クラス内のメソッドがあまり共有フィールドを使用しておらず、クラスの責任が分散していることを意味します。すると、クラスが多くの異なる機能を持つため、動作の予期やテストが難しくなるので、クラスをよりシンプルで明確な責任を持つ複数のクラスに分割することが勧められるということでしょうか。

\text{LCOM}_1 = \begin{cases} P - Q & \text{if } P > Q \\ 0 & \text{otherwise} \end{cases} \text{ここで、} \begin{align*} P &= \text{共有フィールドを持たないメソッドペアの数} \\ Q &= \text{共有フィールドを持つメソッドペアの数} \end{align*}





Pythonでちょっと考えてみたいと思います。

example1
class Hello:
    name = "taro"
    age = "18"
    def hello(self):
        print(self.name)
    def introduce(self):
        print("{0.name}({0.age})".format(self))
    def set_age(self, age):
        self.age = age

メソッドが3つなので、メソッドペア(P+Q)は{}_3 C_2=3ですね。

  • hello-introduce 共有フィールド(name)
  • hello-set_age 共有フィールドなし
  • introduce-set_age 共有フィールド(age)

従って、P=1, Q=2であり、P<Qなので、LCOM1はゼロになります。

example2
class Hello:
    name = "taro"
    age = "18"
    def hello(self):
        print(self.name)
    def introduce(self):
        print("{0.name})".format(self))
    def set_age(self, age=None, name=None):
        self.age = age

introduce.ageを使わないように変更してみました。
.name, .ageを使うメソッドが2群に綺麗に分割されてしまいました。

今回は、P=2, Q=1であり、LCOM1は、P-Q=1となります。
凝集度が低い(Lack of Cohesion in Methodsが高い)ので、まだ改善の余地がある可能性があるということになります。

(LCOM2以降は省略します)

留意点

しかし、上記の例でもさらにHelloを分割していくかというと、少し躊躇うことがあるかもしれません。

このメトリクスが見つけられるのは、構造的な凝集度の欠如だけだ。LCOMは要素が適切に組み合っているかどうかを論理的に判断する方法を持っていない。「なぜ」の方が「どうやって」よりもずっと大事だという、ソフトウェアアーキテクチャの第二法則に照らしてみると、この点はLCOMの欠陥と言える。[1]

ソフトウェアの第二法則は、以下

「どうやって」よりも「なぜ」の方がずっと重要だ。 ソフトウェアアーキテクチャの第二法則[1]

トレードオフを常に意識することが重要そうです。

参考にさせていただいた本、ページ

[1] 『ソフトウェアアーキテクチャの基礎 エンジニアリングに基づく体系的アプローチ
[2] https://www.aivosto.com/project/help/pm-oo-cohesion.html

Discussion