Atualmente, estou estudando o DDD e tenho algumas perguntas sobre como gerenciar repositórios com o DDD.
Na verdade, encontrei duas possibilidades:
Primeiro
A primeira maneira de gerenciar serviços que li é injetar um repositório e um modelo de domínio em um serviço de aplicativo.
Dessa forma, em um dos métodos de serviço de aplicativo, chamamos um método de serviço de domínio (verificando regras de negócios) e, se a condição for boa, o repositório será chamado em um método especial para persistir / recuperar a entidade do banco de dados.
Uma maneira simples de fazer isso pode 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))
}
// ...
}
}
O segundo
A segunda possibilidade é injetar o repositório dentro do domainService e usar apenas o repositório através do serviço de domínio:
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 agora, não sou capaz de distinguir qual é o melhor (se houver um) ou o que eles implicam no seu contexto.
Você pode me dar um exemplo onde um poderia ser melhor que o outro e por quê?
fonte
Respostas:
A resposta curta é - você pode usar repositórios de um serviço de aplicativo ou de um serviço de domínio - mas é importante considerar por que e como você está fazendo isso.
Objetivo de um serviço de domínio
Os Serviços de Domínio devem encapsular conceitos / lógica de domínio - como tal, o método de serviço de domínio:
não pertence a um serviço de domínio, pois
persist
não faz parte da linguagem onipresente e a operação de persistência não faz parte da lógica de negócios do domínio.Geralmente, os serviços de domínio são úteis quando você possui regras / lógica de negócios que exigem coordenação ou trabalho com mais de um agregado. Se a lógica envolver apenas um agregado, ela deve estar em um método nas entidades desse agregado.
Repositórios no Application Services
Portanto, nesse sentido, no seu exemplo, prefiro a sua primeira opção - mas mesmo que haja espaço para melhorias, pois o serviço de domínio está aceitando dados brutos da API - por que o serviço de domínio deve saber sobre a estrutura de
data
?. Além disso, os dados parecem estar relacionados apenas a um único agregado, portanto, há um valor limitado no uso de um serviço de domínio para isso - geralmente eu colocaria a validação dentro do construtor da entidade. por exemploe lance uma exceção se for inválida. Dependendo da estrutura do aplicativo, pode ser simples ter um mecanismo consistente para capturar a exceção e mapeá-la para a resposta apropriada para o tipo de API - por exemplo, para uma API REST, retorne um código de status 400.
Repositórios nos Serviços de Domínio
Não obstante o acima, às vezes é útil injetar e usar um repositório em um serviço de domínio, mas apenas se seus repositórios forem implementados de forma que aceitem e retornem apenas raízes agregadas, e também onde você está abstraindo a lógica que envolve várias agregações. por exemplo
a implementação do serviço de domínio seria semelhante a:
Conclusão
A chave aqui é que o serviço de domínio encapsula um processo que faz parte da linguagem onipresente. Para cumprir seu papel, ele precisa usar repositórios - e é perfeitamente bom fazê-lo.
Mas adicionar um serviço de domínio que agrupe um repositório com um método chamado
persist
agrega pouco valor.Nessa base, se seu serviço de aplicativo estiver expressando um caso de uso que exige trabalhar apenas com um único agregado, não haverá problema em usar o repositório diretamente do serviço de aplicativo.
fonte
Há um problema com a resposta aceita:
O modelo de domínio não pode depender do repositório e o serviço de domínio faz parte do modelo de domínio -> o serviço de domínio não deve depender do repositório.
Em vez disso, o que você deve fazer é montar todas as suas entidades necessárias para a execução da lógica de negócios já no serviço de aplicativo e apenas fornecer aos seus modelos objetos instanciados.
Com base no seu exemplo, pode ser assim:
Portanto, regra geral: o modelo de domínio não depende das camadas externas
Aplicação vs serviço Domínio A partir deste artigo :
Os serviços de domínio são muito granulares, onde, como serviços de aplicativos, é uma fachada destinada a fornecer uma API.
Os serviços de domínio contêm lógica de domínio que naturalmente não pode ser colocada em uma entidade ou objeto de valor, enquanto os serviços de aplicativos orquestram a execução da lógica de domínio e não implementam eles próprios nenhuma lógica de domínio.
Os métodos de serviço de domínio podem ter outros elementos de domínio como operandos e retornar valores, enquanto os serviços de aplicativos operam com operandos triviais, como valores de identidade e estruturas de dados primitivas.
Os serviços de aplicativo declaram dependências nos serviços de infraestrutura necessários para executar a lógica do domínio.
fonte
Nenhum de seus padrões é bom, a menos que seus serviços e objetos encapsulem algum conjunto coerente de responsabilidade.
Primeiro, diga qual é o objeto do seu domínio e fale sobre o que ele pode fazer no idioma do domínio. Se pode ser válido ou inválido, por que não ter isso como uma propriedade do próprio objeto de domínio?
Se, por exemplo, a validade dos objetos só faz sentido em termos de outro objeto, talvez você tenha uma 'regra de validação X para objetos de domínio' que pode ser encapsulada em um conjunto de serviços.
A validação de um objeto requer armazená-lo dentro das regras de negócios? Provavelmente não. A responsabilidade de 'armazenar objetos' normalmente fica em um objeto de repositório separado.
Agora você tem uma operação que deseja executar que abrange uma gama de responsabilidades, cria um objeto, valida e, se válido, armazena.
Esta operação é intrínseca ao objeto do domínio? Em seguida, faça parte desse objeto, ou seja,
ExamQuestion.Answer(string answer)
Isso se encaixa com alguma outra parte do seu domínio? coloque isso lá
Basket.Purchase(Order order)
Você prefere os serviços ADM REST? OK então.
fonte