談談軟體元件的內聚與耦合(1)

更新於 發佈於 閱讀時間約 8 分鐘

近期花了一些時間研讀 Robert C. Martin 所著的 Clean Architecture 這本書,剛好看到了一些概念恰巧可以與工作上遇到的架構做一些印證,於是便想寫一些文章做一些紀錄。

在 Clean Architecture 中,提到了軟體元件的內聚與耦合的概念。

何謂內聚(Cohesion)與耦合(Coupling)呢?

在軟體工程(Software Engineering)中,內聚(Cohesion)與耦合(Coupling) 是軟體工程中,用來衡量元件的度量,我們可以用其來衡量模組與其他模組間的關連性或相依性。

內聚力(Cohesion) 顧名思義是指把相關的東西集合在一起,因此,模組本身不需依賴其他模組,就能完成工作。

當模組的內聚力越高,表示模組包含的物件或功能就越多。雖然提高了模組本身的獨立性,減少跟其他模組的耦合性,但也可能造成重覆程式碼,或違背單一職責原則(SRP)的情況發生。

至於耦合力(Coupling)則是該模組與其他模組或元件的相依程度的大小,耦合度越高,代表模組與其他元件有著越大的相依性。

在高耦合的情況下,很容易發生這種情況,你明明只是加了一個很小的需求,但是卻連帶影響到跟它有相依關係的部份,造成修改後,很多地方都出錯,反而需要要花額外時間去修正被影響的程式碼,「牽一髮動全身」,這句俗諺就很適合用來形容這種情形。

由上述敘述我們可以知道,高耦合將伴隨著低內聚,而高內聚則伴隨著低耦合,在軟體開發的世界中,高內聚的系統比高耦合的系統還要來得容易維護

到這裡,我們來頭看看在元件內聚性,則必須提到以下述三個原則,將是用來衡量元件內聚性的實際標準。

再使用性——發布等價原則 (REP)

再使用性等價原則其實相當好了解,除了「再使用」代表著我們應該要重複利用那些經常被使用到的模組或元件,或是要把相同類型的程式碼歸類在同一個元件中,被歸類在同一個元件中的類別和模組應該要一起被發佈(Release)並伴隨著對應的版號(Version number)。

同時間發佈同元件的模組和程式碼也代表著每次Release都是可追蹤的,把元件依版本號也有一個好處,我們可以透過模組管理工具來管理這些可以重複利用的元件,每次版號的更新耶可以看到對應的更改,常見的模組管理工具,例如 Java的Maven 及 Gradle、Node.js 的 npm、Python的 pip 等等。

共同封閉原則 (CCP)

共同封閉原則的意義在於,要將那些會因為相同理由、在相同時間發生變化的類別收集在相同的元件中,而將那些在不同時間、會因為不同理由產生變化的類別分割到不同元件之中。

實際上的意義其實類似於單一職責原則,每一個類別、元件、方法都應該只有一種理由需要改變(one reason to change),這麼做將可以避免不必要的重新部署、更改與重新驗證。

格蘭特這邊可以舉一個簡單的例子:

以下是一個員工 Employee 類別。

Class Employee {
public int calculateMonthlySalary() {...}
public int generateMonthlyHoursReport() {...}
public void saveEmployee() {...}
}

Employee 裡面有三個功能計算每月薪水產生每月工時報告、儲存Employee資料,那我們來看看有甚麼理由會需要更改這個類別呢?

1.會計部想改變時薪的計算方式->需要更改calculateMonthlySalary() 2.人資想改變加班計算方式->需要更改generateMonthlyHoursReport()要改 3.工程師想改變Employee的編碼方式->需要更改saveEmployee()

當今天如果人資想改變加班的計算方式,從原本的 8 小時之後算加班改成上滿 10 小時後才算加班,這個時候你可能會想,只要簡單改一改 generateMonthlyHoursReport() 裡的邏輯就好了。

不過,當改完後發現,哇咧,由於沒有區分好職責的關係,原本計算薪資的 calculateMonthlySalary()方法中呼叫了generateMonthlyHoursReport()方法,導致最後每一個員工的每月薪資都被超時計算了。

是不是很恐怖呢? 由以上的例子我們可以知道 CCP 的重要性,不同類型、會在不同時間觸發更改的方法應該獨立成不同的元件。

如果我們 Refactor 原本的類別成以下的樣貌,將可以避免上面的狀況﹔

class Employee {
private String id;
public String getId() {
return id;
  }
}
class PaymentService {
public int calculateMonthlySalary(Employee employee) {...}
}
class WorkHoursServiceService{
public HoursReport generateMonthlyHoursReport(Employee employee) {...}
}
class EmployeeDAO {
public void saveEmployee(Employee employee) {...}
}

共同重複使用原則 (CRP)

共同重複使用原則的意義在於「不要強迫元件的使用者依賴他們不需要的東西」。

試想,當今天你的元件依賴了一堆根本不需要的東西時,只要A發生改變,B就要跟著改,有用到A與B的元件也會需要跟著改變,而這些更改將伴隨著重新編譯、測試以及部署,這將會是一場浩劫啊。

因此,當我們依賴著某一個元件時,要確保我們依賴於該元件中的所有類別,意即該元件中的所有類別都是不可分割的。

元件內聚張力圖

不過.....我們有可能三種原則都遵守嗎?

答案是,不可能的,這三種原則將彼此作用,更像是一種Trade-Off(取捨)。

REP 和 CCP 是包容性原則 (Inclusive) 這兩個原則傾向於讓元件變更大,因為要內聚更多相同類別與方法。

而 CRP 是一個排除性原則 (Exclusive) 這個原則傾向讓元件變更小,要讓元件成為最小且不可分割的單位。

因此,如果太過注重 REP 和 CCP,架構就會需要太多沒必要的release,反之如果太過注重 CCP 和 CRP,那麼你的架構就會很難重複使用,而如果太過注重 CRP 和 REP,那麼每次更改都會動到很多元件。

就如同格蘭特工作上同時要接觸 Legacy code 與 設計良好的 code,如果在元件中內聚太多類別及方法,反而會造成一堆 release,而每次 release 都要花費對應的 Effort 去處理,但如果拆分過多元件的話,又會造成其之中的方法難以重複被利用,也因此,如果不好好考慮可維護性的話,legacy code就會變得越來越龐大。

所以,在衡量及設計實際的系統時,我們更應該需要審慎評估每個系統的需求,找出一個最符合的平衡點,就好像沒有100%的男人/女人,只有彼此磨合,找到雙方都可以接受的那種方法及樣貌。

今天有關元件內聚就先提到這裡,下一篇要來談的是元件耦合。

本文同步發表於格蘭特的部落格

留言
avatar-img
留言分享你的想法!
avatar-img
格蘭特的沙龍
14會員
17內容數
還在為不知道怎麼面試而煩惱嗎? 還在為苦無面試機會而沮喪嗎? 別擔心~讓我們一起面對! 在專題中,我將以自身經驗傳授如何撰寫履歷以及分享面試經驗。
格蘭特的沙龍的其他內容
2023/10/26
嗨!我是格蘭特,歡迎來到軟體工程師面試大哉問! 近二十家公司面試經驗大公開,本篇是系列文的第八篇。 這篇將繼續分享上一篇在遊戲橘子的面試經驗。
Thumbnail
2023/10/26
嗨!我是格蘭特,歡迎來到軟體工程師面試大哉問! 近二十家公司面試經驗大公開,本篇是系列文的第八篇。 這篇將繼續分享上一篇在遊戲橘子的面試經驗。
Thumbnail
2023/07/18
嗨!我是格蘭特,歡迎來到軟體工程師面試大哉問! 近二十家公司面試經驗大公開,本篇是系列文的第七篇。 格蘭特這次要分享的是在遊戲領域中的佼佼者,自產及代理多種知名遊戲的遊戲橘子(Gamania)。 本次機會是由 Headhunter 在 LinkedIn 主動聯繫,職位是資深後端工程師。 由於篇
Thumbnail
2023/07/18
嗨!我是格蘭特,歡迎來到軟體工程師面試大哉問! 近二十家公司面試經驗大公開,本篇是系列文的第七篇。 格蘭特這次要分享的是在遊戲領域中的佼佼者,自產及代理多種知名遊戲的遊戲橘子(Gamania)。 本次機會是由 Headhunter 在 LinkedIn 主動聯繫,職位是資深後端工程師。 由於篇
Thumbnail
2023/04/06
歡迎來到格蘭特的私房好書,本文是專題系列文的第二篇。 因工作上有些事情需要處理,讓這個專題延宕了幾個月,希望大家不要見怪 :D。 今天要與大家一同閱讀的是 Annette Simmons 所著的《你的團隊需要一個會說故事的人》。 作者:Annette Simmons (安奈特.西蒙斯) 出版社:先覺
Thumbnail
2023/04/06
歡迎來到格蘭特的私房好書,本文是專題系列文的第二篇。 因工作上有些事情需要處理,讓這個專題延宕了幾個月,希望大家不要見怪 :D。 今天要與大家一同閱讀的是 Annette Simmons 所著的《你的團隊需要一個會說故事的人》。 作者:Annette Simmons (安奈特.西蒙斯) 出版社:先覺
Thumbnail
看更多
你可能也想看
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
大家好,我是一名眼科醫師,也是一位孩子的媽 身為眼科醫師的我,我知道視力發展對孩子來說有多關鍵。 每到開學季時,診間便充斥著許多憂心忡忡的家屬。近年來看診中,兒童提早近視、眼睛疲勞的案例明顯增加,除了3C使用過度,最常被忽略的,就是照明品質。 然而作為一位媽媽,孩子能在安全、舒適的環境
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
我的「媽」呀! 母親節即將到來,vocus 邀請你寫下屬於你的「媽」故事——不管是紀錄爆笑的日常,或是一直想對她表達的感謝,又或者,是你這輩子最想聽她說出的一句話。 也歡迎你曬出合照,分享照片背後的點點滴滴 ♥️ 透過創作,將這份情感表達出來吧!🥹
Thumbnail
Enterprise Architect Structure (EAS) 企業建構體系是一套針對組織發展以及人力資源綜合應用的應用理論體系。其中分成九大模組,彼此之間連動交錯形成一套縝密的應用系統。 EAS理論架構由台灣知名的企管顧問 陳致瑋所提出。理論最初創建於
Thumbnail
Enterprise Architect Structure (EAS) 企業建構體系是一套針對組織發展以及人力資源綜合應用的應用理論體系。其中分成九大模組,彼此之間連動交錯形成一套縝密的應用系統。 EAS理論架構由台灣知名的企管顧問 陳致瑋所提出。理論最初創建於
Thumbnail
老實說,從中文書名無法聯想回原文書是《The Elements of Scrum》,雖然書名翻譯沒有太離譜(和內容無關之類的),但總覺得貼近原意會好一點。『Scrum團隊週記』這一章,整個讀完,其實就差不多可以了解Scrum的大部分,所以,若要讀這本書,又沒有太多時間,就先看這一章吧!
Thumbnail
老實說,從中文書名無法聯想回原文書是《The Elements of Scrum》,雖然書名翻譯沒有太離譜(和內容無關之類的),但總覺得貼近原意會好一點。『Scrum團隊週記』這一章,整個讀完,其實就差不多可以了解Scrum的大部分,所以,若要讀這本書,又沒有太多時間,就先看這一章吧!
Thumbnail
這本書大概花了一個禮拜的零碎時間看完,其實收穫很多,很多原則不僅僅適用於微服務,也適用在單體式應用被部署在很多節點上,加上跟過去的經驗比較,更能體會到書中的觀點
Thumbnail
這本書大概花了一個禮拜的零碎時間看完,其實收穫很多,很多原則不僅僅適用於微服務,也適用在單體式應用被部署在很多節點上,加上跟過去的經驗比較,更能體會到書中的觀點
Thumbnail
近期花了一些時間研讀 Robert C. Martin 所著的 Clean Architecture 這本書,剛好看到了一些概念恰巧可以與工作上遇到的架構做一些印證,於是便想寫一些文章做一些紀錄。 在 Clean Architecture 中,提到了軟體元件的內聚與耦合的概念。
Thumbnail
近期花了一些時間研讀 Robert C. Martin 所著的 Clean Architecture 這本書,剛好看到了一些概念恰巧可以與工作上遇到的架構做一些印證,於是便想寫一些文章做一些紀錄。 在 Clean Architecture 中,提到了軟體元件的內聚與耦合的概念。
Thumbnail
自今年起,我開始接手了公司的GLP規範之章程的建立,從零開始,到今年也建構了一年,過程中也對流程建立也有些心得,也深刻理解這不是件容易的事情,一方面需要釐清目標與現況資源的差距,在有意義的規範下河有限的資源創造出最可行的規範,是一門專業。此篇跟大家聊聊,如何從零到有。
Thumbnail
自今年起,我開始接手了公司的GLP規範之章程的建立,從零開始,到今年也建構了一年,過程中也對流程建立也有些心得,也深刻理解這不是件容易的事情,一方面需要釐清目標與現況資源的差距,在有意義的規範下河有限的資源創造出最可行的規範,是一門專業。此篇跟大家聊聊,如何從零到有。
Thumbnail
本筆記除了以文字說明SOLID設計原則以外,並以Java code實際舉例。 Single Responsibility Principle (SRP) 單一職責原則 每個人負責屬於自己的職責,不該承擔太多職責,大家各自做自己應該做的事情,且不會互相干擾。 續上程式碼,修改如下: Output:
Thumbnail
本筆記除了以文字說明SOLID設計原則以外,並以Java code實際舉例。 Single Responsibility Principle (SRP) 單一職責原則 每個人負責屬於自己的職責,不該承擔太多職責,大家各自做自己應該做的事情,且不會互相干擾。 續上程式碼,修改如下: Output:
Thumbnail
《LeSS in Action》是一個關於 Scrum 的工作坊,我們將在一週的時間內模擬加入一間公司,並且在一週後馬上離職。因此這是一間工程師 100% 離職率的公司,在這一週的時間內我們需要學習針對一個真實的產品進行開發,跨團隊的協作來產生貢獻。
Thumbnail
《LeSS in Action》是一個關於 Scrum 的工作坊,我們將在一週的時間內模擬加入一間公司,並且在一週後馬上離職。因此這是一間工程師 100% 離職率的公司,在這一週的時間內我們需要學習針對一個真實的產品進行開發,跨團隊的協作來產生貢獻。
Thumbnail
隨著軟體開發方法、工具、以及成品應用方式的變化,軟體開發已經不能只靠單一證照、程序、手段來完成;雖然如此,為了專案的進度與品質控管,仍然有一些共通的道理是必須遵守的。本文就來談談這些同樣也適用於其他專案管理的基本原則。
Thumbnail
隨著軟體開發方法、工具、以及成品應用方式的變化,軟體開發已經不能只靠單一證照、程序、手段來完成;雖然如此,為了專案的進度與品質控管,仍然有一些共通的道理是必須遵守的。本文就來談談這些同樣也適用於其他專案管理的基本原則。
Thumbnail
「究竟應該花多點時間去寫好編碼,還是應該快快寫好新的功能,往後才改善編碼的質素」,雖然大家心裏面都希望花時間寫好每一個功能的編碼,但面對開發時間永遠不足、上司的壓力,很多時就會無視編碼的質素,來成就新功能/新產品可以及早推出。我們怎麼說服你自己、你的上司一開始的編碼質素是何其重要?
Thumbnail
「究竟應該花多點時間去寫好編碼,還是應該快快寫好新的功能,往後才改善編碼的質素」,雖然大家心裏面都希望花時間寫好每一個功能的編碼,但面對開發時間永遠不足、上司的壓力,很多時就會無視編碼的質素,來成就新功能/新產品可以及早推出。我們怎麼說服你自己、你的上司一開始的編碼質素是何其重要?
Thumbnail
許多企業都有疊床架屋、多頭馬車、冗員充斥的現象,造成了「職、權、責分離」的結果,必須以提高「職、權、責合一」的程度來解決。如果能做到這一點,效率提升、速度加快、成本降低都只是額外的好處,真正的目標在於建立能「當責」的企業文化。
Thumbnail
許多企業都有疊床架屋、多頭馬車、冗員充斥的現象,造成了「職、權、責分離」的結果,必須以提高「職、權、責合一」的程度來解決。如果能做到這一點,效率提升、速度加快、成本降低都只是額外的好處,真正的目標在於建立能「當責」的企業文化。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News