model view controller - pattern - Patrón de repositorio: ¿Cuál es el ''tamaño correcto''?
repository pattern ef (1)
Los repositorios son, al menos no que yo sepa, un lugar para las reglas comerciales. Son solo una fachada destinada a imitar una colección; Debajo, básicamente, son acceso puro a los datos (si ese es su trabajo, es posible que tampoco persista en nada con un repositorio). Por lo tanto, los repositorios separados no deben considerarse por razones de "reglas comerciales".
Si los objetos de su dominio son realmente objetos separados, entonces debe tener repositorios separados. Recuerda lo que es un repositorio: es una fachada. Simula una colección a tu dominio. Vea aquí una muy buena publicación de blog en Repositorios: http://devlicio.us/blogs/casey/archive/2009/02/20/ddd-the-repository-pattern.aspx
El repositorio es una fachada; una abstracción
Dicho eso ... No creo que tengas objetos separados. Aquí tiene algunos problemas que no tienen nada que ver con los repositorios y todo lo relacionado con el dominio y el diseño del dominio. ¿Los dos tipos de "tarjetas de tiempo" en realidad son dos cosas diferentes, o son realmente iguales?
Usted dice: "Pero me parece un poco extraño que pueda obtener el mismo registro de dos repositorios diferentes".
Eso me dice que en realidad son los mismos datos, expresados de diferentes maneras. Y hay formas de manejar eso.
Si este es realmente el caso, entonces lo que tienes aquí son subclases de una clase base común (algo que se puede modelar en un DB bastante fácil y se maneja elegantemente con NHibernate, por ejemplo).
Te daré un ejemplo de un proyecto en el que estoy trabajando. Tengo algo llamado "Transmisión". Es una clase base; abstracto. No puede ser instanciado. Tengo dos tipos específicos de hormigón de esta clase: DeviceBroadcast y FileBroadcast. Uno transmite audio / video desde un dispositivo (como una tarjeta de captura DirectX) y uno transmite audio / video desde un archivo fuente (como un .mp3).
Tengo un repositorio que devuelve un objeto Broadcast. Puedo transmitirlo a FileBroadcast para manipular información específica sobre un FileBroadcast, o puedo enviar contenido a un dispositivoBroadcast por el mismo motivo, si es de ese tipo. Un Broadcast no puede ser tanto de tipo FileBroadcast como DeviceBroadcast. Tiene que ser uno o el otro.
En la base de datos, almaceno los parámetros genéricos de transmisión en una tabla Broadcast, y luego almaceno las propiedades específicas del archivo en una tabla FileBroadcast. Lo mismo ocurre con la tabla DeviceBroadcast; separar. Sin embargo, cuando realizo una consulta a través del Repositorio, solo deseo las Transmisiones. Ese es mi objeto agregado raíz y, por lo tanto, ese es mi repositorio.
La clase base de difusión tiene métodos comunes que ambas subclases usan (como el método GetCommand (), que devuelve un argumento de línea de comando específico para iniciar un proceso de VLC). Las subclases deben anular e implementar ese método porque es abstracto. De esta manera, la "lógica de negocios" que es exclusiva de un FileBroadcast está contenida en la clase FileBroadcast. La "lógica de negocios" que es exclusiva de un DeviceBroadcast está contenida en la clase DeviceBroadcast. Cualquier lógica que sea común a ambos está contenida en la superclase, Transmisión.
Parece que tienes una situación similar aquí y es por eso que estoy compartiendo mi diseño. Creo que podría ser útil para ti.
Sobre todo, piense en su dominio y los datos. Si va a obtener datos duplicados por medio de repositorios separados, entonces debe pensar más en cómo está diseñando el dominio. No permita que los usuarios dicten el diseño de su dominio tampoco. Ellos conocen el dominio desde su perspectiva. Todo lo que tienes que hacer es presentarles la información de una manera que entiendan. Eso no significa que tengas que tener un mal diseño; Puede tener un buen diseño detrás de escena porque su código es lo que tiene que usar el dominio.
Estoy construyendo repositorios para una aplicación MVC, y estoy tratando de encontrar la forma correcta de dividir responsabilidades entre repositorios. En la mayoría de los casos, esto es obvio. Pero hay un caso particular en el que no estoy seguro de cuál es la respuesta correcta.
Los usuarios de esta aplicación necesitan rastrear varios tipos de tiempo para sus empleados. Para simplificar, consideremos solo dos. Los llamaré "tarjetas de tiempo" y "asistencia". La naturaleza exacta de la diferencia entre estos dos no es realmente importante, pero debe tener en cuenta que los usuarios finales los consideran datos completamente independientes. Creo, sin embargo, que la razón por la que los consideran datos completamente separados es porque nunca tuvieron la oportunidad de verlos juntos en el pasado. Ambos tipos de registros tienen reglas comerciales casi totalmente diferentes sobre la edición de los registros, pero también son, en términos generales, ambos registros de dónde estaba un empleado en un momento determinado. Ambos tipos de registros de tiempo tienen una gran cantidad de propiedades en común, como un número total de horas y un empleado para el que se recolectó el tiempo. Ambos tipos también tienen algunas propiedades que son completamente únicas para el tipo individual. Mantenemos estas propiedades "adicionales" en una instancia de otro tipo. Entonces la estructura general se ve así:
class TimeRecord
{
Person Employee { get; set; }
TimeSpan? Hours { get; set; }
}
class TimeCardData
{
TimeRecord Record { get; set; }
TProperty TimeCardProperty { get; set; }
}
class AttendanceData
{
TimeRecord Record { get; set; }
TProperty AttendanceProperty { get; set; }
}
Entonces la pregunta es, ¿cuántos repositorios se requieren aquí?
1 repositorio
Un diseño con solo un repositorio expondría métodos para devolver "tarjetas de tiempo", registros de "asistencia" o ambos tipos en una lista. Esto es bastante conveniente para los clientes del repositorio, pero, en mi opinión, tiene un peligro real de convertirse en una clase muy gorda. Creo que un repositorio de "tarjetas de tiempo" ya será uno de los repositorios más grandes del sistema, incluso sin manejar la "asistencia" simplemente debido a las complejas reglas comerciales involucradas.
2 repositorios
Otro diseño tendría un repositorio para "tarjetas de tiempo" y otro depósito para registros de "asistencia". Esto tiene la ventaja de que las reglas comerciales para, por ejemplo, "tarjetas de tiempo" están en un lugar por sí mismas. Pero también me gustaría tener una forma de obtener una lista de registros de todos los tiempos, independientemente del tipo. No está claro qué repositorio usar para este caso. ¿Ambos?
3 Repositorios
Un diseño con un repositorio para "tarjetas de tiempo", otro repositorio para registros de "asistencia" y un tercer repositorio para entregar una lista de solo lectura de registros de todos los tiempos también es una posibilidad. Al igual que el diseño de 2 repositorios, esto tiene la ventaja de que las reglas de negocios para, por ejemplo, "tarjetas de tiempo" están en un lugar por sí mismas. Ahora está claro dónde obtener la lista combinada. Pero me parece un poco raro que pueda obtener el mismo registro de dos repositorios diferentes.
Híbrido
Un enfoque híbrido usaría un único repositorio, pero movería cualquier código de reglas comerciales (incluida la selección de registros) a tipos separados. En este ejemplo, un único "depósito de registro de tiempo" agregaría instancias de clases de implementación de reglas de negocios para la "tarjeta de tiempo" y el tiempo de "asistencia". Creo que este es el enfoque que estoy favoreciendo en este momento.
¿Otro?
¿Algo que me haya perdido? ¿Algún argumento convincente para un diseño sobre el otro?