>[success] # 高內聚、松耦合
**高內聚**是`模塊(后臺class 前端hooks 等)`功能的**專一性高,獨立性強**.**低耦合**是模塊之間的**聯系盡量少,盡量簡單**,這句話是描述**模塊設計的兩個方面**
* **高內聚**相近的功能應該放到同一個類中,不相近的功能不要放到同一個類中。相近的功能往往會被同時修改,放到同一個類中,修改會比較集中,代碼容易維護
* **低耦合**類與類之間的依賴關系簡單清晰。即使兩個類有依賴關系,一個類的代碼改動不會或者很少導致依賴類的代碼改動
>[danger] ##### 高內聚、松耦合之間關系
`高內聚`有助于`松耦合`,同理,`低內聚`也會導致`緊耦合`
* [圖片來自極客時間](https://time.geekbang.org/column/article/179615)

左面符合,**高內聚、松耦合**,將每個類都顆粒化,屬于自己的功能都高度聚集,減少了代碼直接的耦合度,這樣在更改代碼時候影響到依賴少,改動少
右面屬于**低內聚,緊耦合**,將`G和I `的實現混為一個功能模塊,構成了**低內聚**因此 產生了錯綜復雜的模塊間相互依賴形成了**緊耦合**,當我們修改這個類的某一個功能代碼的時候,會影響依賴它的多個類
>[danger] ##### 內聚
內聚程度從`低到高`,即**越往下越高內聚越推薦**
* **偶然內聚**:一個模塊內的各處理元素之間沒有任何聯系,只是偶然地被湊到一起。這種模塊也稱為巧合內聚
* **邏輯內聚**:這種模塊把幾種相關的功能組合在一起, 每次被調用時,由傳送給模塊參數來確定該模塊應完成哪一種功能
* **時間內聚**:把需要同時執行的動作組合在一起形成的模塊稱為時間內聚模塊
* **過程內聚**:構件或者操作的組合方式是,允許在調用前面的構件或操作之后,馬上調用后面的構件或操作,即使兩者之間沒有數據進行傳遞。簡單的說就是如果一個模塊內的處理元素是相關的,而且必須以特定次序執行則稱為過程內聚(要完成登錄的功能,前一個功能判斷網絡狀態,后一個執行登錄操作,顯然是按照特定次序執行的)
* **通信內聚**:指模塊內所有處理元素都在同一個數據結構上操作或所有處理功能都通過公用數據而發生關聯(有時稱之為信息內聚)。即指模塊內各個組成部分都使用相同的數據結構或產生相同的數據結構
* **順序內聚**:一個模塊中各個處理元素和同一個功能密切相關,而且這些處理必須順序執行,通常前一個處理元素的輸出時后一個處理元素的輸入
* **功能內聚**:模塊內所有元素的各個組成部分全部都為完成同一個功能而存在,共同完成一個單一的功能,模塊已不可再分。即模塊僅包括為完成某個功能所必須的所有成分,這些成分緊密聯系、缺一不可。
*****
**功能內聚**是最強的內聚,其優點是它的功能明確
>[danger] ##### 耦合
耦合程度從`高到低`,即**越往下越高內聚越推薦**
* **內容性耦合**,即模塊間存在某個模塊訪問另一個模塊內部數據的情況,或者模塊間不是通過正常的數據交換接口來交換數據的,都稱其為內容性耦合,這種耦合或導致內容的混亂,引發邏輯沖突;(內容耦合可能在匯編語言中出現。大多數高級語言都已設計成不允許出現內容耦合。這種耦合的耦合性最強,模塊獨立性最弱。)
* **公共耦合**:一組模塊都訪問同一個全局數據結構,則稱之為公共耦合。公共數據環境可以是全局數據結構、共享的通信區、內存的公共覆蓋區等。如果模塊只是向公共數據環境輸入數據,或是只從公共數據環境取出數據,這屬于比**較松散的公共耦合**;如果模塊既向公共數據環境輸入數據又從公共數據環境取出數據,這屬于**較緊密的公共耦合** 缺點:
1. 無法控制各個模塊對公共數據的存取,嚴重影響了軟件模塊的可靠性和適應性。
2. 使軟件的可維護性變差。若一個模塊修改了公共數據,則會影響相關模塊。
3. 降低了軟件的可理解性。不容易清楚知道哪些數據被哪些模塊所共享,排錯困難。一般地,僅當模塊間共享的數據很多且通過參數傳遞很不方便時,才使用公共耦合。
* **外部耦合**:即多個模塊做訪問全局變量時,不通過約束的結構性參數來傳遞信息,而是直接使用簡單的變量傳遞信息,這回導致邏輯語義的缺失,致使模塊間的功能依賴不易理解;
* **控制耦合**:模塊之間傳遞的不是數據信息,而是控制信息例如標志、開關量等,一個模塊控制了另一個模塊的功能。
* **數據性耦合**,即模塊間接依賴是通過數據交換來完成成的,數據交換過程中不存在控制信息,模塊間只關注彼此的數據交換協議,而不關注模塊內部的數據處理和邏輯控制;(有點函數傳參的味道)
* **非直接耦合**,即平行模塊間不存在彼此的依賴,它們的運行只依賴其上層模塊的調度。
*****
**非直接耦合**作為耦合度最低效果最好的
>[info] ## 高內聚低耦合和其他原則關聯
實際上,所有設計原則的目的都是提高代碼的擴展性,實現高內聚、低耦合,只是手段(出發角度)不同:
1. 開閉原則是從理念本身出發
2. 單一職責原則是從功能的角度出發;
3. 迪米特原則從類之間的關系出發(不該依賴的不依賴,要依賴的最小必要依賴);
4. 接口隔離原則是從接口調用者的角度出發;
5. 里式替換原則是從類的繼承關系角度出發;
6. 控制反轉(依賴倒置)原則是從程序的控制權角度出發。 目的是提高代碼可讀性和可維護性從而間接提升代碼可擴展性的設計原則有: 1. KISS、YAGNI 2. DRY ----- > 目的都是實現高內聚低耦合,但是出發的角度不一樣,單一職責是從自身提供的功能出發,迪米特法則是從關系出發,針對接口而非實現編程是使用者的角度,殊途同歸。
*****
1. 單一職責原則 適用對象: 模塊,類,接口 白話:職責太多,容易被依賴(高耦合),以后維護,容易牽一發而動全身。(易維護性)
2. 接口隔離原則 適用對象:接口,函數 白話:有些是不需要讓你知道的,避免調用者需要了解的太多(最小知識原則)。有些是不能讓你知道的,屬于權限問題,需要隔離開來。
3. 基于接口而非實現編程 適用對象: 接口,抽象類 白話:易維護和可擴展性問題。業務不穩定,于是依賴相對穩定的接口。
4. 迪米特法則 適用對象:模塊,類 白話:這個只是原則,不是說從誰的角度考慮吧。只要符合這個原則,就能做到高內聚、低耦合。
>[info] ## 參考
[設計模式之美](https://time.geekbang.org/column/article/179615)
[# 高內聚低耦合的設計原則](https://zhuanlan.zhihu.com/p/546934025)
[# 低耦合,高內聚的詳解(絕對全面)](https://blog.csdn.net/fengye454545/article/details/79592751)