[Architecture] 累進式Domain Layer

摘要:[Architecture Design] 累進式Domain Layer

[Architecture Design] 累進式Domain Layer

前言

本篇的內容大幅度的簡化了分析設計、物件導向等等相關知識,用以傳達累進式Domain Layer的核心概念。實際開發軟體專案時,建議還是採用DDD、TDD等等系統化方式來分析設計系統內容。

問題情景

軟體專案套用三層式架構,可以將程式碼分門別類提供系統化的整理歸類。

問題情景01

理論上,分析設計Domain Layer的時候,應該要從領域層的角度切入,去分析設計領域層的組成結構。但實作上,人類的思考慣性常常會帶著開發人員使用Presentation Layer的角度,去分析設計Domain Layer的組成結構。例如:下列的商城系統,包含了購物車、商品查詢這兩個使用案例。

問題情景02

購物車這個使用案例,提供一個頁面讓使用者可以查詢購物車購物清單,點擊清單項目可以看到商品內容。依照頁面的需求,開發人員可能會建立一個ShoppingCartService類別來提供領域層的服務,這個類別包含了兩個方法:查詢購物清單(GetAllPurchase)、取得商品內容(GetProductDetail)。

問題情景03

商品查詢這個使用案例,提供一個頁面讓使用者可以商品編號來查詢商品,並將查詢到的商品內容顯示在頁面上。依照頁面的需求,開發人員可能會建立一個ProductQueryService類別來提供領域層的服務,這個類別只包含了一個方法:取得商品內容(GetProductDetail)。

問題情景04

經由實作上面兩個使用案例,可以在領域層內建立ShoppingCartService、ProductQueryService兩個類別。但是仔細檢視兩個類別的方法,會發現GetProductDetail這個方法重覆了。這時有經驗的開發人員,就會精煉領層將共用的方法抽取出來,建立為一個共用的ProductCommonService類別,用以避免不必要的程式碼重覆。

問題情景05

到目前為止,看起來軟體架構一切正常,服務可以不停地依照系統需求被擴展,需要什麼頁面就在領域層擴展出對應的服務,並且從中不停精煉出共用服務。但是上述這個軟體開發架構,其實僅適用於開發人數較少的開發團隊;如果將開發情景拉高到多人共同開發的情景,會發現要從系統中精煉出共用服務,必須要有個人不停審核每個成員產出的服務,才能分析出共用的方法,接著在領域層中建立共用的服務。先不提一般開發團隊是否擁有這樣的人力配置,光是想想這個人員要審核所有的服務、並且發覺重覆的程式碼,這個工作量就讓人覺得頭皮發麻,甚至可以說這是個不可能的任務。

問題情景06

解決方案

為了解決上述問題情景所會造成的問題,在軟體開發架構設計的時候,就需要先設計好Domain Layer,讓領域層擁有「累進程式碼」的能力。

以同樣的商城系統,包含了購物車、商品查詢這兩個使用案例來說,可以先由軟體架構師,定義Domain Layer該擁有甚麼樣的基礎類別(ShoppingCartService、ProductService),這些基礎類別一開始的時候不包含任何方法,只定義了這些基礎類別的職責範圍。(EX:ShoppingCartService負責購物車相關邏輯、ProductService負責商品相關邏輯)

解決方案01

實做購物車這個使用案例的開發人員,依照頁面的需求會需要建立兩個方法:查詢購物清單(GetAllPurchase)、取得商品內容(GetProductDetail)。這時可以依照基礎類別的職責範圍,將GetAllPurchase散落到ShoppingCartService類別、將GetProductDetail散落到ProductService類別。再由購物車頁面去使用這兩個類別的方法,就可以完成使用案例的需求。

解決方案02

實做商品查詢這個使用案例的開發人員,依照頁面的需求會需要建立一個方法:取得商品內容(GetProductDetail)。這時可以依照基礎類別的職責範圍,將GetProductDetail散落到ProductService類別,但是馬上會發現GetProductDetail方法在先前實作購物車使用情景的時候,已經被實做完成。那開發人員就可以很輕鬆的直接使用ProductService類別上的GetProductDetail方法,來完成商品查詢的使用案例需求。

解決方案03

透過上述步驟,就能不停增加Domain Layer中各種基礎類別的方法。而在基礎類別的職責範圍不足以覆蓋專案範圍的時候,也可以繼續增加基礎類別項目來覆蓋更多職責範圍。透過這樣不斷累進的方式,最終就能在Domain Layer中完整封裝軟體專案背後的領域知識。後續遇到新的使用案例,只要組合調用已經封裝好的類別與方法,就能快速滿足使用案例的開發需求。

解決方案04

後記

以DDD的角度去看,Entity、Service、Repository等等領域物件的定義,都可以拿來做為Domain Layer累積程式碼的基礎類別,系統所以要提供的各種方法都可以散落在這些領域物件之上。DDD的相關分析設計資料可以參考:

期許自己
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。