12

Tengo una aplicación asp .net MVC y recientemente comencé a implementar el patrón de depósito con una capa de validación de servicio, muy similar a this.Decisión de diseño de patrón de depósito MVC

He estado creando un repositorio/servicio para cada modelo que creo. ¿Es esto exagerado? En su lugar, ¿debería crear un repositorio/servicio para cada área comercial lógica que proporciona CRUD para muchos modelos diferentes?

Para mí, parece que estoy abarrotando el árbol de proyectos con muchos archivos o abarrotando una clase con muchos métodos. 6 de una manera, media docena de la otra. ¿Puedes pensar en algún buen argumento de cualquier manera?

Respuesta

16

Generalmente, si utiliza un patrón de repositorio "verdadero", a diferencia de otras capas de persistencia (por ejemplo, ActiveRecord o DAO), debe intentar identificar los agregados de su dominio y crear un repositorio por agregado.

¿Qué significa eso? Bueno, depende mucho de su aplicación, pero en general hay objetos que son naturalmente 'padres' de otros objetos, o que son parte de una transacción relacionada.

Creo que el ejemplo canónico es un sistema de comercio electrónico en el que tiene un concepto de orden, y en un orden tiene líneas de pedido cada línea de pedido es un producto y una cantidad, y así sucesivamente.

En ese caso, el objeto Order es una de las raíces agregadas del sistema y se crea un OrderRepository.

Lo que hay que recordar en ese caso es que existe alguna relación (implícita o no) entre un pedido y sus líneas de orden, etc. Por lo tanto, las partes C-UD de "CRUD" en el Repositorio generalmente deberían ser solo un método cada una, y generalmente solo deberían tomar una instancia de ese objeto raíz agregado y operar en él (por ejemplo, repo.Save (order)). Otros posibles params podrían estar ahí, pero eso depende de tu impl.

De hecho, a menudo puede resolver la mayoría de la parte C-UD con herencia (es decir, crear una RepositoryBase que los implemente utilizando alguna lógica conocida sobre qué sucederá para su esquema de persistencia particular).

Eso nos deja la parte R de CRUD. En este caso, es posible que obtenga un montón de métodos de consulta (GetById; GetByName; GetByCustomerName, etc.) si elige ir a la ruta del método de consulta. Algunas personas prefieren, especialmente para aplicaciones simples, exponer una interfaz basada en linq (por ejemplo, un GetEll de IQueryable) que puede tener cláusulas WHERE aplicadas.YMMV dependiendo de tu persistencia subyacente en eso, pero es una oportunidad sólida para aplicaciones simples, esp. si espera que su proveedor de persistencia soporte linq directamente.

Por último, muchas personas realmente separan la parte de la consulta a través de una implementación u otra del patrón de separación de responsabilidad de consulta de comando, que dice que las interfaces para persistir y consultar deben ser diferentes. En ese caso, tendrías un Repo que solo tiene operaciones CRUD (GetById, GetAll, Save, Delete) básicas y otra clase de algún tipo que consulta cosas según las intenciones de tu aplicación.

Espero que ayude.

Paul

+0

Paul gracias por la respuesta detallada. Después de mucho pensarlo y leerlo, siento que estás al tanto con un repositorio/servicio por raíz agregada. También tiene razón sobre el CRUD, 1 método cada uno para C_UD y muchos métodos de R. En su ejemplo de Pedido, ¿el OrderRepository también sería el lugar para poner los métodos R para OrderLines y OrderSubLines? – bradjive

+0

Esa es una buena pregunta, y depende. ¿Las líneas de pedido y sublíneas realmente significan algo útil sin su orden asociado? Si es así, entonces sí, si no es así, todas las consultas tienen que ver con Orders y puede filtrar las colecciones secundarias utilizando expresiones LINQ regulares sobre los IEnumerables. – Paul

3

Esta es una pregunta que hice recientemente y, a pesar de obtener varias buenas respuestas, finalmente llegué a mi propia conclusión: no hay una respuesta correcta. Eso no significa que no haya una respuesta incorrecta, de hecho hay muchas respuestas incorrectas, pero la respuesta correcta siempre dependerá de su propio caso individual.

Terminé con cuatro repositorios y una extensión de clase parcial de mi EF4 Entity Model para las acciones CRUD estándar para las entidades secundarias (direcciones, números de teléfono, códigos de estado, etc.) para que se implementaran una vez y estuvieran disponibles en todos repositorios. Sin embargo, todavía estoy refinándolo a medida que avanzo, por lo que quizás todavía no he encontrado la mejor solución.

Mi consejo sería intentarlo y ver si se ajusta, y ver si se siente bien. Por lo general, si no es siente a la derecha, está mal de todos modos.

Si realmente tiene miedo de saturar su árbol de códigos fuente, siempre puede dividir la parte del modelo en su propia biblioteca e incluirla como una dependencia.