Clean Architecture 實作篇 (九 ~十二)

elliot
Feb 19, 2024

--

應用程式組裝

為了讓應用程式層中的領域程式碼始終指向內層方向(正確的依賴方向) ,所以我們使用了介面,達成反向依賴關係。 而實際的實作則是在執行階段才會提供,而提供的職責就是由一個獨立於架構之外,但會與所以類別產生依賴關係的設定元件,來負責實例化。

其中介紹了三種做法,第一種是純程式碼組裝,這種方式最單純不過會產生大量的程式碼,且必須將需要實例化的依賴都設定為 public,無法使用 package-private。 另外兩種則是透過 Java Spring 和 Spring Config組裝,不過這邊就不多補充,畢竟每一種框架提供的方式或多或少不同。

強化架構中的邊界

透過存取修飾子(Package-private) 的方式,防止非此模組內的類別存取,已降低 因為引入一個指向錯誤方向的依賴關係,而意外造成違反依賴關係的錯誤。 或是透過編譯後檢查,藉由一些工具檢測套件之間的依賴關係是否正確。

實際上我們可以透過切分模組的方式,達到更好的效果

從最基本的切分法(最左),應用程式設定模組、轉接器模組、應用程式模組。而轉接器模組內容同時包含了 網頁層轉接器 以及 儲存層轉接器,這兩個又可以各自切分(依據SRP原則,不該將儲存層洩漏給網頁層)

接著,應用程式也進一步切分,區分出轉接埠 和 實作的服務。 更進一步,可以將輸入轉接埠 和 輸出轉接埠拆分,把服務歸屬在一個模組,把服務實體歸屬在另一個模組。 這樣就能確保依賴關係,確保領域實體不會反過來依賴服務。

然而,拆分得越細,我們對於依賴關係的掌握力就越強,所需要做的對應也就越多,但好處是單除修改某的模組的程式碼時,無須考慮其他模組,也就是說可以由不同開發團隊維護,甚至可以達到 Hot Reload;這樣明確的依賴關係會讓開發人員想要存取 目前尚未允許存取得類別時,多一道關卡,需要多想一想到底需不需要這層依賴關係。

理性看待偷吃步

在使用案例之間共用模型

違反SRP,這兩個使用案例會有相同被修改的理由,除非確實有著共同的需求。

將領域實體當作輸出或輸入模型

這種方式在一開始 採用MVP發展時不會有啥問題,但是一旦提高複雜度時,這種作法就是危險的,原因是輸入輸出轉接埠都依賴於領域實體時,不論是輸入或輸出新增需求時,都必須去動到 領域實體,但是最好的方式應該是 網頁層 或 儲存層新增需求時,是只異動到該層。

省略輸出輸入轉接埠

這樣做,會導致失去了明確定義 通往應用程式核心的進入點,開法者必須對於應用程式內部要有一定的了解,才知道有哪些服務,雖然對於小規模的程式來說不是太大的問題。

省略應用服務

對於單純的CRUD的使用案例來說,應用服務所做的事情往往沒有領域邏輯的額外成分,只是單純的把 CRUD的請求轉交給儲存層轉接器完成而已。 所以很容易認為 不如直接讓儲存層直接去實作使用案例就好。

但這樣做會導致,領域邏輯會四散各處,很難維護。

選擇你的架構風格

其實討論了這麼多,我們可以發現六角架構最主要的功能是在於讓領域核心的程式碼不受到影響,這也是為何這種架構風格適合 DDD開發。

而如果你不把領域當作核心地位,不把依賴方向全部指向 領域程式碼 的話,就沒有落實DDD的機會,設計總會被其他因素給影響。

所以還是得視情況而定,要考量的有很多,團隊開發的經驗,領域程式碼的重要性,甚至是每位開發者所著重的點

--

--