基於DDD項目的設計總結

一、爲什麼要使用領域模型
• 有助於團隊創建一個業務部門與IT部門都能理解的通用模型,並用該模型來溝通業務需求、數據實體、過程模型。
• 模型是模塊化、可擴展、易於維護的,同時設計還反映了業務模型。
• 提高了業務領域對象的可重用性和可測性。
二、領域的分層架構
在Eric Evans《領域驅動設計--軟件核心複雜性應對之道》中對領域的分層架構如下:
[img]/upload/attachment/85785/3ac63432-9d97-397c-807c-e198a8fd7686.jpg[/img]
• 用戶界面(表現層):負責給用戶展示信息,並解釋用戶命令。
• 應用層:該層協調應用程序的活動。不包括任何業務邏輯,不保存業務對象的狀態,但能保存應用程序任務過程的狀態。
• 領域層:這一層包括業務領域的信息。業務對象的狀態在這裏保存。業務對象的持久化和它們的狀態可能會委託給基礎設施層。
• 基礎設施層:對其它層來說,這一層是一個支持性的庫。它提供層之間的信息傳遞,實現業務對象的持久化,包含對用戶界面層的支持性庫等。
三、如何創建領域模型
• 尋找概念類
• 將其繪製爲UML類圖中的類
• 添加關聯和屬性
四、領域模型的開發步驟
• 對領域進行建模
• 設計
• 開發
• 單元測試和集成測試
• 基於設計和開發來完善、重構領域模型
• 使用更新的領域模型重複上述步驟
五、實際項目設計
1、層次結構:
[img]/upload/attachment/85789/bc2c3329-75cc-3856-8a0a-1dc5c736a882.jpg[/img]
2、層次之間的交互
A、頁面提交表單數據到Action,Action創建DTO對象並設置相應屬性值爲表單數據
B、Action傳遞DTO對象給Facade
C、Facade中套用ServiceTemplate事務模板以加入事務管理,在ServiceTemplate中根據具體業務調用Factory或Reposistory,分別create或者load出DomainModel對象
D、Facade傳遞DomainModel對象給Service
E、Service執行具體業務邏輯(調用DomainModel對象相應的業務方法)
F、Service調用Reposistory對狀態已改變的DomainModel對象進行持久化操作(調用相應DAO)
注:
在Facade或Service中如果需要查詢DomainModel對象中的屬性值,調用DomainModel對象的getDataInfo()方法得到DataInfo對象,通過DataInfo對象查詢所需數據,包括Service返回給Façade業務處理結果中所包含的業務數據。
3、對於DomainModel的設計
DomainModel基於貧血模型來設計。在Robbin《總結一下最近關於domain object以及相關的討論》一文對於貧血模型領域的切分原則寫到:
[quote]Rod Johnson提出原則是“case by case”,可重用度高的,和domain object狀態密切關聯的放在Item中,可重用度低的,和domain object狀態沒有密切關聯的放在ItemManager中。
我提出的原則是:看業務方法是否顯式的依賴持久化。[/quote]
在該項目中DomainModel內的業務邏輯方法沒有任何對DAO接口的依賴,如果需要對DomainModel進行持久化操作全部由Service調用Reposistory的store()方法進行處理,對DomainModel的持久化操作已全部封裝於Reposistory中。DomainModel只提供改變自身狀態的業務處理方法。
4、對DomainModel的訪問原則
A、必須從領域模型的根部操作模型的各個屬性
例如一個領域模型結構如下:

public class PersonDomainModel {
Person person;
Bank bank;

public void modifyPerson(String name, String age) {
this.person.setName(name);
this.person.setAge(age);
}
}

操作該領域模型的person屬性只能通過modifyPerson()方法進行,而不能直接調用person對象的setter方法。
B、必須保持領域模型的完整性。最初由Factory構造一個模型的時候,就必須將其進行完整的初始化,而不是隻構造一部分,然後在接下來的處理過程中逐步完善。
5、Factory和Reposistory的職責
Factory只負責領域模型對象的創建(從無到有);
Reposistory對持久化進行了封裝,它操作的是已存在的領域模型對象(從數據庫中讀取數據or重新持久化到數據庫)
6、項目待優化部分
在Service調用Reposistory的store()方法進行持久化操作時,如果某個業務僅對DomainModel的一部分屬性進行了修改,在持久化到數據庫中時仍然會將DomainModel的所有屬性全部進行一次update操作。這樣的數據庫操作沒有必要,只需對DomianModel中修改過的屬性進行持久化操作即可。可以考慮在DomainModel上提供一個類似保存所有修改屬性的列表,在Reposistory持久化時僅對該列表中的修改屬性進行操作。

參考資料:
1、Eric Evans《領域驅動設計--軟件核心複雜性應對之道》
2、Robbin《總結一下最近關於domain object以及相關的討論》http://www.iteye.com/topic/11712
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章