2011-04-06 72 views
10

我試圖使從數據中心設計和開發跳入DDD和已經閱讀埃文斯和Nillson但我仍然有麻煩纏繞我的頭左右,我應該如何構建我的領域層。我敢肯定,我目前的項目的性質沒有幫助!真實世界DDD:構建領域層

一點背景

的應用程序是一個內部解決方案來管理人員評估。人力資源人員將創建評估「模板」,其中包含一系列由團隊領導和管理人員爲其每個直接報告完成的問題。答案是堅持審計和審查。這些評估可以爲各種各樣的東西,如對公司的舉措,績效評估反饋等

我的數據中心側

不影響解決方案,但強調我的數據中心心態,我已經爲數據庫架構願景,幷包括在這裏僅供參考(因爲一張圖片勝過千言萬語):

enter image description here

的模式是,正如所預料的,標準化的和不匹配如何數據在我的應用程序中處理。而且,我忽略了查找表等,試圖將問題保持在最低限度。

的用例

第一使用情況是檢索和顯示,用戶需要完成的評估的列表。這將在用戶首次登錄應用程序時顯示,起初它似乎相對容易,但有兩個摺痕:1 - 評估是基於時間的,因此可能需要每月,每年或每'x'基於員工週年日期的年數;並且,2 - 用戶可以保存正在進行的評估並稍後完成評估。因此,清單應包含到期的評估以及任何正在進行的評估。

接下來,當用戶選擇要執行的評估時,我需要檢索該評估的所有問題(當前版本),以便我可以將它們顯示給用戶。在評估過程中的任何時候,用戶都可以保存當前結果。只有在整個評估完成後,纔可能實際「提交」或承諾。

第三,人力資源需要一種方法來重新生成評估與監督員提供的迴應。

最後,HR能夠創建和修改評估 - 他們的版本。因此,無論何時修改某個評估,都會創建一個新版本,並且該版本將成爲執行任何NEW評估的模板(任何正在進行的評估都將繼續使用其原始模板)。

領域模型

工作無序,這對我來說很有意義,我將有一個是聚合根,以滿足第四使用情況的評估實體。它將有一個子實體的子集合,該子實體又將有一個子實體集合。他們都是實體,因爲他們有身份(是的?)。評估是消費代碼用於持久性,驗證等的對象(儘管Section和Question實體自我驗證並將狀態彙總到根評估)。我的目標是從消費者那裏做出版本摘要,並在數據持久層中實現它(好的或壞的想法?)

這意味着我還將有一個AssessmentRepository來處理對我的持久性,可能還有一個AssessmentFactory在需要時創建一個新的評估。

更大的問題出現在其他用例中。我是否也有EmployeeAssessment聚合根?還是僅僅是一個實體?

放眼使用的情況下,我需要使用該信息的幾種方法。首先,當我生成要向用戶展示的評估列表時,我不僅需要根據評估頻率評估直接報告列表,還需要知道我是否已經開始和/或完成評估爲該員工。這來自EmployeeAssessments表。另一種情況是,當用戶實際執行評估時,我正在與EmployeeAssessments和Responses表進行交互。

從用戶界面的角度來看,當用戶執行評估時,他們對內部數據結構等一無所知。我需要向用戶界面提供該評估的問題列表以顯示並接受響應列表堅持下去。這是否會導致帶有隨附存儲庫的第二個根目錄?

第三個用例相似,在於HR希望能夠重新生成在以後的應對辦法評估。但是,我認爲執行評估時使用的過程可以在此處使用,因爲恢復現有評估需要相同的數據,唯一的區別是讀/寫功能與HR的只讀功能不同。

把它包起來了!

好吧,我洋洋灑灑夠了,想我已經明白我雜念的頭。我很欣賞任何方向,建議,批評等等。正如我所說,我試圖跳槽,並認爲我理解了這些概念,現在這是應用它們的問題。謝謝!!!

回答

5

幾年前,我和你自己一樣。我現在正在從簡單的香草DDD跳到CQRS(請參閱cqrsinfo.com/)。

我會接近這個CQRS方式即使用事件存儲,並在architectuaral水平完全分離讀取寫入。不過,我認爲您提到的問題與普通的香草DDD方式更爲直接 - 所以我會在這種情況下回答。

你需要完全擺脫思考「數據驅動」。從主要工作流程開始。第一次和第三次使用基本上只是獲取操作。我首先會集中討論聚合根狀態改變的用例。因此,使用案例2即「執行評估」將是一個很好的開始。

  • 正如您正確指出的那樣,聚合根將是評估。可以創建「PerformAssessmentService」類(相當於域服務),並且您的執行評估工作流將存在此處。這個工作流將完全處於測試階段,所有依賴項(如存儲庫)都被簡單地刪除。

  • 您可能最終編寫整個執行評估工作流程,而無需任何具體的數據庫/ UI實現等。所有的業務邏輯都是在這個域服務中編排的,並且所有的邏輯都存在於您的評估實體和其他相關實體中。

  • 進入下一個使用案例 - 也許用例4 - 修改評估(做同上一次)

  • 離開外圍的東西,如庫/數據庫,用戶界面等,直到儘可能晚地在你的實現。其重要的在您的域名鎖定了所有的業務邏輯首先 - 然後從域駕駛你的周圍的關注 - 它的便宜得多/更有效(在我的經驗)

注意,有沒有正確的方式做到這一點,這只是一般情況下我會如何處理上述項目的概要。這裏的關鍵是,該領域真的是一切實施背後的驅動力...

+0

好的,我和你在一起。我們來關注第一個使用案例,我需要爲當前用戶生成到期或正在進行的評估列表。我正在努力解決包括評估在內的多少邏輯應該在域層中,而不是在SQL中可以輕鬆完成的。我真的希望讓評估域對象包含一個AssessmentVersion對象列表,並讓我的規範類創建一個使用「assessment.Versions」的表達式,以便所有邏輯都在代碼中? – SonOfPirate 2011-04-07 18:22:28

+0

另外,我認爲我將有一個AssessmentService公開一個ListMyDueAssessments()方法,該方法創建MyDueAssessmentSpecification類的實例並將其傳遞給AssessmentRepository.Find(spec)方法。 Find()返回滿足Spec類提供的Expression的評估對象列表。我在正確的軌道上嗎?怎麼樣返回一個更輕量級,更扁平版本的AssessmentInfo類,這與DDD一致嗎? – SonOfPirate 2011-04-07 18:25:03

0

我會與使用內存庫一個快速和骯髒的原型開始。如果你走的是正確的道路,那麼你會得到一個更好的主意。

+0

這就是,不幸的是,正是我所做的,導致了這些問題。你能解釋爲什麼你鍵入存儲庫嗎? – SonOfPirate 2011-04-07 10:47:47