Repository Pattern Best Practice

前端 未结 3 706
臣服心动
臣服心动 2021-01-30 05:23

So I\'m implementing the repository pattern in an application and came across two \"issues\" in my understanding of the pattern:

  1. Querying - I\'ve read responses

3条回答
  •  佛祖请我去吃肉
    2021-01-30 06:02

    In response to @lordinateur I don't really like the defacto way to specify a repository interface.

    Because the interface in your solution requires that every repository implementation requires at least an Add, Remove, GetById, etc.. Now consider a scenario where it doesn't make sense to Save through a particular instance of a repository, you still have to implement the remaining methods with NotImplementedException or something like that.

    I prefer to split my repository interface declarations like so:

    interface ICanAdd
    {
        T Add(T entity);
    }
    
    interface ICanRemove
    {
        bool Remove(T entity);
    }
    
    interface ICanGetById
    {
        T Get(int id);
    }
    

    A particular repository implementation for a SomeClass entity might thus look like the following:

    interface ISomeRepository
        : ICanAdd, 
          ICanRemove
    {
        SomeClass Add(SomeClass entity);
        bool Remove(SomeClass entity);
    }
    

    Let's take a step back and take a look at why I think this is a better practice than implementing all CRUD methods in one generic interface.

    Some objects have different requirements than others. A customer object may not be deleted, a PurchaseOrder cannot be updated, and a ShoppingCart object can only be created. When one is using the generic IRepository interface this obviously causes problems in implementation.

    Those implementing the anti-pattern often will implement their full interface then will throw exceptions for the methods that they don’t support. Aside from disagreeing with numerous OO principles this breaks their hope of being able to use their IRepository abstraction effectively unless they also start putting methods on it for whether or not given objects are supported and further implement them.

    A common workaround to this issue is to move to more granular interfaces such as ICanDelete, ICanUpdate, ICanCreate etc etc. This while working around many of the problems that have sprung up in terms of OO principles also greatly reduces the amount of code reuse that is being seen as most of the time one will not be able to use the Repository concrete instance any more.

    None of us like writing the same code over and over. However a repository contract as is an architectural seam is the wrong place to widen the contract to make it more generic.

    These exerpts have been shamelesly taken from this post where you can also read more discussion in the comments.

提交回复
热议问题