quinta-feira, 4 de setembro de 2008

Usar ou não DAO nos tempos do JPA?

Recentemente fui questionado sobre os design patterns a serem usados no desenvolvimento de aplicações Web com JSF e JPA. As seguintes perguntas foram feitas:
  • Pensamos em usar um Mediator para evitar acesso direto ao JPA dentro do Seam Component. Este padrão é o melhor a ser adotado?
  • Tem mais algum design pattern que devemos usar explicitamente? Já estamos utilizando DAO, para separar os métodos de acesso ao JPA.
Pensando sobre o assunto, cheguei às seguintes idéias.
Vejo que nos tempos de JPA, evitar o acesso direto ao JPA a partir da camada controller ou até mesmo da camada model (via serviços, ou melhor, façades) não é mais necessário. O uso de um mediator ou DAO para encapsular os códigos de persistência estão saindo de moda considerando que a interface desses objetos é praticamente a mesma do EntityManager. Ou seja, se adicionarmos essa camada, vemos que praticamente é uma cópia e passagem direta de chamadas de uma camada para outra sem um valor agregado significativo. Pode até ser que compense por impor uma interface de DAO com tipagem baseada nas entidades, considerando que JPA não usa generics ainda.
No tempo do JDBC, onde tínhamos infinitas linhas de código para persistência de cada entidade, o DAO ou o encapsulamento de códigos de persistência tinha uma valor enorme para o reuso e manutenibilidade. No tempo do Hibernate, o uso do DAO ainda podia ser justificado considerando que a API do Hibernate não era considerada um padrão. Então seria interessante manter o acesso ao BD encapsulado para possíveis trocas de "provider". Mas, já nesse tempo começamos a perceber que os DAOs não tinham muito código por conta do Hibernate generalizar o acesso ao DB através de reflection e dialect. Mas, agora nesses tempos de JPA a API é padrão, já encapsula a independência do provider, já oference um processo simplificado de configuração e uma API genérica para todas as entidades via reflection, além de ter o mesmo efeito do Hibernate na redução drástica de códigos nos DAO. Uma camada específica de DAO para persistência em banco de dados via JPA perde sentido. Contudo, o DAO ainda é interessante para outros meios de persistência, e até mesmo DB se JPA não for usado.
Portanto, eu recomendo usar o JPA (EntityManager) diretamente na camada controller (MBs clássicos ou seam components como MBs) ou na camada model (seam components como façades ou business services). Daí podemos nos beneficiar da simplificação proposta pelo Java EE ao promover o IoC/DI através da anotação @PersistenceContext ou da proposta do Seam ao promocer o IoC/DI através da anotação @In. Então, a dúvida agora reside em fazer ou não uma camada model para delegar a persistência da entidade a esta camada! Confesso que é uma dúvida interessante de responder e que pode ser adiada para o momento de modelagem de cada arquiterura que realizarmos.
Muitos já me questionaram sobre usar ou não DAO nesses tempos de JPA. Agora pude compartilhar um pouco do que penso sobre esse assunto ... Qualquer contra-posição, adoraria discutir ...

Uma discussão acalorada foi resumida num post do site InfoQ pelo Craig Wickesser "Has JPA Killed the DAO?" com argumentos contra e a favor do DAO com JPA.

3 comentários:

Unknown disse...

Legal seu texto, Spock. No entanto, e se quisermos ter a oportunidade de oferecer mais métodos de acesso doque os propostos pela API do EntityManager ? Como por exemplo um findByCodeAndName ?
Acho que com Generics conseguimos inferir um DAO Generico que simularia um "delegador" para o EntityManager e tudo aquilo que fosse criado a mais, especializaria o DAO Generico desta forma, manteríamos o encapsulamento e a simplicidade do EntityManager sem necessidade de criar vários DAOs "vazios"

Dr. Spock disse...

No caso de um método como findByCodeAndName acho interessante substituir simplesmente por Named Query com um nome, por exemplo, "nomeEnidade.findByCodeAndName" com o código "from Entidade where code like ? and name like ?".

No caso do DAO genérico via uma interface genérica e ter interfaces específicas com uma implementação baseada em generics me parece interessante. Neste caso acho legal tb a idéia de usar AOP através do conceito de introduction para criar um código genérico (aspecto) que é chamado para todo é qualquer método que tem o nome find* e executa uma 'named query' com o mesmo nome do método.

Adolfo Eloy disse...

Spock, como uma forma de discutir sobre este assunto, postei minha opinião em meu blog (até por meu texto ficar muito grande).

Gostaria que desse sua opinião a respeito do modelo que adotei no cenário que expliquei no blog (uma vez que este assunto sempre gera certa polêmica)

Adolfo Eloy : usar ou nao DAO com JPA