¿Está bien que las entidades accedan a los repositorys?

Acabo de empezar a trabajar con DDD, así que tal vez esta es una pregunta tonta …

¿Está bien que una entidad acceda a un repository (a través de una interfaz IRepository) para obtener un valor en tiempo de ejecución? Por ejemplo, quiero aplicar una selección “predeterminada” para una propiedad:

class Person { private Company _employer; public Company Employer { get { return _employer; } set { if(value != null) { _employer = value; } else { _employer = employerRepository.GetDefaultEmployer(); } } } ... } 

Mi pregunta es si hacer algo como esto es una violación horrible de los principios DDD. Y si no es así, mi siguiente pregunta sería ¿cuál es la mejor manera de proporcionar el repository para usar? ¿Debería suministrarse cuando se crea el objeto Persona?

Gracias p

no es una violación horrible de DDD es una horrible violación de … bueno … es simplemente horrible (digo esta lengua en la mejilla) :).

En primer lugar, su entidad se vuelve dependiente de tener un repository … eso no es ideal. Lo ideal sería que tu repository creara la Persona y luego le asignaras todo lo que necesita para ser efectivo en el contexto actual del dominio.

Entonces, cuando necesite una Persona, irá personRepository.GetPersonWithDefaultEmployer () y recuperará a una persona que tiene un empleador predeterminado poblado. El personRepository tendrá una dependencia en un repository de empleador y lo usará para poblar a la persona antes de devolverla.

 PersonReposotory : IPersonRepository { private readonly IEmployerRepository employerRepository; //use constructor injection to populate the EmployerRepository public PersonRepository(IEmployerRepository employerRepository) { this.employerRepository = employerRepository; } public person GetPersonWithDefaultEmployer(int personId) { Person person = GetPerson(personId); person.Employer = employerRepository.GetDefaultEmployer(personId); return person; } } 

La respuesta tipo a usted es el estándar. Depende .

Como regla general, nunca hagas esto. Mantenga sus entidades sin referencias a repositorys. [ poner el sombrero práctico ] En algunos casos raros y extremadamente raros en los que tiene una razón muy, muy, muy buena para hacer esto, agregue un gran comentario que explique por qué lo hace y hágalo: agregue la referencia o use el despacho doble para aprobar el repository [ sombrero apagado ]

Además, si desea seguir los principios DDD, se recomienda encarecidamente que tenga acceso a un experto de dominio y a un proceso iterativo de desarrollo (vea Eric Evans, lo que aprendí desde el libro ).

Con su experto en dominios debe definir contextos delimitadores y lo más importante, los agregados y sus raíces agregadas y sus entidades y objetos de valor. Bajar por el camino de DDD no es fácil al principio, pero las palabras clave están desbordadas.

Algunas cosas con respecto al código que publicaste:

  1. No se recomienda tener instaladores públicos en sus entidades. Use métodos que expresen mejor la intención.

  2. Si se crea una instancia de persona sin inicializar el campo _employer, el getter para la propiedad del Empleador devolverá nulo. Si luego establece el valor de la propiedad del Empleador en nulo, la próxima llamada al captador devolverá un valor no nulo. Esto es probablemente inesperado por los usuarios de su clase.

  3. La persona que llama configurando al Empleador de la Persona (ya sea por public setter o por método público) debe conocer la instancia exacta de la Compañía que debe establecer, incluso si es la predeterminada. Tal vez la persona que llama puede tener la referencia al repository.

  4. Dependiendo de su dominio concreto, la Compañía podría ser un objeto de valor. En ese caso, en lugar de inicializar el _empleador con nulo, podría inicializarlo con el valor predeterminado para el objeto de valor. Este podría ser el caso si solo tienes muy pocas compañías (1-2) y son inmutables y no tienen un comportamiento específico.

Creo que es fácil decir que una entidad no debería estar al tanto de los repositorys, sino difícil de poner en práctica. Especialmente cuando un agregado obtiene una gran colección de vo dentro de él, tenemos que refactorizarlo y delegar operaciones como agregar a algún servicio de dominio que realmente actúe como un repository para evitar la sobrecarga de cargar toda la colección en la memoria.
Pero no creo que sea razonable que las entidades conozcan los repositorys. Si tenemos que hacerlo, entonces usemos servicios de dominio en su lugar. También deberíamos considerar si un repository viola el principio de responsabilidad única : debería haber sido considerado como una colección de raíces agregadas, no como una fábrica normal.

¿Es realmente lo que se recomienda hacer ddd?

¿Y qué pasa si no tiene un repository en memoria, sino una base de datos relacional para su repository y desea obtener 1000 personas con su empleador? ¿Vas a hacer 1000 consultas a través de la llamada de EmployerRepository …?

Utilizaría NHibernate o cualquier ORM para ayudar a implementar personRepository. Con NHibernate, utilizaré Hibernate Query cerca de este: “from Person join fetch Employer” que cargará una instancia “Employer” en cada instancia de “Person”, con solo una consulta SQL.

¿Es una violación a DDD?

Antes que nada, creo que la entidad en sí misma y cómo ensamblar la entidad son 2 deberes de hecho. Entonces, idealmente, es mejor distribuirlos en diferentes clases. Pero eso depende de también.