Serviços de domínio como fachadas

8

Li o .NET-Driven Design com C #: Problem - Design - Solution e notei que o autor criou um serviço de domínio para cada raiz agregada.

No entanto, os serviços de domínio eram apenas fachadas para o repositório correspondente. Por exemplo, este é um exemplo de código do aplicativo de seu livro

public static class CompanyService
{
    private static ICompanyRepository repository;
    private static IUnitOfWork unitOfWork;

    static CompanyService()
    {
        CompanyService.unitOfWork = new UnitOfWork();
        CompanyService.repository = 
            RepositoryFactory.GetRepository<ICompanyRepository, 
            Company>(CompanyService.unitOfWork);
    }

    public static IList<Company> GetOwners()
    {
        return CompanyService.GetAllCompanies();
    }

    public static IList<Company> GetAllCompanies()
    {
        return CompanyService.repository.FindAll();
    }

    public static void SaveCompany(Company company)
    {
        CompanyService.repository[company.Key] = company;
        CompanyService.unitOfWork.Commit();
    }

    public static Company GetCompany(object companyKey)
    {
        return CompanyService.repository.FindBy(companyKey);
    }
}

Como você vê, quase todas as chamadas para os serviços são wrappers para chamadas de repositório. Esse é um bom padrão ao criar serviços de domínio?

Devemos sempre envolver nossos repositórios em serviços de domínio? Existe uma abordagem melhor?

Songo
fonte
O que você quer dizer com "melhor"?
Robert Harvey
A pergunta que eu faria aqui é "qual o valor que o CompanyService fornece sobre o CompanyRepository?". Se a resposta for nenhuma, a classe é intermediária - exclua-a sem piedade!
21813 MattDavey
@MattDavey Neste exemplo de código, posso ver que os métodos do repositório foram traduzidos para chamadas de domínio. Por exemplo, GetAllCompanies()envoltórios repository.FindAll(). No entanto, por que não posso simplesmente criar um método de repositório repository.GetAllCompanies()?!
Songo 21/02
@Ongo: depende se todos os outros métodos da sua camada de serviço também fazem uma chamada de método de repositório da mesma forma.
Robert Harvey

Respostas:

7

Um repositório deve ser uma abstração para seu armazenamento de dados e geralmente fornece recursos de recuperação de dados. Esse arranjo permite, por exemplo, alterar o armazenamento de dados para algum armazenamento de dados diferente (por exemplo, do Oracle para o SQL Server, embora na prática isso raramente aconteça), e a API do repositório ainda funcionará, se você não expôs nenhum detalhes específicos da implementação.

Uma camada de serviço, por outro lado, é uma API destinada a ser consumida por algum usuário ou agente externo e fornece serviços , não a recuperação de dados em si (embora possa fazer isso). Uma API de serviço pode desenhar em vários repositórios e executar transformações nos dados antes de servi-los ao cliente. Pode agrupar os dados em objetos personalizados ou fornecer recursos de paginação. Você pode fazer coisas em sua camada de serviço além do simples armazenamento e recuperação de dados.

Se você não precisar fornecer uma camada adicional de abstração além do que o seu Repositório fornece, talvez não precise de uma Camada de Serviço.

Robert Harvey
fonte
1
+1 Uma coisa chamou minha atenção no código que eu publiquei. O SaveCompanymétodo marca a unidade de trabalho. Se eu estivesse usando apenas um repositório, a chamada para confirmar todas as alterações estaria no repositório?
Songo 23/02
Sim, seria ...
Robert Harvey
2

À medida que seu aplicativo cresce, há operações complexas que sua camada de serviço pode quebrar e expor. É realmente uma fachada sobre o modelo de domínio. Por exemplo, em um aplicativo de vendas, você pode não se importar com o item de linha como um objeto discreto no modelo. Você só deseja adicionar itens a um carrinho, fazer check-out e imprimir uma fatura para o usuário após a aplicação de descontos.

Nos bastidores, provavelmente existem dezenas de objetos envolvidos na interação. O serviço pode projetar uma visualização nivelada do modelo de objeto para que, à medida que o modelo de domínio seja alterado nos bastidores, o cliente não seja impactado por essas alterações.

Michael Brown
fonte