如何避免寫出爛的業務代碼(2)- DDD 整改
一. 背景
目前很多的業務代碼存在以下問題
-
bean 的創建太隨意,基本就是一個需求一些對應的 dto,vo,query bean。
-
不同開發者對於同一個領域的東西有不同的 bean,同一個開發者對於相同邏輯的 bean,在經過 2 月 + 的時間,自己又定義出了一個差不多的 bean -> 職責分散
-
不同開發者對於某塊相同業務的邏輯校驗放在了不同的 service 中 -> 代碼邏輯重複
-
不同的後端 / 前端對接時,相同概念的命名存在差異,導致後面重構時數據訪問沉澱到 manager 層,上層調用的時候處理 case 有問題
-
DTO 類型的 bean 重構過程中根本不知道哪些是可以爲 Null,哪些不可以 根本沒有上下文 / 邊界的概念,比如說模塊 A 會和模塊 B 有交互,模塊 C 會和模塊 B 有交互,通常在 DB 存儲時只會存關聯 id,然後需要去取對應的名稱,其他屬性信息。 這些信息的獲取,有些開發在 manager 層操作,然後將屬性定義到了模塊 A 相關的 DTO 中,有些放在了 service 層做,對於模塊 B 的有效性校驗,也是在不同的 service 中
二. 工程架構圖演進
現狀
目前的系統結構圖通常下面這樣
-
四層 controller/service/manager/mapper
-
不可以同級調用
-
上級可以知曉下級,下級不可知曉上級,也就是 bean 的轉化放在上級
這個分層結構和領域模型對應一下就會發現有些問題
-
資源服務層 repository 是面向 DB 編程
-
service 層是面向前端頁面編程。
這樣對於某一塊的業務,還是沒有將邏輯抽象到一起, 也就不可避免的邏輯冗餘
改進
-
service 層只能調用自己領域的 manager
-
增加一層 Facade 層,專門處理與其他領域的交互 (如果業務還沒有這麼複雜,加上層級太多影響開發效率, 可以採用 FacadeXXXService 來標識這個類專門處理與其他領域的交互) 這樣調整以後結構清晰了許多了,manager 層只處理自己領域的數據 / 緩存,service 層處理自己領域的業務。與外界交互都在自己 Facade 層。
雖然這些改造都只是包結構的調整,但對於一個持續迭代的多人項目開發,帶來的好處是能夠快速瞭解某一塊業務,當新人寫這塊業務的時候,能夠寫在對應的模塊,能夠利用已經寫好的邏輯 / bean.
三. 領域識別
領域演進. 明確的領域 這些領域概念比較清晰,在業界比較通用在一開始就能明確,比如用戶,商品,訂單
演變的領域
有些業務是不斷演進的,一個領域也會裂表爲多個領域,比如訂單和支付。 也有一些比較模糊的領域區分,比如商品清單這邊有個清單業務,將商品添加到清單,就是一個 collection,DB 的設計也就是關聯 id 而已,它能夠劃分到商品領域嗎,不能,因爲它不屬於商品,沒有它不影響商品業務。 清單只是一個展示商品的地方。那他能成爲一個單獨的領域,也很勉強,因爲它的概念比較單薄,可以抽象出來的東西比較少,對於這類的問題,建議是在類級別做區分,當它的概念不斷增加,領域不斷豐富時,抽出到單獨的包,作爲一個新的領域
做上面結構的調整,除了能夠提供代碼規範性,另外一個好處就是做減小微服務化的改造代價。因爲邊界清晰,與其他業務的交互清晰。比如你有一個工程,規劃了 6 個領域模塊,當某個領域模塊發展足夠大,可以遷移出去作爲一個獨立的微服務部署,這時候只需要將它對應的 service,manager 包,以及對於的 bean 遷出即可。其他服務與它的交互可以由 service 改成 soa 調用
潛在的問題目前的領域對象還是不夠豐富 當領域對象多了,相同的編排 / 組合領域對象也可以成爲一個獨立的領域上下文,這時候如何定義這類領域
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s?__biz=MzI4NjI3MDc1NA==&mid=2247483781&idx=1&sn=fe0470775fbbcccd106673833f41ba17&chksm=ebde35c8dca9bcde5fc31651b08f612a19a477ff7f20c95a135513ca2ffcef3c974aded802b0&scene=21#wechat_redirect