0

Recently I have encountered an article Implement the Query Specification pattern and I am confused about using specification pattern with generic repository.

I have already a generic repo like this:

public interface IGenericRepository<T> where T:class
{ 
    IReadOnlyList<T> GetAllAsunc(int id); 
    IReadOnlyList<T> FindAsync(Expression<Func<T, bool>> filter); 
    T GetById(int id)
    void Add(T item); 
    void Update(T item); 
    void Delete(T item); 
}

And a sample method for specification pattern

public BaseSpecification(Expression<Func<T, bool>> criteria)
{
    Criteria = criteria;
}

I can send any expression with IReadOnlyList<T> FindAsync(Expression<Func<T, bool>> filter); method. So, I don't really understand why I need specification pattern with generic repository. It looks they are doing same things. Could you clarify this?

Omer
  • 8,194
  • 13
  • 74
  • 92
  • 2
    *I don't really understand why I need specification pattern* Nobody said you did. The internet is full of pattern evangelists. You should always ask the question (as you do): Great, but what's in it for me? Often the answer will be: nothing. Many patterns are outdated. You're right, an expression is a specification in itself ready to be used in its own right. Now go and ask yourself the same question about the repository pattern. It's so tiring that Microsoft keeps proposing that pattern as the way to go. It can be really refreshing to see totally different approaches, like "vertical slices". – Gert Arnold Jan 16 '22 at 20:55

1 Answers1

4

The specification pattern covers more than just a filter expression, it also covers eager loading and pagination. In your example, if you were dealing with an entity that referenced 3 other entities and had a child collection, how would you tell your repository method which of those should be eager loaded? If your List method could return hundreds of thousands of rows, how would you tell it to load just a page of 50 at a time?

In my personal opinion, using the Specification is a SRP band-aid on a generic repository. Generic repositories are an anti-pattern in EF systems where you are positioning your repository code to have a great number of "forces" lobbying for change using the Specification to mitigate that. I would never advocate for trying to build an MVC web application with a single generic Controller<T> implementation, and for the same reason I don't advocate using Repository<T>. Specifications do not protect callers from being polluted with domain / EF knowledge because every expression passed in must conform to the rules set out by the domain implementation. While a specification might handle filtering, eager loading, and pagination... What about sorting, projection, or other aggregate functions like exist checks and counts? At the end of the day it's a complexity rabbit hole trying to satisfy S.O.L.I.D. principles making your code considerably more complex and harder to follow, and slamming head-first into barriers repeatedly as new requirements don't conform to past assumptions.

Steve Py
  • 26,149
  • 3
  • 25
  • 43