29

我在軟件開發方面非常新穎。就我個人而言,我認爲分層體系結構是減少面向對象方法在軟件開發過程中產生的複雜性的一種好方法,更不用說保持代碼的組織性。現在,我遇到了DDD(域驅動設計)引入的一些問題。當然,初學者水平。
這裏是 -
假設我想構建一個應用程序來保存數據庫中的「人員」相關數據,並在wpf數據網格中顯示個人詳細信息(DDD絕對不適用於這種規模的應用程序,而只是爲了保持對於像我這樣的業餘愛好者來說很簡單)。所以,我設計了一個域類「人」,有點像 -DDD:應該如何組織圖層?

public class Person 
{ 
    public Person(dataType paramA, dataType paramB) 
    { 
     _fieldA = paramA; 
     _fieldB = paramB; 
    } 

    private dataType _fieldA; 
    public dataType PropertyA 
    { 
     //encapsulates _fieldA  
    } 

    private dataType _fieldB; 
    public dataType PropertyB 
    {   
     //encapsulates _fieldB  
    } 

    public dataType PropertyX 
    {   
     //some code based on private fields  
    } 

    public dataType PropertyY 
    {   
     //some code based on private fields  
    } 

    private dataType MethodPQR(dataType param) 
    {   
     //some code  
    } 

    public dataType MethodUVW(dataType paramOne, dataType paramTwo) 
    {   
     //some code  
    } 
} 

現在,我的DDD的理解說的架構(它的最簡單的版本)應該是如下(請糾正我,如果我錯誤) -
enter image description here
注:

  1. 我想將DataGrid綁定到一些的ObservableCollection,只是即時反映任何樣的變化。

  2. 這是一個WPF應用程序,但不一定是在MVVM模式,我故意要這樣使用後面的代碼(我也不知道,如果自己後面的代碼代表了應用層)

我問題是 -

  1. 什麼樣的代碼應該屬於應用層?

  2. 我的猜測是,我絕對不應該將我的域對象(Person)的ObservableColletion綁定爲datagrid的itmsSource。然後我應該從域對象中提取什麼類型的對象,以及如何?

  3. 爲了保持表示層對象和域層對象之間的解耦,可能會出現像「never instantiate domain objects directly in presentation layer」這樣的約定。那麼什麼是非直接的方法?

  4. 如果Code-Behind與應用層對話,那麼應用層是否應該與Repository進行通信?但是,如果需要某種類型的域訪問,而不是而不是數據訪問相關(可能不在此應用中,但可能會發生,對嗎?)誰是應用層應該與之通信的域層中的X人?

我知道我所有的問題和問題都非常非常業餘水平。但他們確實是問題和問題。所以,如果有人有時間,任何迴應將不勝感激。

編輯:我不確定數據存儲庫是否應該有一個域模型的參考。

回答

32

就更多的「經典」DDD而言,yes域對象通常不允許在域以外的任何地方使用。但是,在表示層中不使用域對象是絕對的規則。例如,裸體對象代表了直接使用域對象的學派。我自己主要是堅持域對象不直接使用的哲學,所以我不熟悉他們所建議的所有做法,我個人會認爲直接綁定到域對象會被建議,但是......請記住並不是每個人都認爲這是一個要求。

如果你不允許域本身之外的領域對象,你通常使用的是沒有域的行爲簡單的屬性只有類DTO或數據傳輸對象。 DTO經常反映域模型結構,但不一定。

業務邏輯應該在領域模型中實現,那麼多的東西是在應用層是參與協調各種服務,通常帶來的數據和從客戶端應用程序。許多人爲此使用某種形式的SOA或至少Web服務。這些調用存儲庫,但也要求其他組件(如彙編程序)從存儲庫調用中返回域對象,並將屬性值複製到DTO中,然後將其序列化並返回給調用者。調用者通常是演示者或控制器,但如果您未使用MVC或MVP,調用者仍將處於表示層中。反向行程更復雜 - 用戶界面可能會發回表示更新的DTO或表示要添加的新對象的DTO。調解這些來回活動主要是應用程序層的目的。

就域層的「非數據訪問」而言,有幾個典型的例子。大多數人通常會將您可能認爲是「域服務」的「X」組件稱爲「X」組件。域服務與應用程序服務的區別在於它靠近域模型以及存在實際的業務邏輯。

例如,如果一個應用程序涉及到某種順序放置的,其實有兩個問題 - 下訂單和訂單履行。應用程序服務調解將訂單放置到UI中所需的數據傳輸,然後返回用戶希望放置的訂單。但這只是調解數據傳輸,這就是應用程序服務結束的地方。然後可能需要域服務來應用業務規則並構建實際完成該訂單所需的額外域對象。

一般來說,我發現這是一個有用的概念或隱喻,可以應用於許多場景 - 應用服務僅根據請求提交方便某種請求。另一方面,域服務便於實際請求履行

「獲取」唯一的其他模式以外面向數據我所遇到的或可容易地想象是面向過程的功能。這在每個應用程序中都沒有遇到,但在某些領域普遍存在。例如,在我工作的醫療保健領域,您可能需要包含管理臨牀數據和臨牀過程的重要元素的應用程序。我解決這個問題的方式不是將該流程強調作爲我的領域模型的一部分,而是使用不同的工具。

OOP技術是不適合於實際的過程本身,它們用於從工藝提供數據和捕獲數據是有用的。面向對象畢竟也主要是名詞導向的。對於實時流程管理,您需要「面向動詞的編程」而不是「面向名詞的編程」。工作流程工具是「面向動詞」的工具,可以作爲數據密集型和流程密集型應用程序的域驅動模型的補充。我做了很多涉及C#DDD模型和Workflow Foundation模型的工作,但這只是對於某些類型的應用程序而言。許多典型的商業應用程序只需要域模型和服務。

最後,DDD最重要的方面不是任何技術或體系結構。它的真正核心是圍繞無處不在的語言和與領域專家之間的互動(在我強烈的意見DIRECT互動中)來提煉關鍵領域知識。 (在我看來,大多數聲稱做DDD的公司並不是因爲這麼多公司拒絕讓業務和開發直接互動,而是另一個話題......)這是領域知識的提取和合並,而不是任何這種技術實際上將DDD從傳統的OOP中分離出來,這就是DDD的實際價值所在。

編輯

由於作爲倉庫使用走得遠,該圖是正確的。通常,應用程序層始終通過域對象的存儲庫。首先,您必須能夠將數據帶入應用程序,並且大多數應用程序也需要一定程度的查詢能力。

域OTOH通常做而不是與存儲庫交互。通常情況下,您希望域模型與任何特定技術自成一體並解耦,即它應該表示「純領域知識」。持久性本質上與某種特定技術密切相關,所以通常人們會努力使自己的領域模型不受任何持久性實現的影響。您有存儲庫,但通常不想在域模型中調用存儲庫方法。

在域模型本身中,對象可以作爲新對象(可以直接實例化或通過工廠實例化)獲得,也可以通過遍歷關聯達到。有時,在創建新對象時,將所需的所有內容都傳遞給構造函數是不切實際的,因此,您可能需要在域模型本身中進行某種數據訪問。通常人們所做的是通過接口傳遞數據服務,這樣域模型可以提供數據訪問,但仍與數據層實現解耦。但是大部分域對象都起作用並與已經實例化的其他域對象進行交互。

+0

@Sisyphus:現在+1,清潔和詳細的描述,以及你的時間來開導我。但是,更多的問題會來到你的方式:) – atiyar 2011-05-06 18:09:11

+0

@Sisyphus:再次感謝。你的建議很整潔,應用程序服務和域服務之間的區別非常有幫助。還有一個問題。應用層是否可以直接訪問存儲庫,或者它總是通過域層?我的意思是,幾乎總是,每個請求**履行**執行某種域限制(驗證可能)檢查任何請求**提交**,對不對?那麼應用層不應該向域層提交每個請求,只有域層可以訪問存儲庫? – atiyar 2011-05-07 20:07:45

+1

因爲意見是有限的,我添加到我的答案。見編輯部分。 – Sisyphus 2011-05-08 10:51:27