Imaginemos que tengo Grupos y Usuarios y cuando el usuario quiere unirse a un grupo, llamo al método groupsService.AddUserToGroup (grupo, usuario). En DDD debería hacer group.JoinUser (usuario), que se ve bastante bien.
Pero DDD también lo alienta a usar servicios (sin estado) para realizar tareas, si la tarea en cuestión es demasiado compleja o no encaja en un modelo de entidad. Está bien tener servicios en la capa de dominio. Pero los servicios en la capa de dominio solo deben incluir la lógica empresarial. Las tareas externas y la lógica de la aplicación (como enviar un correo electrónico), por otro lado, deben usar el servicio de dominio en la capa de aplicación, en el que podría tener un servicio separado (aplicación) envolviéndolo, por ejemplo.
El problema aparece si hay algunas reglas de validación para agregar un usuario ...
¡Las reglas de validación pertenecen al modelo de dominio! Deben encapsularse dentro de los objetos de dominio (entidades, etc.).
... o algunas tareas externas deben iniciarse cuando el usuario se agrega al grupo. Tener estas tareas llevará a que la entidad tenga dependencias externas.
Si bien no sé de qué tipo de tarea externa está hablando, supongo que es algo así como enviar un correo electrónico, etc. Pero esto no es realmente parte de su modelo de dominio. Debería vivir en la capa de aplicación y ser entregado allí en mi humilde opinión. Puede tener un servicio en su capa de aplicación que opera en servicios de dominio y entidades para realizar esas tareas.
Pero el hecho de que una entidad dependa de algunos servicios / clases externos no me parece tan bueno y "natural".
No es natural y no debería estar sucediendo. La entidad no debe saber sobre cosas que no son su responsabilidad. Los servicios deben usarse para orquestar las interacciones entre entidades.
¿Cuál es la forma correcta de lidiar con esto en DDD?
En su caso, la relación probablemente debería ser bidireccional. Si el usuario se une al grupo o si el grupo toma al usuario depende de su dominio. ¿El usuario se une al grupo? ¿O el usuario se agrega a un grupo? ¿Cómo funciona en tu dominio?
De todos modos, tiene una relación bidireccional y, por lo tanto, puede determinar la cantidad de grupos a los que el usuario ya pertenece dentro del agregado de usuarios. Si pasa el usuario al grupo o el grupo al usuario es técnicamente trivial una vez que haya determinado la clase responsable.
La validación debe ser realizada por la entidad. Todo se llama desde un servicio de la capa de aplicación que también puede hacer cosas técnicas, como enviar correos electrónicos, etc.
Sin embargo, si la lógica de validación es realmente compleja, un servicio de dominio podría ser una mejor solución. En ese caso, encapsule las reglas de negocio allí y luego instálelo desde su capa de aplicación.
La forma en que abordaría el problema de la validación es de esta manera: cree un servicio de dominio llamado
MembershipService
:La entidad del Grupo necesita ser inyectada
IMemberShipService
. Esto se puede hacer a nivel de clase o de método. Supongamos que lo hacemos a nivel de método.El servicio de aplicación:
GroupService
puede inyectarse con laIMemberShipService
inyección de Constructor, que luego puede pasar alJoinUser
método de laGroup
clase.fuente