2012-04-17 14 views
17

Parece que cada ejemplo que encuentro del patrón de repositorio, la implementación es diferente de alguna manera. Los siguientes son los dos ejemplos que encuentro principalmente.Implementación del patrón de repositorio

interface IProductRepository 
{ 
    IQueryable<Product> FindAll(); 
} 

No es entonces por lo general otra capa que habla con el repositorio y llama al método FindAll() y realiza las operaciones tales como la búsqueda de productos que comienzan con 's' o productos de ir a buscar la carta en una categoría en particular.

El otro ejemplo que encuentro mucho poner todos los métodos de búsqueda en el repositorio

interface IProductRepository 
{ 
    IEnumerable<Product> GetProductsInCategory(int categoryId); 
    IEnumerable<Product> GetProductsStartingWith(string letter); 
    IEnumerable<PromoCode> GetProductPromoCodes(int productId); 
} 

¿Qué ruta recomienda que me haga? ¿O cuáles son las ventajas/desventajas de unos a otros?

Según tengo entendido, habiendo leído http://martinfowler.com/eaaCatalog/repository.html ¿el primer enfoque parece reflejar mejor esto?

Respuesta

16

El primero es horrible. IQueryable es como un GOD object. Es realmente difícil encontrar una implementación 100% completa (incluso entre todos los OR/M). Puede exponer su ORM directamente en lugar de usarlo ya que probablemente obtenga un leaky abstraction layer de lo contrario.

Joel dice que es mejor (el texto es de la wikipedia article):

En el artículo de Spolsky, se llama la atención sobre muchos ejemplos de abstracciones que trabajan la mayor parte del tiempo, pero en un detalle de la complejidad subyacente no puede ser ignorado, y por lo tanto impulsa la complejidad en el software que se supone que debe ser simplificada por la abstracción en sí

Joels blog entry

El segundo enfoque es mucho más fácil de implementar y mantener la abstracción intacta.

actualización

su repositorio está violando el principio de responsabilidad única, ya que tiene dos razones para cambiar. El primero es si la API de productos se cambia y la otra si se cambia la API PromoCode. Debe utilizar en mi humilde opinión dos repositorios diferentes como:

interface IProductRepository 
{ 
    IEnumerable<Product> FindForCategory(int categoryId); 
    IEnumerable<Product> FindAllStartingWith(string letter); 
} 

interface IPromoCodeRepository 
{ 
    IEnumerable<PromoCode> FindForProduct(int productId); 
} 

cosas cambiaron:

  • que tienden a comenzar con métodos Find cuando varios elementos se devuelven y Get si se devuelve un solo elemento.
  • Nombres de métodos más cortos = más fácil de leer.
  • Responsabilidad única. Es más fácil decir qué tienen las clases que usan los repositorios para las dependencias.

Las interfaces pequeñas y bien definidas hacen que sea más fácil detectar violaciones de los principios SÓLIDOS ya que las clases de ruptura de los principios tienden a engordar a los constructores.

+0

Gracias por la respuesta. Pensé que estabas destinado a agrupar por agregados? ¿Debería tener un repositorio por entidad? También aquí hay un ejemplo del primer ejemplo que proporcioné.http: // stackoverflow.com/questions/5049363/difference-between-repository-and-service-layer – Scott

+0

Por agregado. No podía decir que los códigos promocionales eran solo para productos. (dado que se llamó 'GetProductPromos' y no solo' GetPromos') – jgauffin

+0

no tiene su primera interfaz, ¿también 2 razones para el cambio? primero: cambiar el método FindForCategory para cambiar el Producto devuelto por defecto si no encuentra ningún producto por categoría de categoría pasada, y segundo cambiar el FindAllStartingWith para aplicar algunos filtros predeterminados? – Masoud

0

personalmente se recomienda usar el segundo ejemplo, que la forma en que está encapsulando la lógica de búsqueda en un solo lugar y la intención de la persona que llama está claramente definida por el nombre del método que está llamando. Si va con el primer ejemplo, su código de consulta se filtrará a través de su aplicación y terminará duplicando consultas.

0

Recomiendo evitar las duplicaciones. Ese es el primer objetivo. Si tiene lógica que encuentra productos que comienzan con una letra en varios lugares, entonces es un caso especial y vale la pena extraerlo para separar el método (también da una buena descripción para su caso específico). Código sin duplicaciones mucho más fácil de cambiar, comprender y mantener.

Por lo tanto, tienden a tener un método genérico búsqueda con IQueryable y un conjunto de métodos que utilizan más de una vez:

interface IRepository<T> 
{ 
    IQueryable<T> FindAll(); 
} 

interface IProductRepository : IRepository<Product> 
{ 
    IEnumerable<Product> GetProductsInCategory(int categoryId); 
    IEnumerable<Product> GetProductsStartingWith(string letter); 
    IEnumerable<PromoCode> GetProductPromoCodes(int productId); 
} 

Considera también pruebas unitarias. Los métodos específicos son mucho más fáciles de simular que IQueryable.

0

realidad creo que el primero es mejor. Asumo mi decisión en los siguientes factores:

  1. Si la estructura del producto conseguirá refactorizado:

    • enfoque IQueryable - sólo tiene que cambiar métodos de llamada en código.
    • IEnumerables: también debe cambiar los nombres de los métodos.

  2. Si muchos a punto de derivar las interfaces que desea repetir en forma polimórfica:

    • enfoque IQueryable - beneficio de los nombres de los métodos uniformes genéricos
    • IEnumerables - algunos nombres no podría describa el método que necesita.

  3. Elasticness

    • enfoque IQueryable - fácil de dividir en IEnumerables enfoque.
    • Enfoque de IEnumerables: difícil de convertir a un enfoque IQueryable.

Por lo tanto, le sugiero que comience con IQueryable como opción predeterminada y a medida que avanza con su código siempre se puede cambiar a los IEnumerables acercarse más específicos que necesita.

1

Consenso está construyendo: segunda opción hasta el final. Además de la lógica de consulta que se filtra por todo el lugar con IQueryable, la dificultad para implementarlo correctamente es muy difícil PROBAR y simular.

Cuestiones relacionadas