Pra quê um monte de DAOs cheios de métodos?

Correção: inviável… hehehe

EDITADO:
Para usar hql nas regras de negócio é melhor usar SQL.

Isso não é ter métodos que fazem a mesma, coisa, pelo contrário, vc centraliza em uma lugar as operações comuns.
Acho engraçado o pessoal querer programar orientado e objetos e ficar com receio de criar classes para responsabilidades diferentes.
O meu único receio é criar métodos com muitos parêmêtros.
ex:


funcionario.consultar(cidade, idade, sexo, salario, departamento, ordenarPorNome, ordenarPorIdade, totalRegistros, registroInicial);

Esse é meu medo.

Um modo de solucionar isto é fazer sql dinâmico, passando apenas o Objeto como parâmetro e na cláusula WHERE vc vai filtrando onde cada atributo do objeto não é null.

sql += " WHERE 1 =1  " 

if ( obj.getNome != null )
   sql += " and nome = '" + obj.getNome + "'";

.....

[quote=jprogrammer][quote=‘Mauricio Linhares’]
exatamente esse tipo de coisa que eu quero evitar, milhares de classes e métodos pra fazer o mesmo serviço…
[/quote]

EDITADO:
Para usar hql nas regras de negócio é melhor usar SQL.

Isso não é ter métodos que fazem a mesma, coisa, pelo contrário, vc centraliza em uma lugar as operações comuns.
Acho engraçado o pessoal querer programar orientado e objetos e ficar com receio de criar classes para responsabilidades diferentes.
O meu único receio é criar métodos com muitos parêmêtros.
ex:


funcionario.consultar(cidade, idade, sexo, salario, departamento, ordenarPorNome, ordenarPorIdade, totalRegistros, registroInicial);

Esse é meu medo.[/quote]

Não tem HQL no código, na verdade, não tem nem banco de dados no código, é apenas uma string, do tipo “buscarCursosPorNome” e um Map com os parâmetros que essa busca pode receber.

Nesse caso, poderia não ser o mesmo serviço, se a persistência não fosse feita com o Hibernate, mas usando ele o código vai ser igual em todas as buscas. Vai ser sempre a execução de uma busca pelo nome que ela foi definida no arquivo de mapeamento com os parâmetros necessários.

[quote=maikonaraujo]Outra alternativa para diminuir a quantidade de métodos do Dao é deixar apenas métodos simples CRUD e findAll() , por exemplo, e buscas por Nome, endereço ou coisas do tipo se tornarem regras de negócio (processamento feito sobre os objetos) .
Óbvio que isso se torna enviável se sua base de dados é imensa, ai eu acho que não tem muito como escapar, por questão de performance o mais fácil eh implementar várias consultas diferentes.[/quote]

Imagina eu carregando uma tabela inteira, com uns 10000 registros, pra memória e mandar fazer uma ordenação nela, de objeto em objeto. Eu ia derrubar o servidor no primeiro select! A performance já era mesmo…

Já vi vários exemplos onde é passado o objeto para o método de pesquisa.
Na prática seria uma solução bem legal, mas deixa a arquitetura um pouco estranha.
ex:


funcionario f = new Funcionario();
f.setNome("Maria");
f.setIdade(18);

funcionario.consultar(f);

Melhor que passar o objeto é passar um objeto de seleção. onde voce determina em design time quais campos vc pode usar como filtro


funcionario fs = new FuncionarioSelecao();
fs.filtrarPorNome("Maria");
fs.filtrarPorIdade(18);
fs.ordenarPorNome(ASCENDENTE);
fs.ordenarPorIdade(ASCENDENTE);
funcionario.consultar(fs);

Dentro da classe vc vai montando o SQL (ou HQL) dinamicamente ou pega de um XML, ou de um properties, ou qualquer coisa.

Um modo de solucionar isto é fazer sql dinâmico, passando apenas o Objeto como parâmetro e na cláusula WHERE vc vai filtrando onde cada atributo do objeto não é null.

[code]
sql += " WHERE 1 =1 "

if ( obj.getNome != null )
sql += " and nome = ‘" + obj.getNome + "’";


[/code][/quote]

Ave maria!

Faça isso não pelo amor de deus!

Usa busca por exemplos ou então a Criteria API. SQL on-the-fly só dá dor de cabeça.

[quote=jprogrammer]Já vi vários exemplos onde é passado o objeto para o método de pesquisa.
Na prática seria uma solução bem legal, mas deixa a arquitetura um pouco estranha.
ex:


funcionario f = new Funcionario();
f.setNome("Maria");
f.setIdade(18);

funcionario.consultar(f);

[/quote]

O Hibernate já faz isso também, é até uma coisa que já estaria definida no DAO base, que eu citei lá na primeira mensagem.

[quote=Maurício Linhares]
Se o framework de persistência dá essa possibilidade, porque não usar?
Sei lá, as vezes é tanta “independência” disso ou daquilo que agente acaba sem “liberdade”.[/quote]

Concordo, existe aquele momento em que temos que ser pragmáticos e ter consiência que estamos desenvolvendo uma aplicação que possui suas regras de negócio particulares e não um framework mais genérico do mundo. Ou seja, acaba que o Dao fica com muitos métodos mesmo.

Se correr o bicho pega se ficar o bicho come… :lol: :lol:

[quote=maikonaraujo][quote=Maurício Linhares]
Se o framework de persistência dá essa possibilidade, porque não usar?
Sei lá, as vezes é tanta “independência” disso ou daquilo que agente acaba sem “liberdade”.[/quote]

Concordo, existe aquele momento em que temos que ser pragmáticos e ter consiência que estamos desenvolvendo uma aplicação que possui suas regras de negócio particulares e não um framework mais genérico do mundo. Ou seja, acaba que o Dao fica com muitos métodos mesmo.

Se correr o bicho pega se ficar o bicho come… :lol: :lol: [/quote]

Agora que eu comecei a ler o “J2EE Development Without EJB” é que eu fiquei com a pulga atrás da orelha.

Portabilidade entre frameworks de mapeamento objeto/relacional também vai ser um phantom requirement? :shock:

Pelo menos pelo que eu to vendo, eu não vou trocar o Hibernate por outra coisa nem tão cedo…

Na minha humilde opinião não é a questão de trocar, mas de clareza de código também e divisão de responsabilidades.
Vamos supor que vc tenha que no futuro implemntar um mecanismo de log toda vez que fizer uma inserção.
Separando as responsabilidades isso fica mais fácil de implementar.

Não dá para prever tudo (impossível). Mas tente prever pelo menos aquilo que sua experiência já lhe mostrou.
Os patterns foram feitos para serem usados, pois é o resultado da solução de problemas que foram enfrentados anteriormente por alguém.
Mesma coisa os frameworks.
Mas devem ser usados com coerencia e não por modismos.
Acho que desenvolver sua apliação para se moldar ao pattern é errado.
Mas usar sua apliação para usar o pattern é o correto.

[quote=jprogrammer]Na minha humilde opinião não é a questão de trocar, mas de clareza de código também e divisão de responsabilidades.

Separando as responsabilidades isso fica mais fácil de implementar.


Os patterns foram feitos para serem usados, pois é o resultado da solução de problemas que foram enfrentados anteriormente por alguém.
Mesma coisa os frameworks.
Mas devem ser usados com coerencia e não por modismos.
Acho que desenvolver sua apliação para se moldar ao pattern é errado.
Mas usar sua apliação para usar o pattern é o correto.
[/quote]

Foi isto mesmo que eu quis dizer, concorodo que uma arquitertura bem dividida em camadas eh uma ótima solução. Mas sobrecarregar cada camada com patterns pode ser perigoso, tanto em tempo de desenvolvimento quanto para a simplicidade do código. Faz-se o simples implementando os patterns (SEMPRE QUE NECESSÁRIO), e o resto é específico da sua aplicação, se houver necessidade de uma mudança muito brusca vc pode refatorar o código e adcionar mais patterns se necessário.

O Dao, na minha opnião, tem como uma de suas funções separar (arquitetura em camadas) a parte de acesso a sua base de dados do restante da sua aplicação.

Tá aí um exemplo que eu não tinha pensado.

Imagina um monte de DAOs cheios de métodos de busca, todos com parâmetros diferentes, executando buscas diferentes, cada métodozinho ia ter que ter um logger implementado só pra ele! Olha a bagaceira de código que ia ter que ser escrita só pra logar isso!

Se for com um único método, o executar(String nomeDaQuery, Map parametros) eu só vou escrever o log uma única vez e vou ter tanto o nome da query que foi executada como todos os parâmetros que foram passados, todos reunidos em um só lugar :mrgreen:

E realmente não dá pra pensar muito não, porque os métodos de pesquisa estão retornando Lists, quem garante que outro framework qualquer vai retornar Lists também? E eu já matei acesso direto ao banco, porque o driver do banco nunca vai retornar um List né, vou ter que usar mapeamento objeto/relacional de qualquer jeito. E agora, como ficar independente da camada de persistência? É realmente possível fazer isso?

Acho que eu vou é simplificar mesmo a coisa, criar novos métodos pra fazer buscas, só se for pra montar uma busca em tempo de execução ou se houver necessidade de usar coisas específicas de algum banco.

Vou fazer um novo movimento agora:

“Diga não aos milhares de DAOs e os seus milhares de métodos! Os seus dedos agradecem!”

É verdade Maurício, generalizar nesses casos é bem melhor.
Estou entendendo agora a sua posição.
Mas uma coisa muito gernérica não tira a flexibilidade e os recursos type safe do java ?
ex:


class DAO {
  public void salvar(Object object) {
  }
}

class FuncionarioDAO extends DAO {
  public void salvar(Object object) {
  }
}

Funcionario f = new Funcionario();
Departamento d = new Departamento();

FuncionarioDAO.salvar(d);
FuncionarioDAO.salvar(f);

Perco a checagem em tempo de compilação.

EDITADO:

Enquanto o List vai ai mais uma classe: De Colecao.


class FuncionarioColecao {
  public boolean proximo() {};
  public Funcionario getFuncionario() {}
}

FunconarioColecao fc = Funcionario.consultar();
while (fc.proximo()) {
  Funcionario  f = fc.getFuncionario();
}

Idependencoia total

Isso é uma coisa simples de fazer.

No meu sistema aqui, o DAO só insere objetos que implementem a interface “Persistivel”, que é uma interface de marcação (que nessa implementação com o Hibernate ganhou um identificador via aspectos, mas isso já é outra história). Usando uma interface de marcação esse problema ia ser resolvido fácil, porque o Hibernate “descobre” qual a classe que está sendo persistida dando um getClass() nela e enviando ela pro “persister” adequado. Assim o teste de tipos em tempo de compilação pros métodos de inserir, atualizar e deletar estaria resolvido.

Mas você tocou num ponto interessante, dos “objetos” a coisa tá resolvida, mas das coleções ainda não, vou dar uma estudada em generics pra ver como isso pode vir a funcionar.

Impressionante como a gente se frita quando qualquer discussao sobre DAOs aparece aqui no GUJ. Eu vou ser o primeiro a admitir que eu adoro ficar pensando nisso, mas sinceramente, eu tenho mais o que fazer do que ficar pensando na Arquitetura do DAO Generico Que Resolvera Todos Os Problemas De Persistencia Da Humanidade ™. Se tal coisa existisse ou pudesse de fato ser inventada, nos ja estariamos usando faz tempo - nos nao somos os unicos a esquentar a cabeca com isso.

De agora em diante, eu vou usar uma resposta padrao pra esses topicos:

1 - Use o que o seu framework de persistencia te oferece - voce nao vai trocar de framework, e se for, a arquitetura do seu sistema vai ter que mudar de qualquer jeito.

2 - Use um bom cache ou aprenda a usar o cache do seu framework, e caso ele nao seja completamente transparente, aprenda a controla-lo bem

3 - Nao perca mais do que 30 minutos decidindo qual vai ser a hierarquia de classes dos seus DAOs e, se alguma coisa tao estranha assim que o minimo do bom-senso gasto durante aqueles 30 minutos aparecer, um refactoring conserta.

4 - Nenhum refactoring eh tao grande assim se voce tiver testes unitarios e funcionais pra te ajudar.

5 - Faca o mais simples, mas nao o simplorio, e so reclame de performance se voce tiver provas concretas na mao.

6 - Se possivel, use objetos, com dados e comportamento, nao tabelas com farofa em cima.

7 - Mantenha a informacao perto de onde ela vai ser usada.

8 - Use as interfaces ja disponiveis na API do Java e do seu framework para fazer as coisas a que se destinam (Serializable, Externalizable, Criteria), e nao as reinvente ou abstraia.

9 - Nao, persistencia nunca vai ser transparente.

10 - Nao, o Prevayler, Space4J ou outros mecanismos de command-logging nao sao a solucao que estamos discutindo, e provavelmente nao sao solucoes de longo prazo para nenhum sistema de grande porte que vai ser mantido em mais de um lugar.

Com o genérics: beleza.
Mas com o 1.4 criar uma interface de colecao seria interessante.

5 estrelas CV

Mas matou a discussão :lol:

É verdade, na prática mesmo tudo isso é o que vale.
Depois dessa até eu desisto…

[quote=jprogrammer]Com o genérics: beleza.
Mas com o 1.4 criar uma interface de colecao seria interessante.[/quote]

Nao, nao seria. Leia o ponto 8.