對Repository模式誤用的反思和糾正


      一直以來想自己做一套開發框架,在其基礎上進行快速開發,自從接觸微軟的MVC框架和Entityframework以來,閱讀了大量園子里的相關的技術文章,也進行了不少摸索和嘗試,中間經歷了多次大刀闊斧的重構,現在總算有了雛形,把權限、模式和界面初步搞定,但是回頭一看,依然有很多東西思路不夠清晰,很多時候是在生搬硬套,不求甚解,結果搞出來一些四不像的東西。

    入行近十年,項目經驗和開發經驗應當是很豐富的,但是架構方面,確實是個新手,現在總算對相關技術有了一定的了解,因此打算從頭再來一遍梳理,徹底的重構。
    之前參考別人的技術文章,加上自己的摸索,大致采用的模式是這樣的,使用了MVC和Entityframework,Unity作為IOC容器,Model層和View層不必多說, Controller->Service ->Repository,Repository層通過Entityframework來實現數據的增刪改查,業務邏輯放在Service層,通過UnitOfWork模式來實現多實體的事務控制,Controller層的職責就是調度,處理從UI層傳過來的參數轉換。

     首先來說Repository層,首先定義了一個泛型接口,IRepository<Entity>,在里面定義了增刪改查,然后定義了一個類 Repository<Entity>,實現IRepository<Entity>接口,同時為了考慮各實體特有的實現,為每個實體定義一個特有接口,以人員為例,定義IUserRepository接口,繼承IRepository<User>,最終定義類UserRepository,繼承Repository<User>,並實現IUserRepository接口。

 所有的實體都是按照上述模式實現的,使用泛型,主要是實現了代碼復用,這種模式在園子里也有不少人是這樣用的。

 

關於Repository的定義和作用,園子里有很多文章提過多次了,在此我引用下(來源): 

Repository是一個獨立的層,介於領域層與數據映射層(數據訪問層)之間。它的存在讓領域層感覺不到數據訪問層的存在,它提供一個類似集合的接口提供給領域層進行領域對象的訪問。Repository是倉庫管理員,領域層需要什么東西只需告訴倉庫管理員,由倉庫管理員把東西拿給它,並不需要知道東西實際放在哪。 

由此可見,Repository是從領域驅動設計中的概念,從我的架構設計來說,並不是領域驅動的,沒有聚合根的概念,對於Service層來說,需要一個DAL層來處理數據的存儲和查詢,因此,我這里使用Repository明顯是一個誤用。

 

關於Repository與DAL 區別如下: 

Repository是DDD中的概念,強調Repository是受Domain驅動的,Repository中定義的功能要體現Domain的意圖和約束,而Dal更純粹的就是提供數據訪問的功能,並不嚴格受限於Business層。

使用Repository,隱含着一種意圖傾向,就是 Domain需要什么我才提供什么,不該提供的功能就不要提供,一切都是以Domain的需求為核心;而使用Dal,其意圖傾向在於我Dal層能使用的數據庫訪問操作提供給Business層,你Business要用哪個自己選。換一個Business也可以用我這個Dal,一切是以我Dal能提供什么操作為核心。

這也就意味着,不應當在DAL層單獨定義一個IUserRepository類來處理特有的接口方法,如用戶不能被刪除,而是應當在Service層里做控制,DAL單純地提供對數據的查詢和存儲,不關心業務邏輯。

 

     明確了上面的概念,下面就動手進行簡化,有兩種實現方式,一是使用泛型,二是使用T4模板或者代碼生成器,這兩種方式都能達到代碼復用的目的。我這里采用的泛型,首先定義一個泛型接口IDAO<Entity>,泛型接口中定義方法也很明確:增、刪、改、查,此前在IRepository定義了過多的重載方法,例如對於刪除,定義了指定主鍵刪除、指定實體刪除和指定Lambda表達式刪除,對於查詢,定義了返回所有實體集合和返回單頁數據集合。上述概念明確后,DAL層僅需要提供必要的幾個方法即可,而對於同樣功能的方法重載,放到Service層更合適。然后定義EFDAO<Entity>類實現該接口。這樣做的好處不僅代碼實現了復用,而且做到了面向接口編程,對於Service層來說,看到的只是IDAO接口,而不是具體的實現類。而IDAO是怎么實現的,是EntityFramework、NHibernate還是原生的sql,則可以靈活替代,變更數據訪問層對整個系統無影響。

 

簡而言之,我的框架實質是MVC模式加三層架構的結合體,View和Controller層基本不動,Model層細分為Model、Service/BLL、DAL三層。

以上是個人的反思和總結,把個人的誤用經歷、重構原因和最終實現方式發出來,供同道中人參考,歡迎批評指正,期待交流。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM