短知識:豐富你的領域(實體)對象

該文章主要介紹自己根據對領域驅動設計的理解結合開發實際而賦予領域對象更多的實際行為,而不僅僅是作為一個簡單的數據載體而存在。

DO(Domain Object)優化

在貧血模型裡,領域對象一般只作為數據載體而存在,只有get和set方法,這也導致一些簡單的業務邏輯重複出現在多個地方,如僅把對象裡的值提出來去處理判斷,但這些行為放到對象中可以更加豐富DO的行為,增加代碼可讀性,下面以一個優化對象作為數據載體與賦予簡單邏輯後的操作對比為例。

  • 作為數據載體的領域對象
@Data
@Accessors(chain = true)
public class Discount {
private Long id;
/**
* 狀態(0-禁用,1-可用,2-過期) {@link DiscountConstant.Status}
*/
private Integer status;
/**
* 類型(1-折扣,2-優惠券) {@link DiscountConstant.Type}
*/
private Integer type;
/**
* 折扣/優惠券價
*/
private Integer value;
}

當需要進行一些邏輯處理,如返回優惠信息,判斷狀態等,可能就會在多處出現以下的代碼塊:

短知識:豐富你的領域(實體)對象

  • 賦予邏輯的領域對象
短知識:豐富你的領域(實體)對象

當要獲取優惠信息時,如果返回頁面的是Discount這個對象時,則無需任何處理了,getDiscountMsg方法會返回discountMsg信息;當作為邏輯處理獲取信息時,也可以調用discountMsg而無需重複寫類型判斷與字符串拼接。進行狀態判斷時,使用領域對象裡的方法進行判斷更具有可讀性:

if(discount.isStatusEquals(status)){
// do something
}

當然常量值較少時也可以使用isEnabled()判斷對象狀態是否為可用,但當常量值過多時會使對象過於臃腫。

VO(Value Object)優化

值對象在Web應用層中一般表示為表現層(前端)的對象,與DDD中的值對象有所不同。前端進行VO傳參時,VO也可進行類似DO的優化,如複雜參數的校驗,對象的轉換,對象轉換例子:

短知識:豐富你的領域(實體)對象

引申領域模型

  • 貧血模型:領域對象(DO)裡沒有業務邏輯,只含簡單而的數據操作方法(如get、set、toString),從業務層面上看僅僅是一個數據載體在業務與存儲介質之間進行傳輸的數據載體
  • 充血模型:領域對象裡擁有自己的狀態與行為,大多業務邏輯和持久化放在DO裡,業務邏輯層只是簡單封裝部分業務邏輯以及控制事務等

貧血模型與充血模型應用分層差別不大,主要區別在於邏輯的處理,如下圖(左圖參考自《領域驅動設計:軟件核心複雜性應對之道》,右圖參考自《阿里巴巴Java開發手冊》):

短知識:豐富你的領域(實體)對象

結合實際

充血模型對開發人員的業務瞭解要求較高,需要開發人員清楚的認知業務劃分,什麼需要放到service層,什麼需要放到DO層,且DO中還包含DAO進行數據持久化(依賴倒置原則),這對開發人員來說十分混亂。但在實際開發中,並不一定必須按照死規則去編寫代碼,可以借鑑充血模型的邏輯處理,靈活開發,為貧血模型中的領域對象賦予數據對象一定的邏輯,提高代碼的複用性、可讀性。


分享到:


相關文章: