凝集度について


# はじめに
**良い設計**をしていくにあたり「結合度」や「凝集度」といった基準があります。
プログラムを書くにあたり、必ず知っておくべき基本的な設計原則です。
今回はその中でも「凝集度」について説明していきたいと思います。

結合度については[こちら](https://qiita.com/ue_sho/items/59c99ccd712a591883d2)。

# 凝集度とは

情報工学においてモジュール内のソースコードが特定の機能を提供すべく如何に協調しているかを表す度合い。
凝集度の高いモジュールは、堅牢性、信頼性、再利用性、読みやすさなどの点で好ましくなります。 
(Wikipedia引用)

# 凝集度の種類

凝集度は7段階のレベルで表すことが出来ます。

|レベル|名前|内容|
|:-----------:|:------------|:------------|
|1|機能的凝集|単一の目的しか持たない機能を実行するモジュール|
|2|逐次的凝集|同一データを順番的に扱うモジュール|
|3|通信的凝集|同一データを扱う部分を集めたモジュール|
|4|手順的凝集|処理の流れをそのまま詰め込んだようなモジュール|
|5|一時的凝集|同じタイミングで発生する関係ない機能を集めたモジュール|
|6|論理的凝集|お互いに関係ない機能の一つを実行するモジュール|
|7|偶発的凝集|関係ない機能が集められたモジュール|

1が最も凝集度が高く、良い設計と言える。
数字が大きくなるほど凝集度が低くなり、低凝集となる。

良し悪しをはっきり区切ると
**<font color="red">良い凝集</font>** は 1~3
> 1 - 機能的凝集
> 2 - 逐次的凝集
> 3 - 通信的凝集

**<font color="blue">悪い凝集</font>** は 4~7
> 4 - 手順的凝集
> 5 - 一時的凝集
> 6 - 論理的凝集
> 7 - 偶発的凝集

それぞれについて詳しく説明していきます。

## 1. 機能的凝集

単一の目的しか持たない機能を実行するモジュールです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413529/620dfad5-f9c8-c178-b296-964e2995c59f.png)

例）肥満度を判定する。

**～を...する**という形で表すことができます。

## 2. 逐次的凝集

同一データを順番的に扱うモジュールです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413529/db4ecb32-9d73-5218-84da-d2837d067f37.png)

例）体脂肪率を計算し、値が正常であるかチェックする。

「値が正常である」ことは「体脂肪率を計算」しないと分からないので、必然的な順序が存在します。
かつ単一のデータを扱っていると逐次的凝集になります。

**単一のデータ**とは一つのデータという意味ではなく、**一つのまとまりのあるデータのこと**を指します。

一般的に体脂肪率は、体重と体脂肪量の２つのデータで計算されます。
これら二つは体脂肪率を計算するうえではまとまりのあるデータと言えます。


## 3. 通信的凝集

同一データを扱う部分を集めたモジュールです。

ここまでが<font color="red">良い凝集</font>です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413529/428ced58-b7c6-b904-acce-e5c74240d8e4.png)

例）体脂肪率変化を判定し、肥満度を判定する。

扱っている関心ごとは一つだが、それぞれの機能に必然的な順番はないです。

つまり、この場合「体脂肪率の変化の判定」と「肥満度の判定」の順番を逆にしても成り立ちます。

## 4. 手順的凝集

処理の流れをそのまま詰め込んだようなモジュールです。

ここからは<font color="blue">悪い凝集</font>になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413529/b6733df3-df7f-0ee1-93ac-56ef4d1d31e6.png)


例）体脂肪率を計算し、画面に表示する。

逐次的凝集のように機能に順番があるが、「体脂肪率の計算」と「画面に表示する」で使用するデータが異なるので手順的凝集度になります。

### 問題点

仕様変更で機能が「体脂肪率の計算」して「画面に表示」して「LEDを光らせる」というように
仕様変更で**機能が増えるごとに関数が大きくなり理解がし辛くなります**。

## 5. 一時的凝集

同じタイミングで発生する関係ない機能を集めたモジュールです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413529/b8e9dfe4-fdc8-ea05-503a-5a582ad1e1c8.png)

例1）画面を初期化して、ユーザー情報を初期化して、測定器を初期化する

例2）エラーLEDを点滅させて、入力待ち状態に戻る

例のように目的が違うものをタイミングが同じというだけでまとめてしまうのは低凝集となります。

### 問題点

違うデータや目的のものを一斉に扱うので、影響範囲が広く保守がし辛くなります。


## 6. 論理的凝集

お互いに関係ない機能の一つを実行するモジュール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413529/5988c9e9-b117-e47b-7968-683ae62dd07f.png)

例）ユーザー情報を初期化する、またはユーザーを書き換える。

分岐させることが悪いことではありません。

分岐先の処理がお互いに関係ないことが問題です。

### 問題点

外部からの指示によって処理結果が変わるので可読性が悪いです。
また、複数のデータを扱う可能性が非常に高いです。
仕様変更で機能が追加されることも考えられます。
とにかく保守性が悪いです。

## 7. 偶発的凝集

複数のデータが扱われていたり、関係ない機能が集められたモジュールです。

### 問題点

問題点しかないです。やめましょう。

# まとめ

最初にも書きましたが、凝集度の高いモジュールは、堅牢性、信頼性、再利用性、読みやすさが向上します。

問題点をいくつか書きましたが、以下のことをすることで高凝集になり解決できます。

**<font color="red">「単一データを扱うようにモジュール化 (関数分割) する」</font>**

関数分割をすると関数呼び出しをするため処理速度が遅くなると言う人もいるかもしれないです。
しかし、今の時代PCの処理はナノ秒という速度なので、**凝集度などで保守性を上げることのほうが大切**と言えるでしょう。

コードを書く際やレビューをする際などは

1. 機能的凝集
2. 逐次的凝集
3. 通信的凝集

を意識して書いていくことを強くオススメします。

# 最後に

今回モジュールに着目して書きましたが、ファイルの分割やクラスにも当てはめることができます。

保守性の高いコードを書くことは会社にとっても自分にとっても良いことです。

自分もできていませんが、他の人が読んでも分かりやすいコードを目指しましょう！

結合度についても合わせて読んでみてください

https://qiita.com/uesho/items/59c99ccd712a591883d2