DDD - Cómo implementar repositorios de alto rendimiento para la búsqueda


Tengo una pregunta sobre DDD y el patrón del repositorio.

Digamos que tengo un repositorio de Clientes para la raíz agregada de Clientes. Los métodos Get & Find devuelven el agregado completo, que incluye objetos como Address, etc. Todo bien. Pero cuando el usuario está buscando un cliente en la interfaz de usuario, solo necesito un "resumen" del agregado, solo un objeto plano con información resumida.

Una forma en que podría lidiar con esto es llamar al método find en el repositorio como es normal, y luego en la capa de aplicación, asigne cada agregado de cliente a un DTO de CustomerSearchResult / CustomerInfo y envíelo de vuelta al cliente.

Pero mi problema con esto es el rendimiento; cada agregado de cliente puede requerir múltiples consultas para completar todas las asociaciones. Así que si mis criterios de búsqueda coincidieron con 50 clientes, eso es un éxito en la base de datos para recuperar datos potencialmente que ni siquiera voy a necesitar.

La otra cuestión es que tal vez desee incluir datos resumidos sobre el cliente que están fuera del límite de la raíz agregada del Cliente, como la fecha del último pedido realizado, por ejemplo. El pedido tiene su propio agregado y, por lo tanto, para obtener la información del pedido del cliente, tendría que llamar al OrderRepository, también degradando el rendimiento.

Así que ahora creo que me quedan dos opciones:

  1. Agregue un método Find adicional al CustomerRepository que devuelve una lista de estos objetos de resumen haciendo uno consulta eficiente.

  2. Cree un CustomerInfoRepository creado específicamente para leer, que solo tenga el método find descrito en 1.

Pero ambos sienten que voy en contra de los principios del DDD. Mis repositorios heredan de una base genérica: Repositorio donde T: IAggregateRoot. Estos summary info object no son agregados an, y son de un tipo diferente a T, por lo que realmente #1 va en contra del diseño.

Quizás para #2 crearía un resumen SearchRepository sin la restricción IAggregateRoot?

Hay muchos escenarios similares en mi dominio.

¿Cómo implementaría este escenario?

Gracias, Dave

Update

Después de leer la respuesta de Theo, creo que voy a ir con la opción #2 y crear un SearchRepository especializado dentro de mi infraestructura orientada hacia estos escenarios. La capa de aplicación (servicios WCF) puede llamar a estos repositorios que solo rellenan los DTO de resumen directamente en lugar de asignar entidades de dominio a DTO.

* * * * Actualizar 2 ****

Aunque pregunté esto hace más de un año, pensé que solo agregaría que desde entonces he descubierto CQRS que está dirigido a resolver este problema exacto. Udi Dahan (http://www.udidahan.com/) y Greg Young (http://codebetter.com/gregyoung/) han escrito mucho sobre ello. Si está creando una aplicación distribuida con DDD, CQRS es para usted!

Author: saggu, 2010-01-20

2 answers

Creo que solo desea mostrar información resumida. Estos bits de información resumida no son entidades u objetos de valor del modelo de dominio. Son solo información, nada más.

Es algo así como mostrar información de informes. Si me ocupara de esas cosas, no me apegaría al enfoque de DDD puro. Las opciones sugeridas están bien, porque es hacer su trabajo. DDD no debe ser tratado como dogma. Piensa fuera de la caja. Afloje un poco DDD.

Pero tenga en cuenta que solo está creando valores informativos fuera del modelo para mostrar el propósito. Por lo tanto, si un usuario selecciona un bit de información para realizar alguna operación con él (que se define en el modelo de dominio), debe extraer el identificador de los valores informativos y extraer la entidad/valor objeto/agregado de un repositorio.

Recomiendo encarecidamente este video: Eric Evans: Lo que he aprendido sobre DDD desde el libro. Si lees su libro, deberías ver todo el video. Preste mucha atención alrededor de las 30:00 horas, cuando el propio Eric Evans habla de agregados y se refiere al problema que tiene actualmente.

 25
Author: Theo Lenndorff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-03 18:14:23

Lo haría:

  1. Devuelve un objeto diferente que representa una vista de mi objeto para mostrar, por ejemplo, CustomerInfo.
  2. Devuelve una DataTable. A menudo, un contenedor genérico es la forma más fácil y mejor de hacerlo.

Si la T en su repositorio base genérico es un Cliente, entonces creo que está aplicando mal el concepto de raíces agregadas, aunque no soy un estricto Evansangelist. Diseñaría un repositorio para el Cliente que devolviera cualquier dato que lógicamente o agrupa cómodamente con el cliente, incluidas las tablas de datos o los objetos de solo lectura que son vistas de los datos del cliente.

 1
Author: Jamie Ide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-20 00:23:56