內聚與耦合(二) 內聚篇 | Cohesion

2024-09-21
GRASP

看到高內聚的程式,舒適的程度

看到高內聚的程式,舒適的程度

複習前篇

前篇以 Larry Constantine 提出內聚跟耦合的種類作為開頭,具體地描述內聚與耦合的程度差別,本篇以在網路上關於高內聚的定義,且進一步分析。


兩個定義

兩個在網路上會查詢到的高內聚的定義,第一個是:

把需要的程式和資料都包裝在一個模組,使得該模組能夠做為一個單獨的個體執行。

透過將所需資料都聚在一起,因此高內聚,強調了模組的獨立性,而另一個定義是:

degree to which the elements inside a module belong together
模組內部元素屬於一起的程度

此定義更關注內部元素的相關程度,而非模組透過所需資料聚在一起的獨立性。

獨立性的矛盾

如果模組的獨立性作為內聚的評判標準,會出現內聚越高,模組越獨立,從而導致模組自身程式碼過多。例如該模組可能同時擁有日誌紀錄、持久化、快取等等...,導致模組很臃腫。

雖然可以使用將抽象與實現拆分、依賴反轉、拆分共同模組,但此時矛盾出現了,一方面我們高喊著要追求高內聚,另一方面我們又忌憚著高內聚

一個概念如此對立,除了他本身就是這麼複雜以外,也可能是我們搞錯了這個概念的定義,也就是高內聚的意思。

內聚程度

“ Cohesion is the degree to which the members of a certain class belong together. It is a measure of how deeply each piece of device module functionality relates”
“內聚力是某個類的成員屬於一起的程度。它是衡量每個設備模組功能相關程度的指標”

― Fenton, N., & Bieman, J. (2014). Software Metrics: A Rigorous and Practical Approach (3rd ed.).

高內聚通常是功能內聚性(Functional cohesion)、循序內聚力 (Sequential Cohesion)、溝通內聚力 (Communication Cohesion)

  • 功能內聚力 (Functional Cohesion):模組內的元素都屬於單一明確定義的概念,屬於狹隘的業務概念,意旨某個特定業務情境的某個概念。
  • 循序內聚力 (Sequential Cohesion):模組內的元素彼此有順序性,且符合某元素的輸出作為另一個元素的輸入的順序關係。
  • 溝通內聚力 (Communication Cohesion):模組內的元素都需要依賴某一個共同的輸入或更新相同的輸出。

功能內聚力描述了高內聚在業務方面的呈現樣貌;循序內聚力描述了高內聚的元素具有順序需要遵循什麼原則;溝通內聚力描述了高內聚的元素描述了一個總體 - 個別的關係。

可讀性

高內聚也帶來可讀性的提升,如果它符合以上的高內聚描述,我們閱讀程式或模組時,我們不用擔心其他種可能性,尤其是功能內聚力對於概念的歧異性的化解

例如:商務管理系統中產品這個概念,在銷售人員、採購人員、倉庫管理人員關注點以及使用方式都會不一致,銷售人員更關心產品的促銷策略;採購人員更關心產品的成本;倉庫管理人員更關心產品進貨出貨的時間。

而如果產品被作為一個模塊,而非符合功能內聚力的描述,會造成閱讀時要在這三方業務邏輯反覆橫跳,降低了可讀性。因此高內聚使得元素只屬於單一情境的概念這一特性,有助於提升可讀性。

可容忍的低內聚

而在少數情況下,可以接受低內聚的模組或程式碼,例如專案的 SQL 專家,不太了解物件導向的設計,但也只有他能最佳化以及維護這些 SQL 語句,此時把所有 SQL 語句放在同一個類別中,有助於讓 SQL 專家在一個類別進行語句的工作。

又如果極度需要控管性能以及系統開銷,那可以考慮將對於其他服務的接口相關類別使用低內聚的方式設計,以降低系統的物件數量以及較容易統一管理對其他服務的連線的性能開銷。


作者心得

雖然很多文章都是採用第一種定義去描述高內聚,不過對我來講就是有一種矛盾的感覺,因此看到第二種的描述有一種,找到答案的感覺。

咒術迴戰最後一集了... 真的是夢的結束了...


參考資料

也可以看看以下文章