寫出好維護的程式碼 — 高內聚
2025年6月10日
在 寫出好維護的程式碼 — 依賴注入 (Dependency Injection) 與控制反轉 (Inversion of Control) 主題文中,我們談了透過依賴注入 (dependency injection) 與控制反轉 (inversion of control) 這兩個手段把程式碼的耦合度降低,讓程式碼更容易維護。
當提到耦合度,相信多數讀者都聽過「高內聚、低耦合 high cohesion, low coupling」這個原則,在 寫出好維護的程式碼 — 依賴注入 (Dependency Injection) 與控制反轉 (Inversion of Control) 主題文中我們主要在談如何降低耦合,而在這期主題文,我們會專注在「高內聚」的概念上。
從日常生活的例子來理解內聚
在實際談程式撰寫時的高內聚之前,想先用一個生活化的例子跟大家談「內聚」是什麼概念。
以多數人都熟知的廚房為例,在一個料理新手的廚房中,可能因為本身對不同的器具與調味料不熟,所以可能會把所有的東西都塞在一起。這種狀況下,假如今天要煮一道菜,光是找要用的工具以及搭配的調味料,可能就需要先花不少時間。
然而,假如有看過餐廳中專業廚師所使用的廚房,多半會發現整體的動線是精心設計過,不同的廚具、食材、調味料的位置擺放,也都是有縝密的計算,讓廚師能夠在最短的時間拿到自己要用的廚具、食材與佐料。
舉例來說,一個常見的分類方式是把肉類跟蔬菜分開來放,在肉類中不同的肉也會有不同的收納,牛肉不會跟魚肉混在一起,這樣要烹調牛肉相關的料理時,可以非常迅速地找出來。
當然,有些廚房可能會有不同的分類。舉例來說,有些鐵板燒店之所以整體運作效率非常高,其中一個原因是它們把熱門餐點所需的材料,全都事先整理好了。所以當點了沙朗牛排,廚師可以直接拿出要煎那道牛排所需的所有東西,從牛肉本身到相關配料。
上面的這個例子,就是高內聚的表現。例子中的沙朗備盤,是單一職責、單一目的,其存在就是為了讓廚師能煎出美味的沙朗牛排。在沙朗備盤中,沒有任何跟要煎沙朗牛排無關的東西,裡面有的材料全都是與製作沙朗牛排相關。
抽象一點來說,高內聚是指「把相關的東西聚在一起,藉此達到單一目的」,所以備盤的單一目的,以及盤中的東西都是高度相關,就是高內聚的展現。
而當這樣準備,就能夠讓廚師運作起來很高效,因為不用為在煎沙朗牛排時,還要在混雜著甜點佐料的區域找調味料;因為不用大範圍的東翻西找,這能讓速度變快,也能避免拿錯東西。
什麼是高內聚? 有什麼好處?
希望透過上面的例子,讀者們對於高內聚是什麼,有比較具體的理解。在這個段落,讓我們把重點拉回軟體工程的領域中。在軟體工程中,所謂的高內聚是指,把相關的東西聚在一個模組 (例如某個類別或函式)當中,讓該模組有單一且定義清楚的職責。
因此在檢視一個類別或函式時,如果該類別或函式有一個清楚的目的,且類別與函式當中的內容,彼此相近,且僅為該目的而存在,這樣就會說是高內聚。反之,如果一個類別或函式,做了很多事,且做的事情彼此沒關聯,就會被認為是低內聚。
寫程式時到底要拆開還是要聚在一起?
在理解完高內聚的定義與好處後,相信有些讀者這時可能會有個疑問,那就是「高內聚、低耦合」這句話似乎有一點彼此相衝突,高內聚在講要把相近的東西聚在一起,這樣跟耦合在談的要把東西拆開、抽出去似乎有點相違背。
關於這個問題,在《Balancing Coupling in Software Design》一書當中,作者 Vlad Khononov 談到一個很精闢的點。他說內聚是指「模組當中,要素之間彼此相近的程度」。換句話說,內聚本身就是一種耦合。只是內聚的耦合是一種「好耦合」 (作者的原文是寫 cohesion as “good coupling”)。
之所以說這個說法精闢,是因為在寫程式時,總是不免有東西要放一起,只是當放在一起時,如果又要擔心耦合的揉雜,可能會讓大家在寫程式時有所顧忌。但如果用「好耦合」的角度來看,假如某些東西彼此足夠相近,放在一起能帶來上述高內聚的好處,那麼即使放在一起有耦合也無妨。
因此,在思考高內聚時,推薦讀者們可以從「好耦合」的角度來看,推薦可以思考「哪些東西放在一起會讓未來要維護時可以更容易」,藉此來決定什麼要放一起、什麼要拆開。
高內聚與低耦合,檢視的角度有所不同
除了上一段落的角度外,在看「高內聚、低耦合」時,也推薦讀者們可以用不同的視角來看。
具體來說:
- 高內聚是在檢視「模組之內」,確保模組內的東西高度關聯,專注在單一目標
- 低耦合是在檢視「模組之間」,確保模組間不相互糾纏,避免牽一髮動全身的狀況
事實上,這兩種是相輔相成的,當今天如果我們確保一個模組是高內聚的,就能同時確保這個模組有清楚的邊界,這樣跟其他模組之間也比較容易是低耦合的。
閱讀更多
如果讀者們想更了解高內聚這個主題,並有具體的程式碼案例分析,以及高內聚在軟體工程其他面向的應用,我們在 E+ 成長計畫的主題文中,都有更詳細談。感興趣的讀者,可以在以下連結看到 E+ 的詳細介紹 (連結)。
本文為 E+ 成長計畫的深度內容,截取段落開放免費閱讀。歡迎加入 E+ 成長計畫閱讀完整版本 (點此了解 E+ 的詳細介紹)。