DAO's nas classes de negócio

Olá

Nada é imutável no campo da idéias. As coisa evoluem. Desde que os caras da Sun escreveram sobre design patterns, muitos outros autores escreveram também e muitas idéias se aprimoraram.

Siga o exemplo do Phillip, que estuda para caramba para se manter atualizado. Procure ler os livros que ele recomenda e entenderá melhor o porque das mudanças.

[]s
Luca

Não há, pelo menos não amplamente divulgada. Estes padrões foram catalogados por Martin Fowler e Eric Evans.

Não está errado porque o autor está falando sobre DAOs e não sobre Repositórios.

[quote=Rafaelprp]
Tá parecendo aquele velho papo que no mundo java existem vários nomes para a mesma coisa…[/quote]

Releia meu último post.

Interessante a discussão :slight_smile:

[quote=Fabio Kung][quote=saoj] public interface UserDAO { public User loadById(int id) throws Exception; public int insert(User user) throws Exception; public void update(User user) throws Exception; public void delete(User user) throws Exception; public User loadByUsername(String username) throws Exception; public User loadByEmail(String email) throws Exception; public List searchUsersByName(List keywords, boolean and) throws Exception; public List searchUsersByName(List keywords, boolean and, int max) throws Exception; }

  1. Posso considerar essa interface como respositório?[/quote]
    . . . e aí sim renomearia para UserRepository.[/quote]

Se eu entendi bem o que foi dito aqui, inclusive nesse e nesse blog, por todos os motivos já citados, a interface UserDAO deve ser renomeada para UserRepository.

Então, o artigo Ei! Como é o seu DAO? Ele é tão abstraído quanto o meu? do blog da Caelum deve ser atualizado, certo? interface Dao<T, I> { T search(I id); // ? }
Pois essa interface DAO é utilizada na camada de negócio - pelo menos é o que subtende-se pelo artigo: Dao<Cliente> clienteDao = new GenericHibernateDao<Cliente>(session); clienteDao.persist(cliente); Cliente c5 = clienteDao.search(5);
Afinal, Client é um aggregate, e o repository deverá lidar com Client e suas classes colaboradoras, como Address, etc.

Esse outro artigo sugere o que o pcalcado disse acima:
Repository -&gt RepositoryImpl -&gt DAO -&gt DAOImpl

Ali, o autor diz que nos DAO’s devem haver - digamos assim - métodos de granulação fina, estritamente relacionados às operações com banco de dados: create, find / search, update, delete; nos repositórios, operações mais “interessantes”, relacionadas aos negócios", como procurarTodosClientesInadimplentes.

procurarTodosClientesInadimplentes para mim estaria num domain service e poderia gerar outra discussão: se deveria estar num repositório ou não. Mas creio que ficou claro o que quis dizer.

Rafael, você levantou algumas questões muito boas.

Se os objetos do domínio possuírem alguma referência, eu chamaria a interface de Repository, caso contrário chamaria de DAO.

Mas isso também é bem discutível.

Uma vez, batendo papo com o Vinícius Siegel (dono da global code) num evento , estávamos falando sobre pattern e ele falou uma coisa muito interessante : "Depois de 2 ou 3 cervejas, eles são praticamente iguais … :slight_smile: ".

Brincadeira à parte, costumo fazer o design dessa camada utilizando uma interface DAO e sua implementação de modo genérico.

Na camada Business, IoC desse com a "ajudinha" do Spring ou um esquema de anotações que voê pode montar tb …

PS: vou postar um artigo sobre isso no meu blog, que não atualizo a quase um ano :slight_smile:

Legal Phillip. Realmente usar o nome Repository e usar a nomenclatura de métodos sugerida pelo Fábio Kung fica menos na cara que ta usando um banco de dados por trás, fica mais bonito, etc.

Mas acho que o pessoal ta mais acostumado com o termo DAO e, no fim, DAO e Repository acaba tendo o mesmo efeito.

[quote=microfilo]
Mas acho que o pessoal ta mais acostumado com o termo DAO e, no fim, DAO e Repository acaba tendo o mesmo efeito.[/quote]

Ou eu não tô sabendo explicar ou tem algo errado na comunicação…

Imagine a situação: o seu DAO recebe como parâmetro um HttpRequest. Tem o mesmo efeito que passar um objeto de negócios para ele, não?

[quote=RafaelRio]por todos os motivos já citados, a interface UserDAO deve ser renomeada para UserRepository.

Então, o artigo Ei! Como é o seu DAO? Ele é tão abstraído quanto o meu? do blog da Caelum deve ser atualizado, certo?
[/quote]

Não necessariamente. (1)Ele não precisa estar falando de DDD e (2) ainda que você adote a estratégia simplificada de DAO&lt<implements>&gtRepository nada impede que o DAO tenha sua própria interface para promover alguma abstração.

É beeeeeem por aí. Um repository é como objetos de negocio enxergam ‘o lugar onde objetos sao guardados’. Se eles sao guardados num SGBD e mapeados com um DAO nao importa aos objetos de negocio.

Boa Phillip, foi exatamente o que eu quis dizer!

No artigo do Paulo lá no blog da Caelum, o DAO não está sendo usado dentro dos objetos do domínio, por isso continua sendo DAO.

A diferença é sutil:

Dao&lt;Usuario&gt; dao = new Dao&lt;Usuario&gt;(); List&lt;Usuario&gt; usuarios = dao.listAll();

[code]
public class Usuario {
private ProdutoRepository repository;

public Usuario(ProdutoRepository repository) {
this.repository = repository;
}

public List<Produto> getProdutosCompradosDesde(Date dia) {
return repository.getProdutos(this, dia);
}
}[/code]
getProdutos passando ‘this’ ficou BEM feio, mas é só para ilustrar a idéia.

Entao depois de tanta teoria como ficaria uma estrutura web para acessar um
banco de dados por exemplo?

view -> action -> modelo de negocios -> UserRepository(Interface) -> UserDao(implementação) -> etc etc…

??

Se eu entendi direito:

req HTTP -&gt Action -&gt Modelo -&gt UserRepository -&gt Implementação concreta do repositário MySQLUserRepository -&gt Banco de dados.

Mas acho que eu entendi errado, pois acima só trocamos o nome DAO por Repository.

Então talvez seja algo assim:

req HTTP -&gt Action -&gt Modelo -&gt UserRepository -&gt Implementação concreta de UserRepository -&gt User DAO -&gt Implementação concreta de UserDAO -&gt Banco de dados.

Parece correto do ponto de vista teórico, mas com o side-effect prático de termos muitas classes e interfaces.

Minha dúvida agora já é outra. Acredito que devido a simplicidade do meu modelo de negócios ele acabou se comportando como um UserRepository apenas, ou seja, sua única função ficou sendo CRUD de beans.

Acho que esse conceito está difícil de assimilar porque em muitos casos o repositório vai apenas espelhar fielmente o DAO, logo ele parece uma camada a mais apenas com sentido teórico mas nao prático.

Por exemplo, se eu precisar pegar todos os usuários maiores de X anos, com a cueca da cor Y e cadastrados antes de 1990, terei que criar um novo método no repositorio e um outro igualzinho no DAO.

Haverá muita duplicação entre o DAO e o Repository… A dúvida que ficou e se isso tem que ser usado sempre ou não, depende do caso.

O outro extremo seria colocar tudo na action, ou seja, a action -&gt DAO -&gt banco…

Todas essas camadas (Repository -&gt RepositoryImpl -&gt DAO -&gt DAOImpl) são a maior abstração possível. Você não precisa (eu eu acho que nem deve) fazer isso sempre. Se for só para ter um monte de interfaces e classes ocas que só delegam tudo, eu não acho que valha a pena abstrair.

Já foi o tempo que achava melhor interfacear e abstrair tudo. Até discutia bastante sobre isso com o Michael Nascimento e com o Paulo Silveira (aqui e aqui).

Hoje em dia eu mudei minha opinião e procuro sempre manter as coisas o mais simples possível, mas isso não significa fazer errado (acabar com a OO, por exemplo). O Repository não precisa ser apenas um envelope para o dao. Nem interfacear o repositório é obrigatório e regra geral.

Se eu percebo a necessidade de abstrair, refatoro e pronto. Acho que não vale a pena complicar muito o modelo com 1332423 abstrações e interfaces de tudo sem nem ter certeza da real necessidade.

O conceito do Repository é esse que o Phillip apresentou (e o trecho de código que eu postei). Já como implementá-lo, no meu ponto de vista, vai depender de cada caso.

Vinícius Senger né?

(ou ele tem um sobrenome que ninguém conhece?)

[quote=saoj]Então talvez seja algo assim:

req HTTP -&gt Action -&gt Modelo -&gt UserRepository -&gt Implementação concreta de UserRepository -&gt User DAO -&gt Implementação concreta de UserDAO -&gt Banco de dados.

Parece correto do ponto de vista teórico, mas com o side-effect prático de termos muitas classes e interfaces.

[. . .]

Acho que esse conceito está difícil de assimilar porque em muitos casos o repositório vai apenas espelhar fielmente o DAO, logo ele parece uma camada a mais apenas com sentido teórico mas nao prático.[/quote]
Penso assim também.

saoj, pelo que andei pesquisando, esse é o tipo de operação sob responsabilidade de um repository, que internamente utilizaria um DAO para acessar os dados necessários e então fazer o processamento e devolver o resultado ao cliente.

Os DAO’s seriam escondidos e ficariam com o mais simples e puro CRUD; operações mais relacionadas com o negócio sobem para o repository.

[quote=Fabio Kung]Todas essas camadas (Repository -&gt RepositoryImpl -&gt DAO -&gt DAOImpl) são a maior abstração possível. Você não precisa (eu eu acho que nem deve) fazer isso sempre. Se for só para ter um monte de interfaces e classes ocas que só delegam tudo, eu não acho que valha a pena abstrair.

Já foi o tempo que achava melhor interfacear e abstrair tudo. Até discutia bastante sobre isso com o Michael Nascimento e com o Paulo Silveira (aqui e aqui).[/quote]
Assino em baixo. E vale a pena ver essa discussão.

[quote] Hoje em dia eu mudei minha opinião e procuro sempre manter as coisas o mais simples possível, mas isso não significa fazer errado (acabar com a OO, por exemplo). O Repository não precisa ser apenas um envelope para o dao. Nem interfacear o repositório é obrigatório e regra geral.

Se eu percebo a necessidade de abstrair, refatoro e pronto. Acho que não vale a pena complicar muito o modelo com 1332423 abstrações e interfaces de tudo sem nem ter certeza da real necessidade. [/quote]
Mesmo porque, dizer o contrário é ir contra um dos princípios do XP, metodologia que parece ser seguida por vários profissionais no GUJ.

Eu achei o conceito de Repository interessante, mas não vi ganhos nem mesmo em grandes projetos. No meu caso, por exemplo, teria que fazer muito mais do que renomear algumas interfaces.

Se um dia eu achar útil… Bem, para isso que serve refactoring.

Vinícius Senger né?

(ou ele tem um sobrenome que ninguém conhece?)[/quote]

Boa … eu realmente me confundi, não sei pq troquei o sobrenome do cara :slight_smile:

Obrigado :slight_smile:

Rafael, o ganho seria justamente deixar a coisa mais OO.
Em vez de:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = dao.carregaContasPagasDesde1999(fornecedor);
Você consegue fazer:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = fornecedor.getContasPagasDesde1999()
Se o fornecedor tiver uma referência para o RepositorioDeContas (ContasRepository).

Rafael, o ganho seria justamente deixar a coisa mais OO.[/quote]
Kung, você sabe, para calcular ganhos é preciso conhecer vantagens e desvantagens - me corrigindo, a palavra mais correta seria “valor”, ao invés de “ganhos”.

A questão que eu coloquei é “essa camada a mais vale a pena”? Se o preço para mais uma camada superar os ganhos de tornar “a coisa mais OO”, a resposta é não. Taí uma discussão que vai (ou melhor, poderia ir) longe…

Ultimamente tenho pensado que vale a pena questionar novas teorias que andam ululando por aí, em pró da simplicidade, desde que com fundamentos, ao invés de simplesmente aceitá-las.

Esse repository, por exemplo, vocês podem argumentar que torna as coisas mais claras, elegantes, o genro que toda sogra gostaria de ter, mais OO, etc. Mas tô sentindo que a reação da maioria das pessoas será “isso é lindo na teoria, mas não na prática; deixa quieto, vou continuar com meus DAO’s”. Vão deixar (aproveitando esse exemplo) o Repository para uma “zelite” que irá se formar - “isso é só pros caras”.

E quando argumentos do tipo “torna a coisa mais OO”, “segundo Fowler”, etc, finalmente se desgastarem, essa elite ficará isolada numa torre de marfim - já aconteceu e acontece em diversas áreas. Vão dizer coisas lá de cima na torre, as pessoas vão escutar, ficar encantadas, vai entrar por um ouvido e sair pelo outro.

Isso vai formar um vazio, que será preenchido por palpiteiros inconseqüentes, que pregarão contra a OO, design patterns e o inglês e arrebatarão coraçãozinhos por adotarem uma aura de pragmáticos (levanta a mão quem não sabe do que estou falando).

Não me entendam mal, não estou soando as trombetas do apocalipse e sou fã da fundamentação e da boa literatura. Mas tudo tem limites, cada caso é um caso, teoria ainda é uma teoria, devem ser testadas na prática, por aí vai. (Uauu!! Isso é que bom uso de clichês…)

Aceitam uma sugestão? Em casos assim, penso que o ideal seria escrever artigos técnicos com o contexto e os pormenores, como a série sobre exceções do Luca e o artigo sobre DTO do shoes. Um já é referência no tema, o outro, aposto, vai virar.

A partir daí, as pessoas pensam e decidem com suas cabeças qual o melhor caminho.

Abraços!

Rafael, o ganho seria justamente deixar a coisa mais OO.
Em vez de:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = dao.carregaContasPagasDesde1999(fornecedor);
Você consegue fazer:

Fornecedor fornecedor = ...; List&lt;Conta&gt; contas = fornecedor.getContasPagasDesde1999()
Se o fornecedor tiver uma referência para o RepositorioDeContas (ContasRepository).[/quote]

É realmente, o segundo é bem melhor que o primeiro, e temo que eu esteja inclinado a fazer o primeiro. Mas isso não tem haver com a questão do repository x DAO. Seja com DAO dentro de forncedores ou com repository dentro de forncedores talvez a coisa deva ser sempre feita assim mesmo como o Fábio falou… É para pensar e brincar…