Arquitetura 2010 – Parte II 

Apr/10
25

O primeiro post desta série levantou muito burburinho pelas razões erradas. A culpa foi minha porque ao tentar explicar que aplicações EE e sites são coisas diferentes e que para fazer sites não precisamos de EJB acabei citando coisas que não precisava…

Felizmente algumas pessoas entenderam o objetivo do texto: descrever uma arquitetura mais adquada para sites sem usar EJB e aumentando as capacidades de teste e robustez das aplicações. Algumas pessoas pediram um exemplo mais concreto desta arquitura. Porque isto implicariam em escrever muito codigo e seria extenso demorei um pouco. Mas já que tinha que o fazer, resolvi colocar esta arquitetura na nova seção de configurações de arquitetura. Quem estiver interessado pode ler o artigo completo. Quem ler tenha em mente que é um “work in progress” e sugestões são bem vindas. A parte com CriteriaBuilder tive que pular pois ia ocupar muito espaço e não é o foco do artigo. Cada um poderá implementar como quiser. Só uso esse objeto porque ele torna muito facil criar criterios de busca.

Espero que fique claro  desta vez porque esta arquitetura é vantajosa face às tradicionais arquiteturas acopladas ao hibernate e/ou entity manager.

2 comentários para “Arquitetura 2010 – Parte II”

  1. Sem dúvida um bom código, mas consigo ver pouca diferença de usar seu próprio sistema de Criteria/Query/CriteriaBuilder em vez de usar a JPA2. Vi que no outro artigo você não conhecia do lançamento da JPA2, mas agora já poderia ter visto que ela faz exatamente o que você colocou lá, e de forma padronizada (nomes dos métodos parecidos até). Não devemos rejeitar o Java EE a ferro e fogo, mas entendo que “o passado o condena”.

    Sobre ter um DAO abstrato na classe mãe, há muito tempo fui adepto, mas hoje em dia enxergo as grandes desvantagens da heranca até num exemplo simples assim. Escrevi sobre esse mesmo tipo de DAO abstrato em 2006, e hoje em dia não usaria (como comentei lá em 2008, não vale a pena para economizar meia dúzia de linhas que são só delegações):
    http://blog.caelum.com.br/2006/10/29/brincando-com-generics-o-bizarregenericdao/

    Mas como você deixou tudo bem interfaceado, usar o dao abstrato certamente é opcional.

    A propósito, a erasure sempre ocorre. O seu método resolveGenericClass descobre o parâmetro através da assinatura da classe, diferentemente do que está escrito. Não é por causa de ser herança ou por “erasure não se aplicar”. Funcionaria perfeitamente com interface/implementação se usado o mesmo exemplo. Mas, também diferente do que está falado, a herança não obriga nada, já que você poderia ter dando extends em AbstractRepository sem especificar o tipo, o que é uma falha no código: o repository abstrato não checa se esse parametrized type está bem definido.
    http://blog.caelum.com.br/2008/04/28/nao-posso-descobrir-nem-instanciar-tipos-genericos-porque/

  2. A arquitetura que propus parece fazer o mesmo que o JPA2. E de facto assim é. Ela faz exactamente o mesmo ( ok, não exactamente, mas isso é detalhe). O ponto aqui é que o JPA2 não faz o mesmo que esta arquitetura. É isso que é importante entender. Com esta arquitetura eu posso mudar a estratégia de persistencia quando e como quiser. No JPA isso é simplesmente demasiado complexo (não é impossivel, mas teria muito, muito, muito, muito trabalho pois teria que implementar a especificação toda … )

    Agora alguem vai dizer que esse tipo de flexibilidade é inutil, que nunca mudamos de banco, blá, blá, blá. Se a pessoa faz testes unitários e tem experiencia com moking, sabe muito bem que é preciso fazer mock da camada de persistencia e que isso é impossivel usando JPA ou Hibernate directamente. Sempre temos que ter alguem no meio. Ora, esse alguem é a estratégia de persistencia.

    Esta arquitetura é desacoplada. Mesmo que nunca precisa usufruir dessa qualidade ( o que eu duvido muito) ela é sem duvida melhor. Até porque, basta colocar o hibernate/jpa por baixo da estratégia de persistencia e voilá, teremos o que todo o mundo está usando por ai… algum tipo de objeto que encapsula o acesso a esses caras. O ponto , aqui é que, o encapsulamento não é completo/correto sem um mecanismo de Query Object, o qual não é viável sem Repositorios. Uma coisa leva a outra…

    Não ha nenhum DAO nesta arquitetura . então não entendi do que está falando.

    O erasure nem sempre ocorre.

    “For instance, erasure doesn’t apply to subclasses of generified classes” fonte

    É sim porque ha herança – não funcionaria sem isso , não funciona para interfaces – e é sim porque erasure não se aplica neste caso.
    Não é uma falha no código, é uma simplificação. Desta forma não precisa passar a classe no construtor ou em qq outro lugar.
    O AbstractRepository não checa porque não precisa. A construção da classe e o proprio java garantem que a tipagem é compativel. Veja que na realidade quem irá definir o tipo é o critério e quem a carrega é a estratégia de persistencia, portanto as assinaturas genéricas do repositorio servem apenas para manter a tipagem forte e com isso simplificar a escrita.

    Ao contrário do que pode parecer dos variados exemplos de “DAO Genéricos” vinculados por ai onde o programador precisa passar explicitamente o literal da classe no contrutor das implementações, isso não é uma necessidade. Aliás, é uma má prática por criar um código que não é DRY.

    Todas as implementações do artigo são exemplos, e cada pessoa pode modificar como entender. O objetivo é mostrar os componentes e suas responsabilidades, não uma implementação “ultima”. Contudo, não pude deixar passar a oportunidade de mostrar que ainda ha alguns mitos a serem quebrados. Sendo um deles a crença que a erasure sempre acontece.

    Nem sempre acontece. E podemos tirar vantagem disso para deixar o código mais elegante.

Comente

Artigos