Pregunta

Después de leer los libros de Evan y Nilsson, todavía no estoy seguro de cómo gestionar el acceso a datos en un proyecto controlado por dominio.¿Deberían los métodos CRUD ser parte de los repositorios, es decir?OrderRepository.GetOrdersByCustomer(cliente) o deberían ser parte de las entidades:Cliente.GetOrders().El último enfoque parece más OO, pero distribuirá el acceso a datos para un único tipo de entidad entre múltiples objetos, es decir.Cliente.GetOrders(), Factura.GetOrders(), ShipmentBatch.GetOrders(), etc.¿Qué pasa con la inserción y actualización?

¿Fue útil?

Solución

Los métodos CRUD-ish deberían ser parte del Repositorio...ish.Pero creo que deberías preguntarte por qué tienes tantos métodos CRUD.Lo que hacen ellos en realidad ¿hacer?Qué son en realidad ¿para?Si realmente menciona los patrones de acceso a datos que utiliza su aplicación, creo que hace que el repositorio sea mucho más útil y evita que tenga que hacer una cirugía de escopeta cuando ocurren ciertos tipos de cambios en su dominio.

CustomerRepo.GetThoseWhoHaventPaidTheirBill()

// or

GetCustomer(new HaventPaidBillSpecification())

// is better than

foreach (var customer in GetCustomer()) {
    /* logic leaking all over the floor */
}

Los métodos de tipo "Guardar" también deberían formar parte del repositorio.

Si tiene raíces agregadas, esto evita que tenga una explosión en el Repositorio o que la lógica se extienda por todas partes:No tiene 4 x # de patrones de acceso a datos de entidades, solo los que realmente usa en las raíces agregadas.

Ése es mi $0,02.

Otros consejos

DDD generalmente prefiere el patrón de repositorio al patrón de registro activo que indica con Customer.Save.

Una desventaja del modelo Active Record es que prácticamente supone un modelo de persistencia único, salvo algún código particularmente intrusivo (en la mayoría de los lenguajes).

La interfaz del repositorio está definida en la capa de dominio, pero no sabe si sus datos están almacenados en una base de datos o no.Con el patrón de repositorio, puedo crear un InMemoryRepository para poder probar la lógica del dominio de forma aislada y usar la inyección de dependencia en la aplicación para que la capa de servicio cree una instancia de un SqlRepository, por ejemplo.

Para muchas personas, tener un repositorio especial sólo para realizar pruebas suena ridículo, pero si usa el modelo de repositorio, es posible que realmente no necesite una base de datos para su aplicación en particular;A veces, un simple FileRepository será suficiente.Conectarse con una base de datos antes de saber que la necesita es potencialmente limitante.Incluso si se necesita una base de datos, es mucho más rápido ejecutar pruebas en un InMemoryRepository.

Si no tiene mucha lógica de dominio, probablemente no necesite DDD.ActiveRecord es bastante adecuado para muchos problemas, especialmente si tiene principalmente datos y sólo un poco de lógica.

Retrocedamos un segundo.Evans recomienda que los repositorios devuelvan raíces agregadas y no solo entidades.Entonces, suponiendo que su Cliente es una raíz agregada que incluye Pedidos, cuando recuperó al cliente de su repositorio, los pedidos vinieron con él.Accederá a los pedidos navegando por la relación desde Cliente hasta Pedidos.

customer.Orders;

Entonces, para responder a su pregunta, las operaciones CRUD están presentes en repositorios raíz agregados.

CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);

Lo he hecho en ambas formas de las que estás hablando. Mi enfoque preferido ahora es el método ignorante persistente (o PONO - Plain Ole' .Net Object) donde tus clases de dominio solo se preocupan por ser clases de dominio.No saben nada acerca de cómo persisten o incluso si persisten.Por supuesto, a veces hay que ser pragmático al respecto y permitir cosas como un Id (pero incluso entonces solo uso un supertipo de capa que tiene el Id para poder tener un único punto donde se encuentran cosas como el valor predeterminado)

La razón principal de esto es que me esfuerzo por seguir el principio de responsabilidad única.Siguiendo este principio, encontré que mi código es mucho más comprobable y fácil de mantener.También es mucho más fácil hacer cambios cuando son necesarios ya que sólo tengo una cosa en qué pensar.

Una cosa a tener en cuenta es el exceso de métodos que pueden sufrir los repositorios.ObtenerPedidoporCliente..Obtener todos los pedidos..Obtener pedidos con 30 días de antigüedad..etcétera etcétera.Una buena solución a este problema es observar el patrón de objeto de consulta.Y luego sus repositorios pueden simplemente aceptar un objeto de consulta para ejecutar.

También recomiendo encarecidamente buscar algo como NHibernate.Incluye muchos de los conceptos que hacen que los repositorios sean tan útiles (mapa de identidad, caché, objetos de consulta...)

Incluso en un DDD, mantendría las clases y rutinas de acceso a datos separadas de las entidades.

Las razones son,

  1. La capacidad de prueba mejora
  2. Separación de preocupaciones y diseño modular.
  3. Más mantenible a largo plazo, a medida que agrega entidades y rutinas.

No soy un experto, sólo mi opinión.

Lo molesto de Applying DDD&P de Nilsson es que siempre comienza con "No haría eso en una aplicación del mundo real, pero..." y luego sigue su ejemplo.Volver al tema:Creo que OrderRepository.GetOrdersByCustomer(cliente) es el camino a seguir, pero también hay una discusión sobre la lista de correo ALT.Net (http://tech.groups.yahoo.com/group/altdotnet/) sobre DDD.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top