2012-01-26 39 views
1

我今天閱讀this文章,並試圖澄清一些事情。這篇文章是否意味着模型對象應該包含業務邏輯? 例如,讓我們說有一個Student對象,我們通過Hibernate從數據庫中檢索。這篇文章是否說學生對象應該包含業務邏輯,而不是隻有getter和setter?AnemicDomainModel - 需要更簡單的解釋

+2

基本上是這樣。如果您有與域實體相關的複雜行爲邏輯,Fowler說您應該將其全部組織在域模型中。 –

回答

6

無視日期,馬丁福勒說,今天和八年前一樣重要。 Fowler沒有說明你應該將持久性混合到域對象中,恰恰相反:

「還值得強調的是,將行爲放入域對象不應該與使用分層將域邏輯與此類事物分開的可靠方法相抵觸作爲持久性和陳述責任。「

你應該再次閱讀文章,因爲文章描述了這種反模式extermely好,但我會試着總結一下你在的情況下你都在問:如果你是創建一個

域模型,是的,您的域對象應該包含業務邏輯和狀態,並且應該通過傳達業務含義的方法來更改域實體的狀態。貧血領域模型是一種反模式,因爲您承擔額外一層課程的成本,但是您沒有收穫好處。爲什麼要打擾一個域圖層,當它傳達與使用活動記錄樣式方法(數據集等)相同的意圖時,您必須映射數據庫?所以這篇文章並沒有說你應該有一個「學生對象」,但是它表明如果你這樣做,你應該明確地爲這個班級添加狀態。

由於當前技術的可用性,如果您還沒有對域進行建模,那麼關於沒有一組對象來表示您的模型的文章中的要點可能會有點混亂。有很好的工具可以毫不費力地在一組POCO和數據庫之間移動數據(Nhibernate,EF,Simple Data,Massive,Dapper等),所以在回顧中我會說你最終可能會得到一組現在大多數解決方案中的「實體」,真正的區別在於這只是一個數據庫模型還是一個真正的領域模型。

我將通過向您展示域入口點(命令處理程序)和域模型之間的交互示例來關閉它。下面顯示的方法位於命令處理程序中,該處理程序使用請求來更改域中的某些內容。請注意,域上的層上代碼只需獲取域實體並在域上調用一個方法?那是一個很重要的一點,因爲我們的建模工作流程域中完全封裝,而不是在層ontop的 - 的 - 你的域代碼或其他任何地方:

public void Handle(AddEmailAddressForAlerts command) 
    { 
     var agent = _repository.GetAgent(command.AgentKey.AgentId); 
     agent.AddEmailAddressForAlerts(new EmailAddress(command.EmailAddress)); 
    } 
+0

人們通常會將領域模型與實體混淆在一起,因此我們應該一直問 - 我們是否應該將所有領域邏輯放入領域模型(抽象整個業務邏輯) - 是的!我們是否應該將所有的域邏輯放入實體 - 不!有域名服務等。 –

1

注意日期 - 引用已超過八年。

馬丁福勒顯然是一個非常聰明的傢伙,我喜歡這篇文章的觀點,但帶着一粒鹽。總體來說,將狀態和行爲封裝在一起是一件好事,但它應該與分層考慮進行平衡。持久性與業務邏輯不同。我仍然有一個單獨的持久層;我不會把持久化放在模型對象中。

教條應該受到各種形式的挑戰。注意別人的想法,但要爲自己思考。

+0

感謝您的回答。你說過「我不會把持久化放在模型對象中」。但是你會將業務邏輯放在模型對象中嗎? –

+0

這不是一個是或否的答案。我會封裝使用我的組件更容易使用的東西。面向服務的體系結構往往功能更強大,而且沒有任何問題。 – duffymo