ORM是不適合DDD的!鮑勃大叔表示同意

banq發表於2019-06-15

鮑勃大叔推薦的Mark Seemann一文:昨天我拜訪了一個客戶討論軟體架構,包括DDD和ORM。今天我偶然發現了我在2014年寫的東西。它仍然反映了我今天的想法。

關於使用ORM進行DDD的合適性?我不同意。ORM可能看起來很強大,但事實上,它們非常有限。似乎解決了一個問題,但創造了更多的問題。

DDD藍皮書中描述的最重要的戰術模式之一是聚合根的概念。我見過的所有ORM都公然違反了這種模式,因為你可以從任何指定的表開始並載入該表的行,然後沿著各種“導航屬性”來載入來自關聯表的資料。這意味著沒有根,因此沒有明確的資料所有權。

這樣的壞處使得一切都是可變的,你很快就會有很難推理一個系統(banq注:沒有邏輯推理的軟體系統,無法讓人看懂,是沒有邏輯思維的人胡亂搪塞!)。

(其實,Spring  Boot的Spring Data JPA適合DDD!因為它有一個聚合根!)

 眾說紛紜:

我從來沒有理解為什麼人們著迷於構建不必要的和不自然的等級。世界不是這樣的,所以要學會處理它。許多縱橫交錯的等級制度是可能的,沒有一個是對的或錯的。

任何模型都是不現實的。唯一準確的地圖就是現實本身。好的模型做出了不切實際的假設,在實踐中運作良好。我從未發現ORM在實踐中運作良好。

這就是我們稱之為模型的原因。但是“物件”和“關係表”也經常隱藏或混淆自然(邏輯)語義,並且在演變中更加不穩定(這些之間的對映必然充滿)。基於事實的模型不會增加這些額外的問題。

對於那些努力定義聚合根的人,我發現以下內容很有幫助:從關係找聚合根:如果各種關係定義為一種組合或連線,那麼那個不被其他實體組合的就是AR(聚合根)!(banq注:•聚合根= 資料表實體 + 資料表關係!)

我不確定我理解這個定義......我認為Aggregate Root是一棵樹。根據模式,您必須只讀取和寫入根,它將隨所有分支和葉子一起提供。你絕不能以任何其他方式讀寫分支和葉子。

如果我們繪製模型的類圖,我們就有組合關係(當父類死亡,子類也死亡)。如果一個實體永遠不是子類,那麼它就是一個AR。不知道是否有更好的解釋。

它只是一個封裝聚合的Facade,它只是圍繞著許多物件一起工作的邊界 - 一個比一個類更大的組織單元:決定了AR將是什麼,它是你設計的一個特色。

我最初的想法是通過儲存庫模式約束ORM。例如,對於Entity Framework,僅允許訪問擴充套件聚合基型別的物件。

當然,這也要求表示實體的類的設計遵循聚合邊界。定向約束關聯僅限於概念上包含在聚合中的實體。

小心DDD。它經常導致功能分解。

如果你有A,B和C,A後面跟著B,B後跟著C,然後你會建立A,B和C服務。你經常會得到一個膨脹的客戶端或上帝物件。DDD可以導致這種情況。

導航屬性和延遲載入:使用預先載入/顯式載入

您可以刪除導航屬性並僅對映fk。但是RDBMS是這裡的問題,在db級別,每個表都是頂級實體。文件資料庫更適合聚合根定義IMO

我曾經和一個客戶討論過這個問題,他們認為他們能夠“遍歷”整個域模型真是太好了。懶裝載無處不在,沒有限制.....

這一切都很有趣和遊戲,直到生成的所有查詢都搞垮了伺服器和資料庫。

與“SRP單一責任”相反的是“ORM”;)

業務規則/不變數就是一個動機。在根中,您可以強制執行跨越屬於AR的多個實體的規則。例如,具有與購物車中的商品相關的規則的購物車,例如折扣。該邏輯適合購物車實體,而非物品實體。

 

相關文章