O que um repositório realmente deve fazer?

15

Ouvi muito do padrão de repositório, mas não entendi o que um repositório deveria realmente fazer. Quando digo "o que um repositório realmente deve fazer", estou preocupado principalmente com quais métodos ele deve fornecer. Por exemplo, um repositório deve realmente fornecer métodos CRUD, ou deve fornecer algum tipo diferente de método?

Quero dizer, os repositórios devem conter lógica de negócios ou devem simplesmente conter a lógica para se comunicar com o armazenamento de dados e gerenciar as entidades a serem salvas ou carregadas?

Também ouvi dizer que repositórios são unidades de persistência para agregados. Mas como é isso? Não entendo como isso funciona na prática. Eu pensei que deveríamos ter apenas uma interface IRepositoryque contenha os métodos CRUD e, para qualquer entidade, a implementação simplesmente conteria a lógica para salvar e recuperar esse tipo do armazenamento de dados.

user1620696
fonte
4
"os repositórios devem conter lógica de negócios" - não.
ozz
1
Aqui está a minha resposta para uma pergunta relacionada sobre SO
Eric King
2
Eu acho que você está sendo pego pela palavra "deveria" - o repositório é um padrão específico, você fala como se houvesse uma maneira de fazer um repo que fosse a melhor maneira de fazer um repo; isso é um equívoco, pois existe apenas uma maneira de fazer um repo, qualquer outra coisa não seria um repo. Como tal, o padrão de repo possui pontos fortes e fracos, mas não há várias abordagens para um repo. No entanto, existem várias maneiras de interagir com os dados, dos quais um repo é apenas um. Leia aqui para outras abordagens de interação de dados
Jimmy Hoffa

Respostas:

13

Bem, você pode ver um bom exemplo no Spring Data Framework, que é baseado no conceito de repositórios.

Lá você verá repositórios que lidam apenas com o armazenamento de dados e raramente contêm lógica comercial (isso é reservado para a camada de serviço). Então, por exemplo, dê uma olhada no design deles e verá que eles têm uma interface CRUDRepository que expõe métodos para criar, destruir e recuperar entidades (entre outras coisas). Há também um PagingAndSortingRepository que adiciona funcionalidade extra para exatamente isso, resultados de classificação e paginação, etc., etc.

Portanto, essa estrutura é talvez um bom lugar para estudar um bom design de repositório.

Até onde eu sei, muitos dos conceitos implementados pelo Spring Data Framework vêm de um ótimo livro chamado Design Orientado a Domínio: Combatendo a Complexidade no Coração do Software , o livro tem uma seção inteira dedicada ao design do Repositório.

Você pode obter uma cópia dele.

Um pequeno trecho do livro explica:

O padrão REPOSITORY é uma estrutura conceitual simples para encapsular essas soluções e trazer de volta nosso foco no modelo.

Um REPOSITÓRIO representa todos os objetos de um determinado tipo como um conjunto conceitual (geralmente emulado). Ele age como uma coleção, exceto com capacidade de consulta mais elaborada. Objetos do tipo apropriado são adicionados e removidos, e o mecanismo por trás do REPOSITORY os insere ou os exclui do banco de dados. Essa definição reúne um conjunto coeso de responsabilidades por fornecer acesso às raízes dos AGREGADOS desde o início do ciclo de vida até o final.

Os clientes solicitam objetos do REPOSITORY usando métodos de consulta que selecionam objetos com base nos critérios especificados pelo cliente, geralmente o valor de determinados atributos. O REPOSITORY recupera o objeto solicitado, encapsulando o mecanismo de consultas ao banco de dados e o mapeamento de metadados. Os repositórios podem implementar uma variedade de consultas que selecionam objetos com base em qualquer critério que o cliente exija. Eles também podem retornar informações resumidas, como uma contagem de quantas instâncias atendem a alguns critérios. Eles podem até retornar cálculos de resumo, como o total em todos os objetos correspondentes de algum atributo numérico.

Um REPOSITÓRIO elimina uma carga enorme do cliente, que agora pode conversar com uma interface simples e reveladora de intenção e pedir o que ele precisa em termos de modelo. Para suportar tudo isso, é necessária muita infraestrutura técnica complexa, mas a interface é simples e conceitualmente conectada ao modelo de domínio.

Portanto:

Para cada tipo de objeto que precisa de acesso global, crie um objeto que possa fornecer a ilusão de uma coleção na memória de todos os objetos desse tipo. Configure o acesso através de uma interface global conhecida.

Forneça métodos para adicionar e remover objetos, que encapsularão a inserção ou remoção real de dados no armazenamento de dados. Forneça métodos que selecionem objetos com base em alguns critérios e retornem objetos totalmente instanciados ou coleções de objetos cujos valores de atributo atendam aos critérios, encapsulando assim a tecnologia real de armazenamento e consulta. Forneça REPOSITÓRIOS apenas para raízes AGREGADAS que realmente precisem de acesso direto. Mantenha o cliente focado no modelo, delegando todo o armazenamento de objetos e acesso aos REPOSITÓRIOS.

edalorzo
fonte
4

Ele não deve fornecer uma interface CRUD direta nem lógica de negócios. Ele medeia entre a lógica de negócios e o banco de dados. A interface deve estar em termos de lógica de negócios, mas não executar a própria lógica de negócios, mais como uma primitiva de lógica de negócios. Como exemplo, digamos que você iria construir um sistema de email, você tem usuários e mensagens. Seu repositório forneceria operações CRUD básicas para usuários e mensagens, mas também forneceria visualizações filtradas de mensagens como GetUsersNewMessages (usuário) ou GetSearchedMessages (usuário, searchTerms).

A idéia é que o Repositório oculte como o armazenamento é implementado e forneça uma interface limpa que permita acesso rápido e flexível aos dados. Manter as operações em termos de alto nível do que deveria acontecer e não de como significa que você tem mais flexibilidade para implementá-las da melhor maneira para o armazenamento subjacente.

pedregoso
fonte