O padrão Repository para persistência de dados.

Há muito tempo atrás, em uma terra distante, escrevi um artigo explicando a diferença e a abordagem nos padrões mais comuns de persistência de dados: Active Record e DAO. Que na verdade era parte de uma série sobre boas práticas em programação.

Lá no fim, disse que escreveria sobre outro padrão, o Repository. Muito tempo se passou, e eu me esqueci disso. Mas o Frederico me lembrou (obrigado), então aqui estou.

O padrão Repository (ou Repositório) tem, em uma abordagem muito semelhante ao DAO, a responsabilidade de representar a camada de dados na aplicação. A semelhança entre DAO e Repository é tanta que em muitas abordagens são programados da mesma forma, ou simplesmente delegam do Repositório para o DAO. Em casos de migração onde se tenta “uma abordagem mais Domain Driven” simplesmente refatoram os DAO para se chamarem Repositório.

Porem os padrões atuam em camadas distintas da aplicação, e podem até mesmo coexistir.

 

Padrão de projeto Repository explicado

 

 

Os Repositórios pertencem ao modelo da aplicação, são parte de camada de negócios complementando o Model e fornecendo estes objetos as outras camadas (como Controle e Apresentação, se aplicável) e recuperando estes do banco de dados.

Porem, sendo parte do modelo, os repositórios não conhecem detalhes de infra-estrutura da aplicação (banco de dados, http, etc), e é na área de infra em que atuam os DAOs. Assim o DAO tem o trabalho de traduzir as chamadas à persistência em chamadas de infra, sejam elas banco de dados, webservices, arquivos em disco ou outra abordagem qualquer.

A confusão acontece por que na maioria dos projetos toda persistência e acesso a dados é feita através de um , e apenas um, banco de dados. E , mais ainda, os frameworks atuais abstraem e traduzem os objetos em relacionamento de forma tão simples que o DAO simplesmente passa ao framework o que recebe e retorna o resultado.

Dessa forma , em sistema onde temos um modelo Usuário, teríamos um UsuárioRepository atuando no modelo. Este repositório faria a interface de criar, recurar e guardar os Usuários, e pode incluir métodos específicos, como filtros ou pré-preencher os usuários.

Mas o repositório não sabe de infra, então ele poderia ter de delegar a um DAO as chamadas. Desta forma os DAO apenas implementam as chamadas mais genéricas como select, insert, update e delete. Em um framework atual, que oferece essa interface de forma simples, o repositório poderia passar a chamada ao framework, se a configuração não passar pelo repositório.

Então, ao receber uma chamada o Repositório valida isto de acordo com as regras de negócio que o cabe(já que a maior parte pode estar no próprio modelo), e pede à camada de infra esses dados. A camada de infra trata essa chamada no cabe à infra ( valida, encode, traduz campos…) e acessa a persistência. Ela trata o retorna da persistência no que vale a infra (array para objetos, encoding, joins…) e devolve ao repositório. O repositório então trata este retorno o que diz respeito ao negócio, criando objetos, cálculos e o que for aplicável.

Como disse, em muitos projetos isso gera classes desnecessárias e o mal uso dos repositórios. Uma forma diferente de lidar com isso é que os Repositórios são interfaces, implementadas pelos próprios DAO(o contrário não é valido), pois do ponto de vista de modelagem o modelo continua acessando o Repositório. E pode-se criar um repositório implementado aonde preciso, antes do DAO. Esta forma parece um pouco mais complexo, mas é ate mais simples.

O que temos afinal é: O Repositório é uma camada de negócio da aplicação, responsável por manter e persistir os objetos de Modelo, enquanto isto não envolver infra. Quando tratar de infra, esse trabalho é delegado aos DAO ou diretamente ao framework, caso este seja bem abstraído.

3 ideias sobre “O padrão Repository para persistência de dados.

  1. Olá Julio,

    Entendo sua dúvida, muito válido, essa abordagem é um pouco confusa na verdade.

    O DAO pode retorna um usuário por conta própria (criando com new, setters e etc) e o repositório pode aplicar regras específicas, ou um aggregate especifico (um ListaDeUsuarios ao invés de Usuario[] por exemplo).

    O repositório está muito ligado ao negócio, ao “nomes”, então pode até delegar diretamente servindo mais para usar a nomenclatura do negócio.

    Vale uma olhada em DDD em geral.

  2. ola, estou iniciando um projeto web em java e gostaria de saber se poderia me esclarecer a seguinte dúvida sobre o padrão:

    Citando o exemplo, que tipo de objeto o UsuarioDAO retorna em um getByID() por exemplo? imagino que nao deva ser o mesmo objeto Usuario definido no model, certo? que objeto seria este e como eu o transformaria dentro do Model em um objeto Usuario? espero que eu tenha conseguido explicar minha dúvida. Abracos e parabens pelo post.

Comentários encerrados.