如何避免寫出爛的業務代碼(2)- DDD 整改

一. 背景

目前很多的業務代碼存在以下問題

  1. bean 的創建太隨意,基本就是一個需求一些對應的 dto,vo,query bean。

  2. 不同開發者對於同一個領域的東西有不同的 bean,同一個開發者對於相同邏輯的 bean,在經過 2 月 + 的時間,自己又定義出了一個差不多的 bean -> 職責分散

  3. 不同開發者對於某塊相同業務的邏輯校驗放在了不同的 service 中 -> 代碼邏輯重複

  4. 不同的後端 / 前端對接時,相同概念的命名存在差異,導致後面重構時數據訪問沉澱到 manager 層,上層調用的時候處理 case 有問題

  5. DTO 類型的 bean 重構過程中根本不知道哪些是可以爲 Null,哪些不可以 根本沒有上下文 / 邊界的概念,比如說模塊 A 會和模塊 B 有交互,模塊 C 會和模塊 B 有交互,通常在 DB 存儲時只會存關聯 id,然後需要去取對應的名稱,其他屬性信息。 這些信息的獲取,有些開發在 manager 層操作,然後將屬性定義到了模塊 A 相關的 DTO 中,有些放在了 service 層做,對於模塊 B 的有效性校驗,也是在不同的 service 中

二. 工程架構圖演進

現狀

目前的系統結構圖通常下面這樣

  1. 四層 controller/service/manager/mapper

  2. 不可以同級調用

  3. 上級可以知曉下級,下級不可知曉上級,也就是 bean 的轉化放在上級

這個分層結構和領域模型對應一下就會發現有些問題

  1. 資源服務層 repository 是面向 DB 編程

  2. service 層是面向前端頁面編程。

這樣對於某一塊的業務,還是沒有將邏輯抽象到一起, 也就不可避免的邏輯冗餘

改進

  1. service 層只能調用自己領域的 manager

  2. 增加一層 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