領域建模實現思考

領域建模實現思考

“Javaeye論壇-領域建模”板塊有很多討論,不再引述,直接列舉我的觀點。

JavaEE中領域建模的困境包括:
1) 類膨脹。 需要職責理順,分散和委託出去。
2) 無法擺脫Entity的Domain Service注入?

思路:
1. 目前的 Service 模式是一種組件化的,形式上是 OO 的,實質上是組件的,它能很好的解決現有問題。 但忽視了領域對象之前的天然關聯性。

2. 領域模型特徵: 普遍共識一般是Domain Object要求“ 數據 + 行爲 ”的完整封裝,對象實例的行爲基於自己的數據,對象之間存在數據關聯(Data Association)和行爲關聯(Behavior Association)。此外領域對象還能響應事件。
一個應用的領域對象依據其相互關聯,可由一個根對象(Root Model) 導航獲取到任何一個的Domain Object。

因此一個完整的領域模型可以抽象爲:
Domain Model = Data + Association + Behavior + Event

3. 恰當平衡領域建模思想和實踐的衝突。
第一個問題:如類膨脹,就是談的很多的充血問題。隨着系統發展,一個Domain Object要承擔的Behavior增多,代碼中的Method增多,導致文件龐大。 這更主要是一個實現階段的問題,但不能不認真考慮。

解決充血肯定要反向思考,即給對象“放血”。將行爲分散,實現角度需要增加Behavior類或接口,協同構建Domain Model。

Qi4j 框架基本實現了這一點,Domain Object設計和方法定義完全靠 Interface 和 Interface繼承; 方法實現類爲Mixin,只關注它要實現的Interface,子類爲Composite模式,實現了很好的放血和分散。
如:
Domain Object 定義
public interface Speaker
{
String sayHello();
}


方法實現
public class SpeakerMixin
implements Speaker
{
public String sayHello()
{
return "Hello, World!";
}
}


子類(應該說是接口)定義
@Mixins( SpeakerMixin.class )
public interface PoliticianComposite extends Composite, Speaker // +others
{
}


但Qi4j 還有Concern等很多概念,看它的範例代碼,感覺巨複雜,大量用了Annotation,不很喜歡。

3) 領域建模對使用者(程序員)要簡單,友好。
現有框架太多的EJB,Service,DAO等框架要求的類,分層清晰,但導致代碼增多,開發量和使用難度增加。當然,因爲這種架構設計的清晰,規範性,在實踐中獲得了很大成功,功勞不可忽視。
新一代的開發框架,如果要面向“領域驅動設計”,需要將 Service,DAO,VO等概念進行融合,實現Data 和Behavior的重新聚合,而且Behavior不管它是原子性的CRUD,還是粗粒度的Business Method。

4) 類設計思路1:Behavior類繼承 Data 類,這樣使用者面對的是數據和Behavior統一的對象實例;
5) 類設計思路2:Domain Object恰當劃分Sub Domain, 避免Behavior膨脹。

6) 類設計思路3:1關聯的對象( order.customer ) 既有數據,又有Behavior,不存在什麼問題,Hibernate等已經很好支持; 但N關聯的對象( 如:user.orders ) 是一個集合(Collection)仍是以Data Model爲中心;需要變爲以“Behavior + Data Model”爲中心,重點在Behavior;需要一個集合對Element成員有CRUD操作, 特別是更業務性的操作。


7) 跨環境( Context )問題。
一個Domain Object 在一個系統的不同子系統,不同領域有不同的Data Model和Behavior,因此對Domain Object需要按Context 進行關注。
一個基類如Person如果在不同Context有不同的表現,Manager,Employee,Sale,Clerk等,就需要按各自 Context 設計,而不能單線繼承的設計。

思考的編程模型:

Category extends CategoryDO {
void deleteProduct(String productId);
}

Category category = Categorys.find("sss");
category.getId();

category.deleteProduct("xxxx");

category.getProducts().delete("sss");

category.getProducts().add("ddddd");

category.getProducts().query("xxxx");


[參考資料]
1. Robbin domain model的延伸討論 http://www.iteye.com/topic/57075
2. Taowen 貧血的Domain Model http://www.iteye.com/topic/191261
3. Taowen 再論領域模型的困境 http://www.iteye.com/topic/401223
4. Lifethinker 一個簡單例子:貧血模型or領域模型 http://www.iteye.com/topic/283668
5. javaboy2006 基於DDD項目的設計總結 http://www.iteye.com/topic/351597
發佈了15 篇原創文章 · 獲贊 0 · 訪問量 2638
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章