1. 分層封裝
在大多數應用中我們都是將代碼分層封裝(如Clean架構),如下:
com.awesome.project
.common
StringUtils
ExceptionUtils
.controllers
LocationController
PricingController
.domain
Address
Cost
CostFactory
Location
Price
.repositories
LocationRepository
PriceRepository
.services
LocationService
分層封裝比較流行的原因可能是開發人員能夠很容易發現功能相似的代碼,同時也符合人們“習慣於對事物進行分類”的思想,但是分層封裝會帶來如下問題:
-
添加或修改業務時需要跨多層修改代碼
-
在某一層中封裝的代碼通常是不相關的(如LocationRepository和PriceRepository)
-
不同的開發人員對不同的代碼層應該包含的功能有不同的認知,因此需要時間統一大家的認知,對新人需要進行統一的培訓
-
把某一個domain提取成單獨的微服務並不容易
-
更多的分層意味着更高的複雜性
-
開發人員需要時間來思考代碼應該放到哪個分層
-
隨着業務越來越複雜和對架構缺少守護,分層架構會越來越腐化,遠遠偏離最初的架構設計
2. 按特性(或domain)封裝
考慮到分層分裝的問題,我們可以按特性或domain對代碼進行封裝,比如:
com.awesome.project.component
.location
Address
Location
LocationController
LocationRepository
LocationService
.platform
StringUtils
ExceptionUtils
.price
Cost
CostFactory
Distance
Price
PriceController
PriceRepository
這種結構化代碼的方更符合OO原則,可以做到業務高內聚,不僅能夠解決分層封裝代碼的問題,同時具有如下優勢:
-
開發人員更聚焦於業務,而不至於花時間如何組織我們的代碼
-
從DDD的角度出發,開發人員可以很容易的找到某一個domain下的聚合根,比如price包中的Price類肯定是聚合根,因爲我們可以通過PriceRepository直接獲得Price,而Cost很可能被Price使用,因爲我們無法直接獲得它
使用這種封裝方式要解決的首要問題是:**應用業務規則往往是由多個領域的業務規則組合完成的,在哪裏完成這些領域業務規則的組合呢?**不同的開發人員可能有不同的解決方法,比如將Controller提出到單獨一個層:
com.awesome.project
.controller
LocationController
PriceController
.component
.location
Address
Location
LocationRepository
LocationService
.platform
StringUtils
ExceptionUtils
.price
Cost
CostFactory
Distance
Price
PriceRepository