Actualmente estoy estudiando DDD y tengo algunas preguntas sobre cómo administrar los repositorios con DDD.
En realidad, he encontrado dos posibilidades:
El primero
La primera forma de administrar los servicios que he leído es inyectar un repositorio y un modelo de dominio en un servicio de aplicación.
De esta manera, en uno de los métodos de servicio de la aplicación, llamamos a un método de servicio de dominio (verificando las reglas de negocio) y si la condición es buena, el repositorio se llama a un método especial para persistir / recuperar la entidad de la base de datos.
Una forma simple de hacer esto podría ser:
class ApplicationService{
constructor(domainService, repository){
this.domainService = domainService
this.repository = repository
}
postAction(data){
if(this.domainService.validateRules(data)){
this.repository.persist(new Entity(data.name, data.surname))
}
// ...
}
}
Segundo
La segunda posibilidad es inyectar el repositorio dentro del dominioServicio, y usar el repositorio solo a través del servicio de dominio:
class ApplicationService{
constructor(domainService){
this.domainService = domainService
}
postAction(data){
if(this.domainService.persist(data)){
console.log('all is good')
}
// ...
}
}
class DomainService{
constructor(repository){
this.repository = repository
}
persist(data){
if(this.validateRules(data)){
this.repository.save(new Entity(data.name))
}
}
validateRules(data){
// returns a rule matching
}
}
A partir de ahora, no puedo distinguir cuál es el mejor (si hay uno mejor) o qué implican ambos en su contexto.
¿Me puede dar un ejemplo donde uno podría ser mejor que el otro y por qué?
fuente
Respuestas:
La respuesta breve es: puede usar repositorios de un servicio de aplicación o un servicio de dominio, pero es importante considerar por qué y cómo lo está haciendo.
Propósito de un servicio de dominio
Los Servicios de dominio deben encapsular conceptos / lógica de dominio, como tal, el método de servicio de dominio:
no pertenece a un servicio de dominio, ya
persist
que no forma parte del lenguaje omnipresente y la operación de persistencia no forma parte de la lógica empresarial del dominio.En general, los servicios de dominio son útiles cuando tiene reglas / lógica de negocios que requieren coordinar o trabajar con más de un agregado. Si la lógica solo involucra un agregado, debe estar en un método en las entidades de ese agregado.
Repositorios en Servicios de Aplicación
Entonces, en ese sentido, en su ejemplo, prefiero su primera opción, pero incluso allí hay margen de mejora, ya que su servicio de dominio está aceptando datos sin procesar de la API, ¿por qué el servicio de dominio debe conocer la estructura de
data
? Además, los datos parecen estar relacionados solo con un agregado único, por lo que hay un valor limitado en el uso de un servicio de dominio para eso; en general, pondría la validación dentro del constructor de la entidad. p.ejy lanzar una excepción si no es válida. Dependiendo del marco de su aplicación, puede ser simple tener un mecanismo consistente para detectar la excepción y asignarla a la respuesta apropiada para el tipo de API; por ejemplo, para una API REST, devuelva un código de estado 400.
Repositorios en Servicios de Dominio
A pesar de lo anterior, a veces es útil inyectar y usar un repositorio en un servicio de dominio, pero solo si sus repositorios se implementan de modo que acepten y devuelvan solo raíces agregadas, y también cuando está abstrayendo lógica que involucra múltiples agregados. p.ej
la implementación del servicio de dominio se vería así:
Conclusión
La clave aquí es que el servicio de dominio encapsula un proceso que es parte del lenguaje ubicuo. Para cumplir su función, necesita usar repositorios, y está perfectamente bien hacerlo.
Pero agregar un servicio de dominio que envuelve un repositorio con un método llamado
persist
agrega poco valor.Sobre esa base, si el servicio de su aplicación expresa un caso de uso que solo requiere trabajar con un único agregado, no hay ningún problema al usar el repositorio directamente desde el servicio de la aplicación.
fuente
Hay un problema con la respuesta aceptada:
El modelo de dominio no puede depender del repositorio y el servicio de dominio es parte del modelo de dominio -> el servicio de dominio no debe depender del repositorio.
Lo que debe hacer en su lugar es ensamblar todas las entidades necesarias para la ejecución de la lógica de negocios que ya están en el servicio de aplicaciones y luego simplemente proporcionar a sus modelos objetos instanciados.
Según su ejemplo, podría verse así:
Entonces, regla general: el modelo de dominio no depende de las capas externas
Aplicación vs Servicio de dominio De este artículo :
Los servicios de dominio son muy granulares, ya que los servicios de aplicaciones son una fachada destinada a proporcionar una API.
Los servicios de dominio contienen lógica de dominio que no se puede colocar naturalmente en una entidad u objeto de valor, mientras que los servicios de aplicación organizan la ejecución de la lógica de dominio y no implementan ellos mismos ninguna lógica de dominio.
Los métodos de servicio de dominio pueden tener otros elementos de dominio como operandos y valores de retorno, mientras que los servicios de aplicación operan sobre operandos triviales como valores de identidad y estructuras de datos primitivas.
Los servicios de aplicación declaran dependencias de los servicios de infraestructura necesarios para ejecutar la lógica de dominio.
fuente
Ninguno de sus patrones es bueno a menos que sus servicios y objetos encapsulen un conjunto coherente de responsabilidad.
En primer lugar, diga cuál es su objeto de dominio y hable sobre lo que puede hacer dentro del idioma del dominio. Si puede ser válido o no válido, ¿por qué no tener esto como una propiedad del objeto de dominio en sí?
Si, por ejemplo, la validez de los objetos solo tiene sentido en términos de otro objeto, entonces tal vez tenga una 'regla de validación X para los objetos de dominio' de responsabilidad que puede encapsularse en un conjunto de servicios.
¿Validar un objeto necesita almacenarlo dentro de las reglas de su negocio? Probablemente no. La responsabilidad de "almacenar objetos" normalmente va en un objeto de repositorio separado.
Ahora tiene una operación que desea realizar que cubre un rango de responsabilidades, crear un objeto, validarlo y, si es válido, almacenarlo.
¿Es esta operación intrínseca al objeto de dominio? Luego hazlo parte de ese objeto, es decir
ExamQuestion.Answer(string answer)
¿Encaja con alguna otra parte de tu dominio? ponlo ahí
Basket.Purchase(Order order)
¿Prefieres hacer los servicios ADM REST? OK entonces.
fuente