iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0
Software Development

一個好的系統之好維護基本篇 ( 馬克版 )系列 第 6

Day 06 : 聚合性三大原則 - REP、CCP、CRP

  • 分享至 

  • xImage
  •  

同步至 medium

https://ithelp.ithome.com.tw/upload/images/20240921/20089358ImS2dXYZRG.png

對了順到先說一下,這幾個東西的概念都是從《Agile Software Development, Principles, Patterns, and Practices》裡提到的,其中它是專門用來討論 package、module、component,放正有很多種意思,然後這裡只要想成某一些程式碼的集合就好。

然後今天要談的,就是要如何讓這個程式碼的集合(模組)可以更 cohesion。接下來我們就來談談這三個原則

  • 重用性-發布等價原則(REP:Reuse/Release Equivalence Principle)
  • 共用封閉原則(CCP:Common Closure Principle)
  • 共同重複使用原則(CRP:Common Reuse Principle)

然後有個重點要先說

聚合這三個原則,都是 base 在解耦的前提,也就是說它希望在不影響其它元件情況下,越聚合越好

重用性-發布等價原則(REP:Reuse/Release Equivalence Principle)

這個概念是由 Robert C. Martin 在 《Agile Software Development, Principles, Patterns, and Practices》所提出,內容如下 :

The unit of reuse is the unit of release. Effective reuse requires tracking of releases from a change control system. The package is the effective unit of reuse and release.

我事實上當初在看這個原則的定義時,有點看不太懂,而且這和聚合性有什麼關,後來悟了一下,下面是我自已比較理解的句子 :

要 reuse 的元件,應該要一起 release,所以反過來說,要一起 release 的元件,就應該都放在一起。

因為如果一個開發者寫了一個 class 說它是可以重複使用的,事實上也只是一開始可以用,但是接下來在變更之後的事情,能不能重用就是另一回事。

備註 : 事實上還有一段就是說要 reuse 時不要 copy 原始的程式碼,因為舊有的改了,copy 的就沒辦法跟蹤了,但我自已在想,這不是應該是每個開發者都知道的嗎…

然後這個我在實務上算有看過,但通常比較常發生在為了切而切的地方,例如三不五時就切個 lib 或微服務,然後每一次 release 時發現,要等其它 lib 上完後,才能 release。

所以在設計元件時,通常要確定他是可以被獨立運行與佈署的,以 libary 來說,版控就是一個實踐 REP 的方法,但是如果本來拆分時就和其它服務職責重疊與依賴太多,那就沒救了……

然後最後書中還有提到一句話如下,我自已覺得讓我在拆分時也有個方向。

一個元件中的類別若不是全部都是可重複使用的,那麼就必須全部不是可重複使用的。

共用封閉原則(CCP:Common Closure Principle)

The classes in a package should be closed together against the same kinds of changes. a change that affects a package affects all the classes in that package.

這個原則到很好理解,而且實務上也是很實用,它的主要概念為 :

經常一起變化的元件,就應該放在一起,因為他們的變化原因可能很相同

假設我們有兩個元件,分別為 :

  • order : 用戶交易的單位
  • suborder : 每一筆商品各別的子訂單

這個時後如果你將 order 與 suborder 分開來在兩個元件,或是兩個微服務,那和找死差不多,如果某個商品退款了,然後 order 就要修改某個欄位,接下來如果分 2 個 module 就是 2 個都要動,然後如果是微服務就又需要想分散式事務…。然後順到說一下,這個概念事實上很接近後面 DDD 的 Aggregate 要說明的概念,這個後來在來談談。

那要如何遵守呢 ? 在開發上,我要如何判斷那些東西要放在一起呢 ? 那些不用呢 ?

這裡我先簡單談一下我的想法,詳細後面會說,如果是 domain layer,通常我們會設計 domain model,然後假設我們現在有 2 個 domain model 我們用 A 與 B 來說明,然後在開發初起他們還很獨立,也就是說不會一個一個欄位變了,會去影響到另一個,但開發久了發現,我的 A 欄位變動,同時間也需要去改 B 的,越來越多,那就是該考慮合成一個 Aggregate 了。

共同重複使用原則(CRP:Common Reuse Principle)

The classes in a package are reused together. if you reuse one of the classes in a package, you reuse them all.

這一個原則根據原文來看,他的主要概念如下 :

經常一起被使用的類別應該放在一起,包含依賴的東西。但反過來說不被依賴的就不要包在一起。

就像是我們實務上不是很常有 service 與 repository ,然後通常會透過 service 去 repository 抓資料,所以如果有 userService 與 userRepository 的話,他們就應該被放在同樣的模組中。

但是我這裡想到一點,就是我們通常會依賴一些 common 類的東西,那這個東西要怎麼辦法 ? 如果根據這個原則那就會包含同一個模組中,但這樣其中一個模組就又要自已做一個 common 類的東西 ? 所以這裡我通常會先想一下依賴的東西的特性。

小結

  • CCP 與 CRP 事實上有衝突,兩個主要的意思為 :
  • CCP 共用封閉原則 : 一個包中的所有類別應該對相同類型的變更保持封閉
  • CRP 共同重複使用原則 : 在一個包中重複使用的類別應該放在同一個包裡

衝突的情境

維護與重複使用: CCP 強調對變更的封閉性,CRP 強調類別之間的重複使用。如果兩個類別經常一起使用,但它們在不同的包中,這可能會違反 CRP。然而,如果這兩個類別對變更的影響是不同的,將它們放在同一個包中可能會違反 CCP。


上一篇
Day-05: 耦合性三大原則 ADP、SDP、SAP
下一篇
Day-07: 設計原則的小整理
系列文
一個好的系統之好維護基本篇 ( 馬克版 )30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言