Type erasure com GenericEntity

Interessante isso que você comentou… Inclusive li um artigo seu em que você comenta este padrão (também tem este artigo que introduz uma outra abordagem deste conceito)…

Mas isso na prática não seria um pouco mais custoso em termos de praticidade para criação de novas entidades?

Outra questão… Visto que uma DAO (no caso de um ORM um DomainStore) faz parte da camada de integração e que este não conterá regra de negócios (no caso de uma DomainStore) e somente ela sabe como prover os dados para o Repositório, o que você pensa sobre algoritmos mais próximos da persistência ou do banco de dados em si (tal como triggers, por exemplo)… Você condena totalmente esse uso?

Por exemplo, digamos que a gente tenha uma entidade Fatura que é mapeada para um banco relacional como uma tabela “faturas”, bem como uma tabela “parcelas” mapeadas em classe como Parcela (Fatura 1xN Parcela). Para cada alteração de valor de uma das parcelas é necessário atualizar o valor total pago e o status contido na fatura. Uma operação destas (na minha opinião) é típico de criação de uma trigger. Sei que isto amarra um pouco a aplicação, mas por outro lado é tão raro alterar o banco de dados do sistema quanto modificar a linguagem. E vale a pena lembrar ainda que a maioria das integrações com outras bases são feitas através de XML ou importação de arquivos texto com layouts próprios que o sistema deve entender e tratar da forma certa.
Além disso, há ainda uma outra vantagem em relação à trigger, que é a questão de segurança e da não necessidade de abrir transações em código, o que, muitas vezes, deixa de ser produtivo tanto em questões de desenvolvimento como performance.

O que vocês pensam sobre isso?

[quote=erico_kl]Interessante isso que você comentou… Inclusive li um artigo seu em que você comenta este padrão (também tem este artigo que introduz uma outra abordagem deste conceito)…
[/quote]

Esse meu artigo está um pouco desatualizado. O exemplo que eu dou de escrever um SQL era para ajudar a entender, mas acabou confundindo o padrão parecendo que o repositório gera SQL. Ele gera QueryObjects do qual SQL é um exemplo, mas o artigo deveria mostrar isso. O exemplo real seria por exemplo o repositorio escrevendo uma Criteria do hibernate de depois chamamdo o session.

O segundo artigo usa o padrão repositorio do jeito que eu falei ( Repositorio chama DomainStore, que - no caso - é o Session do Hibernate )

public class Repository {
  private final Session session;  
  public Repository(Session session) {   // <- isto que interessa para nós
    this.session = session;
  }
   
  public void get(Long id) {
    // poderia delegar para um dao, se fosse necessário
    Usuario u =  session.load(id);  // <- isto é uma query
    u.setRepository(this);   // <- isto que interessa para o artigo deles
  } 
}

A discussão deles é se o entity deve ou não ter acesso ao repositorio. Isso é a implementação de outro padrão (ActiveRecord). Se a sua aplicação usar ActiveRecord, o artigo discute como injetar o repositorio em cada instancia da entidade.
Não contraria o fato do repositorio em si, comunicar com o domainStore e não com o dao (pese embora o comentário que poderia chamar o DAO, o que eu considero uma alternativa ao uso do session)

O exemplo do ActiveRecord sim. mas o uso de domainStore com repositorio não. Não tem nenhum problema. Vc usa como usaria um DAO, mas por baixo dos panos vc tem mais flexibilidade.

Trigger e Procedure é o jeito legado de fazer. Se vc usa isso, então vc precisa do DAO “sabor legado”, que falei antes. Eu não uso. Qualquer processamento é feito é java. Por uma razão simples : portabilidade.

Entenda que se vc usa procedure ou trigger a sua camada de serviço/domínio vai até ao banco. Isto é contrário ao principio de isolamento. Se vc só manda dados, então o banco tem um proposito especifico e um só (SRP - Single Responsability Principle) o que o torna muito mais simples de mudar. Pode mudar de SQL Server para Postgress ou Oracle sem pensar duas vezes. Já com triggers e SP é um parto … Vc fala que isso nunca muda … bem depende muito da sua aplicação. Se vc tem um produto e o cliente que escolhe o banco, importa e muito.

O exemplo que vc cita é a forma como alguém pensa fora do java ( em clipper , ou vb , sei lá). Em java vc não pensa assim. Repare que o conceito de trigger ainda é usado, mas é tudo feito em java. (vc configura um listener no hibernate, por exemplo, que o avisa quando a entidade é inserida ou atualizada, etc… e ai vc faz algum codigo de logica. É assim que são feitos os códigos de auditoria, por exemplo). O SP é o codigo que está nos Services, e triggers são eventos trabalhados com listeners. Simples.

Acho que a simplicidade de manutenção trunfa qualquer vantagem que vc se lembrar. Até a performance é maior porque vc pode distribuir vários AS que são muito mais stateless que o banco e por isso mais fáceis de escalar.

Tem pessoas que acham que devem delegar ao banco, eu não acho. Para mim banco de dados é um objeto burro.

Mas atenção, o padrão DomainStore não proibe vc de usar procedure e triggers. Mas ai vc terá que implementar o seu próprio DomainStore pois os de fábrica como o JPA e o Hibernate não têm muito suporte a isso. Vc até consegue invocar um SP no hibernate, mas não lhe dá muita vantagem pois coisas como o cache do hibernate não são usados nessas operações ( e é no cache que está a magia e a escalabilidade da coisa). Vc pode pensar em uma camada onde implementa o seu DomainStore chamamdo o hibernate, por exemplo, por baixo dos panos, mas como as queries que são recebidas são genéricas vc tem que entendê-las e saber “ah! vc está tentando acessar o total das faturas, então em vez de fazer esse sum que vc está pedindo, vou chamar este SP aqui” … é possível, mas é complicado demais.

O JEE 7 e 8 vão trazer muita coisas util como uso do fork/join e concorrencia em ambiente JEE o um framework de batch. Com isto, vc perde totalmente necessidade de SP e triggers no banco.

Ok, somente a DAO conhece a infraestrutura, ou seja, é ela que está amarada diretamente ao modelo de dados que for usado (banco, xml, web service etc…). Li em outro artigo que os Repositórios geralmente são interfaces que a DAO implementa, mas aí onde ficam as implementações de domínio? Neste caso o repositório não acabaria sendo somente um facade para expor os métodos da DAO?

Ao meu ver, para separar bem as coisas, um repositório não deveria conter nada que envolva sql, transações, hibernate ou qualquer outro framework ORM, sendo que isso é responsabilidade da DAO (ou do DomainStore).

Mas aí estamos escolhendo entre ou ficar preso ao banco, ou ficar preso ao framework… E em ambos os casos seria um parto a manutenção em uma troca de banco relacional para um banco OO, por exemplo (claro que aqui estou indo um pouco além)…

Eu discordo. Acredito que muita “gambiarra” que é feita em código java, que além de ser menos performática, acaba sujando um pouco o que realmente interessa para o código e o domínio em si, poderia ser implementada diretamente no banco (desde operações de cálculo, logs, controle de usuários (roles) etc, até as próprias triggers que comentei). Claro que esse uso depende da abordagem e do contexto em que o sistema está incluído, mas acho que os bancos de dados, em alguns casos, podem servir mais do que somente para o propósito de CRUD.

Por outro lado também é interessante deixar isso desacoplado e fazer o controle por código, mas como falei tudo depende do contexto e das necessidades.

O que preciso mesmo é montar uma arquitetura com os padrões que realmente irão ajudar (principalmente na manutenção e agilidade) e não acabar burocratizando o processo…