2016-09-29 116 views
1

我們的團隊有一個基本上是MIS的項目。 我們正在使用的架構是CQRS與DDD(域驅動設計)。 我們擁有持久層中的持久化對象,領域層中的域對象,數據傳輸對象以承載來自用戶的輸入信息,以及查看對象以在特定頁面上顯示數據。域對象是否可以與持久對象相同?

我認爲這種設計是巨大的。但在項目實施過程中,我們發現了一些阻礙我們的問題。最令人厭惡的是我們必須編寫許多轉換器來在兩個不同的層之間轉換對象,如PO到DO,DO到PO,DTO到DO。這些轉換器中有太多的get和set語句。我們之所以沒有使用像BeanUtils這樣的東西,是因爲當兩個對象中的字段具有不同的類型或名稱時,它效果不佳。顯然這些代碼違反了開放原則。每當特定頁面發生變化或者我們想要更改數據庫中的字段時,這將是一場噩夢。

我不知道是不是真的不一定分開DO和寶,我們可以只簡化架構和設計,使他們同樣的事情,因爲在大多數情況下,他們只包含差別不大相同的字段。 我們如何簡化設計以避免我們面臨的問題並提高我們的生產力並確保軟件的可擴展性和穩定性?

+0

也許你有貧血的域模型。 https://en.wikipedia.org/wiki/Anemic_domain_model無論如何,你不應該做你正在計劃的事情,因爲它會導致貧血域模型。 ;-)據我所知... – inf3rno

+0

從域對象中分離持久化對象是IMO最近的一個趨勢,這是由於ORM做了一個或多或少的離開域實體原始工作的不好的事實。關於測繪,還檢查了http://blog.ploeh.dk/2012/02/09/IsLayeringWorththeMapping/ – guillaume31

+0

域對象模型的業務限制。持久化對象模擬數據應該如何存儲在數據庫中。目的非常不同。只是在簡單的情況下,CRUD應用程序可以是相同的。 – MikeSW

回答

2

如果你看看DDD的戰術模式,你會發現任何關於「域對象」。如果您聚合了根,那麼您有聚合,它由實體和其中一個實體組成。每個有界上下文可能只有一個實體,這將是您的聚合根。

你堅持你的聚合作爲一個整體。基本倉庫以「集合樣式」運行,只允許您將新集合放入存儲庫並通過其標識從存儲庫檢索一個集合。

CQRS將一個對象分成兩部分。一個對象是您的聚合優化寫作。通常,在「寫入端」你的命令處理程序中使用集合式存儲庫就足夠了。然而,在「閱讀方面」,你有更扁平的閱讀模型,代表你想以一種爲閱讀而優化的方式展示給用戶的內容。

如果你說你使用CQRS但只有一個模式,一個數據庫,這不會有很大的意義。如果你有命令處理程序,這並不意味着你使用CQRS。

此澄清後,大家可以看一下總的持久性。 從來沒有人說過你不能堅持聚合。從某種意義上說,如果您擁有合適的存儲空間,這實際上是首選方法。通常情況下,ORM不是一個合適的存儲,因爲它會在你發現目標世界和關係數據庫世界之間的阻抗不匹配的地方產生摩擦。文檔數據庫更適合於此。 PostgreSQL JSONB功能也是一個不錯的選擇。

流將被:

  • DTO(命令)從客戶端發送
  • 工作單位開始
  • 命令處理程序檢索從倉庫聚集
  • 命令處理程序調用對聚合方法來執行必要的邏輯運算
  • 骨料可能發射可工作
  • 01的在同一單元內觸發的事件處理程序的一些域事件工作
  • 單位提交更改

正如你看到的,對於任何持久性「轉換」這裏沒有真正到位。如果你有一個合適的存儲空間,那就很好。

當你閱讀,但是,你有來自客戶端的請求。然後,這個請求會轉到某個查詢提供程序,數據提供程序或任何您稱之爲的內容。有的把所有這些查詢到他們的資料庫,但是這僅適用,如果你使用CQRS或至少有一個持久性模型,而不是兩個都

查詢是冪等,它們不改變系統的狀態,因爲你沒有後果一樣,除了你的持久層,如果讀不優化,可以加載可以運行多次。但是,讀取方面不需要大量的抽象。同時,您不應將聚合發回給查詢您的域的客戶端。您需要擁有一個代表客戶視圖模型以滿足特定需求的DTO,而不是更少。此DTO需要儘可能快地在客戶端進行優化,無需計算和轉換。這基本上是CQRS建議在讀取方面做的 - 準備您的數據以快速交付這些DTO。