Os serviços são de três tipos: Serviços de Domínio , Serviços de Aplicativo e Serviços de Infraestrutura .
- Serviços de Domínio : Encapsula a
lógica de negócios que não se encaixa naturalmente em um objeto de domínio e NÃO são operações CRUD típicas - elas pertenceriam a um Repositório .
- Serviços de aplicativos : Usado por consumidores externos para conversar com seu sistema (pense em Serviços da Web ). Se os consumidores precisarem acessar operações CRUD, eles serão expostos aqui.
- Serviços de infraestrutura : Usado para abstrair preocupações técnicas (por exemplo, MSMQ, provedor de email, etc.).
Manter os Serviços de Domínio junto com seus Objetos de Domínio é sensato - todos eles são focados na lógica do domínio. E sim, você pode injetar Repositórios nos seus Serviços.
O Application Services normalmente usa os Serviços de Domínio e os Repositórios para lidar com solicitações externas.
Espero que ajude!
(Se você não quiser ler, há um resumo na parte inferior :-)
Eu também lutei com a definição precisa de serviços de aplicativos. Embora a resposta de Vijay tenha sido muito útil para o meu processo de pensamento há um mês, cheguei a discordar de parte dele.
Outros recursos
Há muito pouca informação sobre serviços de aplicativos. Assuntos como raízes agregadas, repositórios e serviços de domínio são discutidos extensivamente, mas os serviços de aplicativos são mencionados apenas brevemente ou são excluídos por completo.
O artigo da MSDN Magazine Uma Introdução ao Design Orientado a Domínio descreve os serviços de aplicativo como uma maneira de transformar e / ou expor seu modelo de domínio a clientes externos, por exemplo, como um serviço WCF. É assim que o Vijay também descreve os serviços de aplicativos. Desse ponto de vista, os serviços de aplicativos são uma interface para o seu domínio .
Os artigos de Jeffrey Palermo sobre a Onion Architecture (parte um , dois e três ) são uma boa leitura. Ele trata os serviços de aplicativo como conceitos no nível do aplicativo , como uma sessão do usuário. Embora isso esteja mais próximo da minha compreensão dos serviços de aplicativos, ainda não está alinhado com meus pensamentos sobre o assunto.
Meus pensamentos
Passei a pensar nos serviços de aplicativos como dependências fornecidas pelo aplicativo . Nesse caso, o aplicativo pode ser um aplicativo de desktop ou um serviço WCF.
Domínio
Hora de um exemplo. Você começa com o seu domínio. Todas as entidades e quaisquer serviços de domínio que não dependem de recursos externos são implementados aqui. Quaisquer conceitos de domínio que dependem de recursos externos são definidos por uma interface. Aqui está um layout de solução possível (nome do projeto em negrito):
As classes
Product
eProductFactory
foram implementadas na montagem principal. OIProductRepository
é algo que provavelmente é apoiada por um banco de dados. A implementação disso não é uma preocupação do domínio e, portanto, é definida por uma interface.Por enquanto, vamos nos concentrar no
IExchangeRateService
. A lógica de negócios para este serviço é implementada por um serviço da web externo. No entanto, seu conceito ainda faz parte do domínio e é representado por essa interface.A infraestrutura
A implementação das dependências externas faz parte da infraestrutura do aplicativo:
XEExchangeRateService
implementa oIExchangeRateService
serviço de domínio comunicando-se com xe.com . Essa implementação pode ser usada por seus aplicativos que utilizam seu modelo de domínio, incluindo o conjunto da infraestrutura.Inscrição
Observe que ainda não mencionei os serviços de aplicativos. Vamos ver isso agora. Digamos que queremos fornecer uma
IExchangeRateService
implementação que use um cache para pesquisas rápidas. O esboço dessa classe de decorador pode ser assim.Observe o
ICache
parâmetro? Esse conceito não faz parte do nosso domínio, portanto não é um serviço de domínio. É um serviço de aplicativo . É uma dependência de nossa infraestrutura que pode ser fornecida pelo aplicativo. Vamos apresentar um aplicativo que demonstra isso:Tudo isso se reúne no aplicativo como este:
Resumo
Um aplicativo completo consiste em três camadas principais:
A camada de domínio contém as entidades de domínio e os serviços de domínio autônomo. Quaisquer conceitos de domínio (incluindo serviços de domínio, mas também repositórios) que dependem de recursos externos, são definidos por interfaces.
A camada de infraestrutura contém a implementação das interfaces da camada de domínio. Essas implementações podem introduzir novas dependências fora do domínio que precisam ser fornecidas ao aplicativo. Estes são os serviços de aplicativos e são representados por interfaces.
A camada de aplicativo contém a implementação dos serviços de aplicativo. A camada de aplicativo também pode conter implementações adicionais de interfaces de domínio, se as implementações fornecidas pela camada de infraestrutura não forem suficientes.
Embora essa perspectiva possa não corresponder à definição geral de serviços DDD, ela separa o domínio do aplicativo e permite compartilhar o conjunto de domínio (e infraestrutura) entre vários aplicativos.
fonte
IExchangeRateService
interface? Este é um conceito de domínio, ou seja, algo que está incluído na linguagem onipresente do seu cliente. Outras partes do seu domínio podem depender desse serviço, e é por isso que sua interface é definida na camada de domínio. Porém, como sua implementação envolve um serviço da web externo, a classe de implementação reside na camada de infraestrutura. Dessa forma, a camada de domínio se preocupa apenas com a lógica de negócios.ExchangeRate
instância, que contém uma moeda base, uma moeda contrária e o valor da taxa de câmbio entre essas duas moedas. Esses valores fortemente relacionados representam o conceito de 'taxa de câmbio' do domínio, portanto, eles vivem na camada do domínio. Embora possa parecer um DTO simples, no DDD é chamado de Objeto de Valor e pode conter lógica de negócios adicional para comparar ou transformar instâncias.O melhor recurso que me ajudou a entender a diferença entre um Serviço de Aplicativo e um Serviço de Domínio foi a implementação em java do exemplo de carga de Eric Evans, encontrado aqui . Se você descarregá-lo, poderá verificar os internos do RoutingService (um Serviço de Domínio) e do BookingService, CargoInspectionService (que são Serviços de Aplicativo).
Meu momento de 'aha' foi desencadeado por duas coisas:
Lendo a descrição dos Serviços no link acima, mais precisamente esta frase:
Lendo esta postagem do blog , especialmente esta parte:
fonte
Serviço de domínio é a extensão do domínio. Isso deve ser visto apenas no contexto do domínio. Esta não é uma ação do usuário, como por exemplo, fechar conta ou algo assim. O serviço de domínio se encaixa onde não há estado. Caso contrário, seria um objeto de domínio. O serviço de domínio faz algo que só faz sentido quando realizado com outros colaboradores (objetos de domínio ou outros serviços). E que fazer sentido é responsabilidade de outra camada.
Serviço de aplicativo é a camada que inicializa e supervisiona a interação entre os objetos e serviços do domínio. O fluxo geralmente é assim: obtenha o objeto (ou objetos) do domínio do repositório, execute uma ação e coloque-os lá (ou não). Ele pode fazer mais - por exemplo, pode verificar se um objeto de domínio existe ou não e lançar exceções de acordo. Portanto, ele permite que o usuário interaja com o aplicativo (e provavelmente é daí que o nome se origina) - manipulando objetos e serviços de domínio. Os serviços de aplicativo geralmente devem representar todos os casos de uso possíveis. Provavelmente, a melhor coisa que você pode fazer antes de pensar no domínio é criar interfaces de serviço de aplicativo, o que lhe dará uma visão muito melhor do que você realmente está tentando fazer. Ter esse conhecimento permite que você se concentre no domínio.
Os repositórios geralmente podem ser injetados nos serviços de domínio, mas esse é um cenário bastante raro. É a camada de aplicação que faz isso na maioria das vezes.
fonte
No Red Book (Implementando o Design Orientado a Domínio, de Vaughn Vernon), é assim que eu entendo os conceitos:
Objetos de domínio ( entidades e objetos de valor ) encapsulam o comportamento exigido pelo (sub) domínio, tornando-o natural, expressivo e compreensível.
Os serviços de domínio encapsulam comportamentos que não cabem em um único objeto de domínio. Por exemplo, uma biblioteca de livros que empresta a
Book
aClient
(com asInventory
alterações correspondentes ) pode fazê-lo a partir de um serviço de domínio.Os serviços de aplicativo lidam com o fluxo de casos de uso, incluindo quaisquer preocupações adicionais necessárias sobre os domínios. Geralmente expõe esses métodos por meio de sua API, para consumo por clientes externos. Para desenvolver nosso exemplo anterior, nosso serviço de aplicativo pode expor um método
LendBookToClient(Guid bookGuid, Guid clientGuid)
que:Client
.Book
.Client
eBook
) para manipular a lógica real do domínio de emprestar o livro ao cliente. Por exemplo, imagino que confirmar a disponibilidade do livro é definitivamente parte da lógica do domínio.Um serviço de aplicativo geralmente deve ter um fluxo muito simples. Os fluxos complexos de serviços de aplicativos geralmente indicam que a lógica do domínio vazou do domínio.
Como você pode ver, o modelo de domínio permanece muito limpo dessa maneira e é fácil de entender e discutir com os especialistas em domínio, porque contém apenas suas próprias preocupações comerciais reais. O fluxo de aplicativos , por outro lado, também é muito mais fácil de gerenciar, pois é isento de preocupações com o domínio e se torna conciso e direto.
fonte
Millett, C (2010). Padrões profissionais de design do ASP.NET. Wiley Publishing. 92
fonte
Serviços de domínio : um serviço que expressa uma lógica comercial que não faz parte de nenhuma raiz agregada.
Você tem 2 agregados:
Product
que contém nome e preço.Purchase
que contém a data da compra, a lista de produtos solicitados com quantidade e preço do produto naquele momento e forma de pagamento.Checkout
não faz parte de nenhum desses dois modelos e é conceito nos seus negócios.Checkout
pode ser criado como um Serviço de Domínio que busca todos os produtos e calcula o preço total, paga o total chamando outro Serviço de DomínioPaymentService
com uma parte de implementação da Infraestrutura e converte-o emPurchase
.Serviços de aplicativos : um serviço que "orquestra" ou exercita métodos de domínio. Isso pode ser tão simples quanto apenas o seu controlador.
Este é o lugar onde você costuma fazer:
Você pode fazer validações aqui, como verificar se a
Product
é único. A menos que umProduct
ser exclusivo seja invariável, ele deve fazer parte do Serviço de Domínio que pode ser chamadoUniqueProductChecker
porque não pode fazer parte daProduct
classe e interage com vários Agregados.Aqui está um exemplo completo do projeto DDD: https://github.com/VaughnVernon/IDDD_Samples
Você pode encontrar muitos exemplos de Serviço de Aplicativo e alguns Serviços de Domínio
fonte
Pense em um Serviço de Domínio como um objeto que implementa lógica de negócios ou lógica relacionada a regras de negócios em objetos de domínio. Essa lógica é difícil de se encaixar nos mesmos objetos de domínio e também não causa alteração de estado do serviço de domínio (serviço de domínio é um objeto sem um "estado" ou melhor sem um estado que tenha um significado comercial) mas, eventualmente, altere o estado apenas dos objetos de domínio nos quais opera.
Enquanto um Serviço de Aplicativo implementa lógica de nível de aplicativo como interação do usuário, validação de entrada, lógica não relacionada aos negócios, mas a outras preocupações: autenticação, segurança, email, etc., limitando-se a simplesmente usar serviços expostos por objetos de domínio.
Um exemplo disso pode ser o seguinte cenário pensado apenas para fins explicativos: temos que implementar um aplicativo utilitário domótico muito pequeno que execute uma operação simples, ou seja, "acenda as luzes, quando alguém abre a porta do quarto de uma casa para entrar entre e apague a luz quando fechar a porta que sai da sala ".
Para simplificar muito, consideramos apenas duas entidades de domínio:
Door
eLamp
cada uma delas possui dois estados, respeitosamenteopen/closed
eon/off
métodos específicos para operar alterações de estado nelas.Nesse caso, precisamos de um serviço de domínio que execute a operação específica de acender a luz quando alguém abrir a porta do lado de fora para entrar em uma sala, porque a porta e os objetos da lâmpada não podem implementar essa lógica da maneira que consideramos adequada. a sua natureza .
Podemos chamar nosso serviço de domínio como
DomoticDomainService
e implementar 2 métodos:OpenTheDoorAndTurnOnTheLight
eCloseTheDoorAndTurnOffTheLight
, esses 2 métodos alteram, respectivamente, o estado de ambos os objetosDoor
eLamp
paraopen/on
eclosed/off
.O estado de entrada ou saída de uma sala que não está presente no objeto de serviço de domínio e nos objetos de domínio, mas será implementado como simples interação do usuário por um serviço de aplicativo, que podemos chamar
HouseService
, que implementa alguns manipuladores de eventos comoonOpenRoom1DoorToEnter
eonCloseRoom1DoorToExit
assim por diante para cada sala (este é apenas um exemplo para fins de explicação ..) , que se preocupam respectivamente com os métodos de serviço de domínio de chamada para executar o comportamento assistido (não consideramos a entidadeRoom
porque é apenas um exemplo) .Este exemplo, longe de ser um aplicativo do mundo real bem projetado, tem o único objetivo (como foi dito mais vezes) de explicar o que é um Serviço de Domínio e sua diferença em relação a um Serviço de Aplicativo, espero que seja claro e útil.
fonte