Registrar    Login   Sobre o InfoBlogs  

Possibilidades de design no uso do seu Generic DAO    



Muitas vezes, quando estamos criando nosso sistema temos a tentação de criar o GenericDAO para não ter que ficar repetindo as operações CRUD e listagens.

O maior problema com o GenericDAO é que não necessariamente todas as operações fazem sentido para uma determinada classe. Daí o que fazer se, por exemplo, não faz sentido excluir um pagamento?

public class PagamentoDAO
          extends GenericDAO<Pagamento> {

     @Override
     public void excluir(Pagamento pagamento) {
         throw new UnsupportedOperationException();
     }
}

Não parece uma solução muito elegante, mas é um dos únicos jeitos de proibir uma operação declarada na classe mãe, e ainda assim, só funciona em tempo de execução. Esse é um dos principais motivos para muitos não gostarem de usar o GenericDAO e preferirem usar composição ao invés de herança. Mas como fazer para não repetir o código trivial das operações do CRUD?

Um dos jeitos é usar uma outra abstração de persistência de objetos: o Repository. Com o Repository, temos um lugar onde podemos guardar e buscar por objetos, não importando como fazemos isso. O DAO já está muito ligado com armazenamento em banco de dados, e foi criado quando as operações do BD eram muito trabalhosas (em especial no JDBC).

E como juntar o Repository com o GenericDAO? O Repository pode ser definido, por exemplo, como uma interface, e aí podemos fazer o seguinte: se, para um pagamento, faz sentido apenas salvar e listar, mas não excluir, então criamos a interface:

public interface PagamentoRepository {
    void salva(Pagamento pagamento);
    Pagamento busca(Long id);
    List<Pagamento> lista();
}

E usamos o GenericDAO como implementação dessa interface:

class PagamentoDAO
          extends GenericDAO<Pagamento>
          implements PagamentoRepository {
   // implementacao extra
}

E no nosso código de domínio “nunca” referenciaremos o PagamentoDAO, apenas o PagamentoRepository, assim mesmo que a implementação saiba fazer mais coisas, a interface só expõe as operações suportadas.

Se você usa Injeção de Dependências e algum framework que a suporta (como o VRaptor, Spring ou Java EE6), você pode deixar os DAOs apenas como infraestrutura, e usar os Repositories como interfaces públicas da sua aplicação:

public class PagamentoController {
    public PagamentoController(PagamentoRepository repository) {
         this.repository = repository;
    }

    public void salva(Pagamento pagamento) {
         // validações e outras regras
         repository.salva(pagamento);
    }
}

Ainda poderíamos melhorar o nome do nosso repositório para BaseDePagamentos, ContasAPagar ou ainda Pagamentos, evitando usar sufixos nas classes. Usando abstrações e padrões simples conseguimos evitar repetição de código sem perder a semântica e restrições das nossas classes de modelo, além de esconder detalhes de implementação.

Share/Bookmark

Outros assuntos neste blog:



 leia mais...



Categoria: Java Blog: blog dos desenvolvedores da Caelum Visualização: Abrir com frame