

領域模型不要直接依賴Repository
source link: https://teddy-chen-tw.blogspot.com/2023/06/repository.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

領域模型不要直接依賴Repository
June 11 19:23~20:38
▲圖1:將Repository放到Entities Layer(錯誤示範XD)
前言
6/5~6/7到客戶家上【領域驅動設計與簡潔架構入門實作班】,有一位學員問了Teddy不少問題,像是:
- 為什麼Teddy建議Entities Layer的物件不要直接操作Repository?
- 為什麼有人說UoW(Unit of Work)和Repository在DDD裡面算是Anti-Pattern?
- 為什麼Teddy沒有用Specification模式?
這些問題,應該是有在下功夫研究DDD的人,才會提出來的問題。針對這三個問題,Teddy分三集來說明,今天先談第一個問題。
增加領域模型與測試複雜度
Entities Layer是Clean Architecture存放領域模型(Domain Model)的地方,它應該只表達問題領域的業務邏輯,儘可能與外在世界、框架無關。Repository是領域驅動設計(Domain-Driven Design;DDD)中,用來存取聚合(Aggregate)的設計模式。也就是說,Repository隔離了儲存層,讓它的使用者無需知道儲存聚合的實作細節。
Entities Layer知道Repository又怎樣?首先,這麼作讓Domain Model依賴資料存取介面,雖然這個依賴透過Repository介面做到依賴反轉,但「資料存取」的概念還是洩漏到Domain Model,增加不必要的複雜度。
這種不必要的複雜度增加,可以從測試的角度看出來。針對Entities Layer物件的測試,理想上就是傳統軟體測試所說的單元測試,而且是可以做到「測試隔離」(test in isolation)。這樣子的單元測試,因為與外在世界無關,所以可以跑得很快且可以單獨測試業務邏輯。
看到這裡鄉民們可能會想:「我有學過Test Double(測試替身),我可以在測試案例中注入Test Double,這樣就可以寫出與世隔絕的單元測試。」
使用Test Double雖然可以讓使用Repository的Entities Layer物件做到隔離測試,但是付出的代價就是單元測試變得複雜且可能出現重複程式碼。現在,要測試Entities Layer物件之間,都要在單元測試的Arrange階段先設定Repository替身,這會複雜化且重複Arrange區塊的程式碼。
弱化階層式架構
請參考圖1,如果將Repository放在Entities Layer,從Clean Architecture的角度來看,為了滿足相依性原則,BoardRepository必須是一個介面,然後在Interface Adapters Layer實作BoardRepositoryImpl。如此一來,雖然滿足相依性原則,卻造成了BoardRepositoryImpl跨層依賴於BoardRepository。雖然在鬆散式階層架構中允許跨層依賴,但Teddy認為這會弱化了階層式架構的一致性。
其他人怎麼說
請參考圖2,在IDDD書中也提到,不要將Repository注入給Aggregate。
▲圖2:Teddy的FB廢文1
如圖3所示,在Unit Testing一書中也提到,在領域模型中直接使用資料庫(相當於Repository)會造成程式碼過度複雜。
▲圖3:Teddy的FB廢文2
結論
只要程式可以正確動起來,設計沒有絕對的對、錯,但有合適程度的差別。關於這個問題Vladimir Khorikov有一篇很棒的blog: <Domain model purity vs. domain model completeness (DDD Trilemma)>,鄉民們可以參考。
友藏內心獨白:領域模型越乾淨越好。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK