Acesso ao EntityManager: através de um DAO ou diretamente?

Isso não é verdade sempre. Já lidei com vários sistemas cujo ciclo de vida terminou mas ele nunca saiu daquela arquitetura inicial. E é desses casos que falo Sérgio.

Agora eu me tornei um desenvolvedor apressado, desleixado ou gambiarrento só porque decidi utilizar uma abordagem menos “generalizada” para UM projeto em particular? Claro que não.

Generalizar não é ruim. Generalizar sempre, cegamente, sem refletir sobre a necessidade daquela generalização específica e o impacto que ela vá causar na manutenção do sistema, pra mim é ruim.

Concordo com todos os seus outros pontos.

Ok. Sendo assim, será fácil para você - e todos os que concordam com você - apresentar casos reais onde uma generalização correta levou a um aumento no custo ou no esforço de manutenção.

Concordo que uma generalização mal feita possa levar a isso. É difícil aceitar que uma bem feita o faça.
Antes que alguem pergunte: bem feito neste contexto significa ter seguido os princípios de OO : Separação de Responsabilidade, Encapsulamento , Abstração, Herança e Inversão de Controle ( não injeção automática de dependência) por meio ou não de padrões de projeto.

Note ainda que todas as API padrão do java seguem estes princípios de uma forma natural em que, muitas vezes, o programador - sobretudo o novato - não as reconhece Contudo ele as usa e naturalmente ele as acha funcionais. A Collections API é um ótimo exemplo. Outros são o JDBC , a api de servlets e o swing. Todas elas respeitam OO e é isso que permite que vc esteja , por exemplo, no JDBC 4 totalmente retrocompativel com o JDBC 1.0. Vão argumentar que ao fazer um sistema ninguém está pensando que ele vai durar 20 anos como a JDBC. Mas é isso que significa baixa manutenção - daqui a 20 anos ainda posso usar as mesmas coisas que uso hoje. Posso usar mais, mas isso é bonus, o importante é não mudar o que já tenho.

Aguardo exemplos. Se quiserem abrir outro tópico estejam à vontade.

Fiquei um pouco confuso sobre Herança nessa sua lista de princípios OO. Acho que faltou mais algumas coisas também.

http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

[]s

Fiquei um pouco confuso sobre Herança nessa sua lista de princípios OO. Acho que faltou mais algumas coisas também.
[/quote]

Tentei jogar por baixo. Respeitado esses elementos vc obtem os outros a que se refere o texto e que são chamados realmente principios. Da SoC vc pode derivar todos os outros pontos que escrevi excepto abstração. E da abstração nasce a herança. Só tentei colocar em termos simples para todos podessem apresentar exemplos.
Por outro lado, as violações mais comuns de OO são relacionadas ao não comprimento das regras de algum dos elementos que citei. O uso de 'principios" não foi feliz, seria mais “elementos”.

Contudo, após os exemplos serem apresentados podemos analizar na otica dos principios que mencionou.

Pelo que vejo nossos pontos convergiram e você já concordou de antemão:

Se você tivesse dito a frase acima sem a palavra “correta”, eu falaria o seguinte:

Um exemplo que vemos com freqüência aqui no GUJ - e que acredito que você enquadra como "generalização mal feita", assim como eu - está ilustrado abaixo:

Veja que o esforço de manutenção de uma camada de persistência que foi implementada como acima é maior do que se tivéssemos simplesmente:

[quote=tnaires]
Um exemplo que vemos com freqüência aqui no GUJ - e que acredito que você enquadra como "generalização mal feita", assim como eu - está ilustrado abaixo:

Veja que o esforço de manutenção de uma camada de persistência que foi implementada como acima é maior do que se tivéssemos simplesmente:

Sim, realmente eu vejo isso como uma generalização mal feita. Por alguma razão as pessoas adoram criar classes chamadas DAO e as nomeiam assim mesmo quando sabem que não são DAOs. Isso, para mim, é surreal. O Sindrome de DAO é um problema grave. É a gripe suina do design Java do pós EJB 2.1.

Este problema é diretamente derivado de um desrespeito ao SoC. Qual seria a diferença entre a responsabilidade do DAO e do Repositório ? A resposta comum é que o rep é para colocar coisas do dominio e o dao para coisas de infra. Mas isso nunca acontece. Se vc usar hibernate por baixo do dao e criar criterias no repositorio o dao só serve para passar a bola à frente. Não ha desacoplamento algum já que o DAO não tem qualquer responsabilidade. Se o rep criasse critérios agnosticos (que não dependem de nehuma lib) e o dao os interpretasse para criteria do hibernate, perfeito. Assim teriamos 2 responsabilidades diferentes e podemos até pensar em subsittuir o HibernateDAO por outro usando outra tencologia já que ele é um interpretador. hum… mas perai! o DAO é suposto ser um datamapper. Esse papel de interpretador não cabe em um dao. Logo esse objecto intermédio não é um dao, é um Interpreter que atua como estratégia para o repositorio. Veja que o problema não é o numero de camadas, mas a responsabilidade de cada uma. E que o verdadeiro datamapper está algures dentro do próprio hibernate.
A estrutura seria assim:

(quando vc é tentando a colocar Impl no nome da classe isso significa que vc não sabe diferenciar em quê a implementação é diferente de outra)

ProdutoRepository não precisa implementar nenhuma interface especifica chamada Repository. Contudo, ele pode. Mas aqui não estamos usando o mesmo padrão que no DAO (interface + N implementações) que é um tipo Service. Estamos usando outro padrão : Layer Super Type.
A diferença não está na implementação porque ambos usam interface + N implementações. A diferença está na responsabilidade e na abstração.

O Service tem uma interface porque define um contrato. As implementações são especificações reais de como esses contratos podem ser providos. A implementação é irrelevante para quem usa o contrato.Todas as implementações têm a mesma responsabilidade (satisfazer o contrato) e o mesmo comportamento ( dado pela interface do contrato)

O Layer Super Type tb tem uma interface, mas esta não é um contrato do qual derivam implementações. É um denominador comum entre objetos com responsabilidades diferentes que se comportam de forma semelhante. ProdutoRepository e ClienteRepository tem responsabilidades diferentes mas compatilham alguns comportamentos semelhantes como adicionar, remover e procurarTodos. Eles tem alguns comportamentos iguais, não todos. Por exemplo, produtorepo tem findProdutoComNecessidadeDeReposição que não faz nenhum sentido para ClienteRepositorio

Não consigo sublinhar o suficiente quando é importante entender os padrões. A maior parte das pessoas não os entende e isso causa problemas - alguns absurdos. Contudo, se entender SoC e seguir uma ou duas práticas não é necessário saber padrões. Pior que não entender é dizer que não é necessário e causa problemas. Ao contrário, padrões são coisas boas. Eles ajudam a criar aplicações de forma mais rápida e com menos custo e esforço de manutenção. Eles são o “caminho das pedras” , a “receita de bolo” , de fato. Sem gambiarra.
Se isto não fosse verdade não existiram livros como “Refactoring to Patterns”.

Olá

O que será este tal de SoC?

[]s
Luca

[quote=Luca]Olá

O que será este tal de SoC?

[]s
Luca[/quote]

Separation Of Concerns

Bem, minha contribuição para o tópico. Não vai responder nada, mas demonstra alguns estilos de repositórios que já apliquei.

(creio que a maior contribuição é mais sobre conceito de repositório e nomenclaturas)

Muito legal os seus exemplos Rodrigo!

O que eu costumo fazer é criar uma interface pro repositório e uma implementação desta interface que acessa a session (ou o entity manager). Esta implementação normalmente extende uma classe abstrata que fornece o CRUD.

Assim os serviços conhecem apenas a interface do repositório, deixando as classes mais coesas e facilitando os testes unitários. Nunca gostei muito da idéia de usar o entity manager diretamente nos services, mas lendo todo o tópico irei considerar para os casos mais simples.

[quote]Bem, minha contribuição para o tópico. Não vai responder nada, mas demonstra alguns estilos de repositórios que já apliquei.

(creio que a maior contribuição é mais sobre conceito de repositório e nomenclaturas) [/quote]

Acho horrível esse tipo de nomenclatura que você utilizou.
Acho que o nome da classe deve ser algo abstrato.
Usaria esses nomes em instâncias, não no nome das classes.
Não vejo problema em um PedidoRepository. O nome deixa clara a responsabilidade da classe.
Vejo Pedidos faturados como um estado de pedido, caso o negocio mude e evolua e novos estados apareçam, teria que criar mais repositórios. Acho isso desnecessário, um PedidoRepository apenas bastaria e seria mais fácil de manter.

Boa Tarde amigos !

Bom estou iniciando alguns estudos na técnica de Mapeamento Objeto Relacional e escolhi esse framework
para iniciar os meus testes, ficaria muito grato se alguem tivesse alguma aplicação que exemplifica a utilização
desse framework. se possível me enviar eu agradeceria muito

Obrigado !