N 層開發中的 DDD 概念
在花了幾個月的時間研究 DDD 方法之後,我現在開始將這些概念應用到我公司的實際產品中。事實上,我的任務是為未來的開發創建一個合適且可維護的架構。
我們決定使用以下技術:EF4(真正的 v2)、Unity
我獲得的資訊量最有啟發性,但是,在最佳實踐中我還有幾個問題:
問題 #1: DTO - 最佳實踐
我有我的域對象(POCO 類)。有幾種方法可以實現這些類。
- 傳統方法:創建包含公共 getter/setter、驗證和適當業務邏輯的 POCO 類。還可以創建 DTO 並使用映射技術來管理它們。(自動映射器)
- 傳統 - DTO:創建如上所述的 POCO 類,但是,使用您的 POCO 作為傳輸對象。我的理解是業務對象永遠不應該離開域。
- Hybrid:我偶然發現了一篇有趣的部落格文章,其中作者創建了他的 POCO 對象和 DTO。在他的領域對像中,他創建了一個 DTO 實例。這使得可維護性更容易,因為您不會像 #1 那樣複製您的屬性。像這樣:
公共抽像類 POCOBase<T> : ValidationBase, IPOCO 其中 T : DTOBase, new() { 公共 T 數據 { 獲取;放; } 公共 POCOBase() { 數據 = 新 T(); } 公共 POCOBase(T dto) { 數據 = dto; } } 公共類 SomePOCO : POCOBase { } 公共類 SomeDTO : DTOBase { 公共字元串名稱 { 獲取;放; } 公共字元串描述{get; 放; } 公共布爾 IsEnabled { 獲取;放; } } // 例子 // POCOBase<SomeDTO> somePOCO = new SomePOCO(); // somePOCO.Data.Name = "blablabla"; // somePOCO.Validate(); // 返回一些POCO.Data;問題 #2: UI/服務層應該返回哪些對象?
這就是 DTO 的重點。一個非常簡單的輕量級對象,僅包含裸屬性。它也不包含任何驗證結果。如果我將我的 DTO 序列化回客戶端,則應假定客戶端需要任何驗證結果,例如 InvalidRules 集合。
例如,假設我正在使用亞馬遜的 API。我想在我的個人商店中添加一本書。如果我嘗試在不發送 ISBN 的情況下添加一本書,該服務可能會返回某種包含驗證結果錯誤的響應組。
我錯過了什麼嗎?我的印象(至少來自 DDD “純粹主義者”)認為 DTO 不應該包含業務邏輯。在我看來,DTO 沒有提供足夠的資訊作為傳輸對象。要麼,要麼我需要一種封裝 DTO 和驗證結果的新型 Response 對象。
問題 3: 多少 IoC 太多了?
在我看來,我應該遵循黃金法則:
“辨識應用程序中不同的部分,並與那些保持不變的部分分開。”
對我來說,這在應用 IoC 方面是有道理的。為了減少依賴,我的表示層、業務邏輯層和數據訪問層都通過 IoC 容器進行通信。我的應用層包含通用介面和抽象。比這更多地使用 IoC 似乎有點矯枉過正。我喜歡我可以創建模擬測試儲存庫這一事實 - 只需更改 Unity 的配置,我就可以使用 TDD。
我希望我已經清楚地說明了這些問題。提前感謝您的幫助!
我將嘗試一次解決您的問題。
答案 1
DTO 與 DDD 正交,因為它們在應用程序架構的不同位置服務於不同的目的。也就是說,DTO 在域模型中沒有位置,因為它們沒有行為,因此會導致貧血域模型。
具有持久性無知的 POCO 是要走的路。Jeremy Miller 有一篇很好的文章解釋了這個概念。
答案 2
位於域模型之上的層通常需要返回為相關目的量身定制的自己的對象。
對於 UI,MVVM 模式效果特別好。本文介紹了用於 WPF 的 MVVM,但該模式在 ASP.NET MVC 中也很有魅力。
對於 Web 服務,這就是 DTO 模式適用的地方。WCF 數據契約是 DTO,以防您想知道 :)
這將需要在服務介面和領域模型之間來回進行大量映射,但這就是您必須為 Supple Design 付出的代價。您可能會發現AutoMapper在這方面很有幫助。
答案 3
IoC(真的:DI)越多越好,但是關於您的問題的一件事讓我印象深刻:DI 容器應該只連接對像圖,然後讓開。對像不應依賴 DI 容器。
有關更多詳細資訊,請參閱此 SO 答案。