Repository,我可能不會用你 (3) - 正反意見

這篇筆記整理 Oren Eini 與 Grey Young 兩人在部落格上筆戰 Repository 模式的一些論點。不是很完整,看看就好....

在<Repository,我可能不會用你>文後附的延伸閱讀裡面,有兩篇是出自 Oren Eini 的部落格。Oren Eini 很明顯是反對 Repository 的。他寫了好幾篇文章批評 Repository,甚至拿 CodePlex 上面的程式碼當作例子,清楚表明他對「過度設計」有多麼厭惡。
Oren Eini 何許人也?Rhino Mocks 就是他寫的。他同時也主導或參與  RavenDB、NHibernate、和 Castle 專案的開發,還寫了本書:DSLs in Boo: Domain Specific Languages in .NET

在一篇標題為「Repository is the new Singleton」的文章裡,Oren 提到 Repository 有兩個問題。首先,查詢條件通常很多樣、複雜,結果就是在 Repository 類別裡面加入一堆查詢方法,例如:
  • FindCustomer(id)
  • FindCustomerWithAddresses(id)
  • FindCustomerWith...

Oren 提出的解決辦法是使用查詢物件來封裝查詢條件。這裡的查詢物件,其作用與 query specification 類似,只是實作方法不太一樣。

其次,Oren 認為 Repository 之所以如此普遍,大多是受到 DDD 的影響。他認為 DDD 務須謹慎為之,除非真有需要才用它,否則很可能比不用 DDD 還糟糕。此外,他也認為多數人只是把 Repository 設計成 DAO,而不是 DDD 所說的那種 Repository。

最後,他把自己的資料存取策略歸納成四點:
  • 當資料來源是資料庫時,直接使用 NHibernate 的 ISession。
  • 把複雜的查詢條件封裝成查詢物件。
  • 尊重底層的 storage 實作:如果資料來源不是資料庫,就為它寫一個 DAO。
  • 別保護開發人員。(連結指向另一篇文章,大意是應該讓開發人員成長,而非處處框架限制、保護他們)

老實說,我覺得他的幾篇批 Repository 模式的文章並沒有把他的解決方法解釋得很清楚(內心獨白:show me the code!)。或許就如他在某篇文章裡面說的,他的想法散落在各篇文章裡面,單單一篇文章無法窺得全貌。
2014-05-08 補充:他在一次演講中解釋了他認為好的設計方式:Breaking apart conceptions(可是我真的聽不太懂他的英語,哭!)

筆戰

Oren Eini 對 Repository 的批評自然引來不少質疑,其中有位仁兄就特地寫了篇文章來反駁:Repository is Dead: Long Live Repository。此人是 Greg Young。我對他不太熟悉,只知道他是個獨立顧問,到處演講,以及為《Exploring CQRS and Event Sourcing》一書寫序。

Greg Young 在那篇文章的幾個重點如下:
  • Repository 介面不必是物件導向的;它代表了一個架構邊界,亦即 tier/layer 之間的一個邊界。在定義這樣的邊界時,通常會比較程序導向(我不太確定他的意思,但我猜他指的是接著提到的 CQS 模式)。
  • 沒有將 Repository 視為 tier/layer 邊界的人,是誤用了 Repository 模式。
  • 對於複雜的查詢條件,為了避免寫一堆類似 GetCustomerByID、GetCustomerByXyz123 的方法,建議將「讀」和「寫」的操作分開,也就是使用 CQS(Command and Query Separation)模式。而 Oren 文章提到的解法是查詢物件(query object),根本了無新意。
  • Oren 既然認為「Repository 已死」,卻又在文章裡嘗試提出基於 Repository 的改進方案,簡直矛盾。

Oren 看到那篇打臉文章後,寫了一篇 Night of the living Repositories 作為回應。嗯....有部電影叫作《活死人之夜》,英文片名是 Night of the Living Dead。兩個標題只有一字之差,但 Oren 可沒說 Repositories = Dead 喔。他還挺幽默的 :)

底下是他的反擊內容概要:
  • 我(Oren)壓根沒說過「Reporitory 模式已死」這種話;我只是說,此模式沒有考慮到既有 ORM 框架的優點,以及在 ORM 之上再疊一層 Repository 其實沒有得到多大好處。
  • Greg 說我自相矛盾:既反對 Repository,卻又使用 Repository 模式來解決問題。但我看不出來我原先的文章哪裡有建議使用 Repository。我提出的方法中根本沒有 Repository;資料儲存的部分是直接由 ORM 框架(NHibernate)負責,資料查詢的部分則是利用查詢物件。
  • 邊界之說,我懂。但我不確定這樣的「人工邊界」是否恰當。
  • 就算使用 CQS 模式,我也會需要為資料寫入操作提供不同的提取策略(fetch plan)。我認為提取策略是個重要觀念,原因就在於此。

然後,Greg 的回應:More on Repository
然後,Oren 又回應:The Repository's Daughter。(哈!這是《將軍的女兒》續集嗎?)

筆戰到此大致結束。我沒有全部看完,說實在,挺累的。也許兩人在替自己觀點辯護時,在心中都有個特定的 context,而彼此的 context 不太相同,以至於有時候出現雞同鴨講的情形,繼續爭論下去肯定沒完沒了。

小結

有句話說得好:「讓想結婚的結婚吧,不想結婚的繼續維持單身吧,反正他們終究都會後悔的。」
我依樣畫葫蘆:「想用 Repository 就用,不想用的就別用吧,反正他們終究會把事情做對的。」

結論:Oren 一定也很愛看電影。

2 則留言:

  1. 結論很棒 XD

    倒是煥麟大哥這幾篇Repository的文章,讓我了解到我之前對Repository Pattern的誤解。

    看來我是把Factory, Builder跟Repository有點攪在一起了...

    如果有機會,也想請煥麟大哥有空閒時間時,可以寫篇文章開示一下,解釋一下這三個Pattern的差異跟使用場景 ^___^

    回覆刪除
  2. 那我得好好用功 study 才行 ^^
    有不對的地方請多指正喔! Thanks!

    回覆刪除

技術提供:Blogger.
回頂端⬆️