Retorno de Consultas DAO

33 respostas
J

Vou refazer uma pergunta que fiz em um tópico e ficou esquecida.

o que vocês retornam em um metodo de consulta de um DAO quando :

  • é agrupamento

  • com restrição de campos (apenas alguns campos da classe)
    retornam um DTO só com os campos usados ou o objeto inteiro ?

  • campos nulos (ver se o campo é nulo em primitivos)
    usam classes Wrappers ?

Gostaria da opinião de vocês.

33 Respostas

louds

Todas as anteriores, depende do caso e necessidade.

Rafael_Nunes

1-Um Collection genérica.
2-Independente do que eu precise, retorno o objeto inteiro, quem é responsável pelo tratamento das informações é minha camada de negócio.
3-Não entendi, de qualquer forma retorno sempre o objeto, havendo campos nulos ou não.

jgbt

depende muito.
ja retornei collections de obj, somente obj com os atributos…
gosto muito de usar uma VO generico, que é um hashmap, so ele trafega dados, crio interfaces para as cosntantes usadas nas chaves.
ele pode conter beans, ou collections de beans, ou wrappers, dependendo do caso.

[]'s

louds

Eu acredito que todos esses usos são válidos, não vejo mal em o seu DAO retornar diretamente DTOs caso em todos use cases dele os valores são enviados para o outro tier sem qualquer processamento.

Não tem problema retornar objetos incompletos caso um dos membros seja um blob de 100megas, por exemplo.

louds

jgbt:
depende muito.
ja retornei collections de obj, somente obj com os atributos…
gosto muito de usar uma VO generico, que é um hashmap, so ele trafega dados, crio interfaces para as cosntantes usadas nas chaves.
ele pode conter beans, ou collections de beans, ou wrappers, dependendo do caso.

[]'s

:!: :!: Enterprise HashMap detected :!: :!:

jgbt

o que quer dizer?

[]'s

J

Todo muito mete o pau no desenvolvimento com HashMap, mas ele quebra uma galho enorme.
Agora é mais fácil falar “depende da necessidade”.
Pelo menos todo mundo dá sua opinião

Quando me refiro a ver se o campo é nulo em primitivos me refiro no seguinte.

class Funcionario
{
  private  float salario;
  // getters and setters
}


Funcionario f = FuncionarioDAO.consultar();
f.getSalario() // opa como eu vejo se é nulo

ou uso

private Float salario;
// agora eu posso ver se é nulo.
jgbt

sinceramente, ate gostaria que alguem me desse motivos de não usar hashmap.
qual a diferença de ter 30 beans para trafegar dados, ou ter um unico obj para isso.
quase todos frameworks trabalham com hashmap.
alguem???

[]'s

cv1

Eis o problema, tanto com HashMaps quanto com VOs: http://www.martinfowler.com/bliki/AnemicDomainModel.html

jgbt

ae cv, esse artigo ja foi citado antes e nunca parei p/ ler… :smiley:
vo da uma lida então e posto minhas considerações… :mrgreen:
valew!!

[]'s

J

VO e HashMaps podem ser usados para transportar dados de um tier para outro. Neste caso não são antipatterns pelo contrário.
Agora que eu entendi é que o autor do artigo condena o uso na camada de domínio e negócios, pois quebra a estrutra OO trabalhando com dados generalizados.

Então cv como você trabalha com dados agrupados.
ex:

a média de salário de departamentos. Agrupando por departamento e trazendo o nome de cada responsável.
onde departamento , responsável seriam entidades diferentes.

Para não usar HashMap só vejo DTO.

cv1

Se voce quer tanto a media de salario de um departamento, pq nao ter um metodo Departamento.getMedia(), que calcula a media baseando-se nos salarios dos funcionarios que fazem parte dele?

jgbt

blz, entendi a sua abordagem, mas fica a duvida:
o que o Departamento.getMedia() retornaria, ja que tem dados agrupados de 2 entidades? VO? HashMap? :mrgreen:

[]'s

F

blz, entendi a sua abordagem, mas fica a duvida:
o que o Departamento.getMedia() retornaria, ja que tem dados agrupados de 2 entidades? VO? HashMap? :mrgreen:

[]'s

Double ou Float nao? :mrgreen:

]['s

cv1

Nao, Joao… Departamento eh um objeto do seu dominio. Assim como tem getMedia():BigDecimal, tem getResponsavel():Funcionario, e tem getFuncionarios():Set… :wink:

Ele nao eh um VO, pq ele nao eh um objeto que serve so pra ser estuprado por um DAO, que manda pro controller fazer autopsia. Ele (oooooh, vejam so!) contem as regras de negocio relacionada a departamentos! :slight_smile:

jgbt

cv:
Nao, Joao… Departamento eh um objeto do seu dominio. Assim como tem getMedia():BigDecimal, tem getResponsavel():Funcionario, e tem getFuncionarios():Set<Funcionario>… :wink:

Ele nao eh um VO, pq ele nao eh um objeto que serve so pra ser estuprado por um DAO, que manda pro controller fazer autopsia. Ele (oooooh, vejam so!) contem as regras de negocio relacionada a departamentos! :)

blz, acho que agora rolou, objeto do dominio… ele é o responsavel pelas operações, ja me devolvendo o que interessa. tenho que começar a ver as coisas de maneira diferente… :mrgreen:

valew!!

[]'s

J

Isso que o CV colocou é o OO puro.
Mas isso não gera perda de performance.
Cada método faria uma consulta diferente ?

Não vivemos um mundo acadêmico.
Essas abordagens OO são bonitas mas como temos limitações tecnológicas temos que usar recursos que se baseam no bom senso.
é a balanca entre clareza de código X funcionalidade

Também volta avelha discussão do tráfego da rede para objetos remotos.
Isso na camada de negócio é fantastico, mas na camada de serviço tem que ser DTO ou HashMap mesmo.

cv1

jprogrammer:
Isso que o CV colocou é o OO puro.
Mas isso não gera perda de performance.

Isso foi uma pergunta? Se foi, a resposta eh nao. Ganho em produtividade e qualidade do codigo, sim.

Nao, cada metodo faz o que tem que fazer, e nao mais que isso :wink:

pcalcado

jprogrammer:
I
Isso na camada de negócio é fantastico, mas na camada de serviço tem que ser DTO ou HashMap mesmo.

Defina “Camada de Serviços”…

J

É uma pergunta sim (falou ?)
Quando falo de consulta eu falo de SQL mesmo, banco de dados.

ex:
eu faco a busca dos departamentos (uma SELECT), depois faço a busca da media (SELECT AVG(funcionario.salario) where funcionario.id_departamento = this.id);

ou poderia fazer um select direto que traria a média.

voltando a pergunta dos primitivos. É melhor usar Integer doque int.
pois assim posso ver se é nulo.
ou é melhor ter uma método isSalarioNull() e um int;

_fs

Não só isso cara. Integers são serializáveis.

J

Não sei o nome correto mas defino para os EJBs, Web Services, RMI.
Ou seja é uma camada que serve de ponte entre as tiers e delega requisiçoes do cliente para as regras de negócio no server.
máquina local->serviço remoto->regras de negócio

Que muita gente usa para colocar direto as regras de negócio.

Isso deve ter uma nome mais apropriado. Alguém sabe ?

pcalcado

Se sua aplicação realmente está distribuída (cliente -web app, swing, etc. - em máquina diferente do servidor), DTOs servem apra isso.

Se estão na mesma máquina, não é desculpa, trabalhe com seus objetos normais e poupe esforço e cabelos brancos :wink:

_fs

jprogrammer, serialize os seguintes objetos para um arquivo:

class DaoFoodObject {
    private Integer id;
    private String tempero;

    // getters setters
}

class SmartObject {
    private Integer id;
    private String tempero;

    // getters setters

    public void meuMetodoDeNegocio() {
         if( "sal".equals( tempero ) )
                  System.out.println( "Eu sou salgadinho." );
         else if( "açúcar".equals( tempero ) )
                  System.out.println( "Eu sou docinho." );
         else
                  System.out.println( "Eu sou natural." );
    }
}

E veja o tamanho dos dois arquivos gerados.

louds

Coitado do funcionario com salario nulo! :lol: Deve ser estagiario. :twisted:

Serio, HashMaps conseguem ser pior que VOs! Na hora do desenvolvimento meio que dão na mesma, mas depois de durante a manutenção é simplesmente o pior dos infernos. Fora a diferença gritante em termos de performance e consumo de memoria.

_fs

Louds por que dá diferença no consumo de memória?

rodrigousp

cv:
Nao, Joao… Departamento eh um objeto do seu dominio. Assim como tem getMedia():BigDecimal, tem getResponsavel():Funcionario, e tem getFuncionarios():Set… :wink:

Ele nao eh um VO, pq ele nao eh um objeto que serve so pra ser estuprado por um DAO, que manda pro controller fazer autopsia. Ele (oooooh, vejam so!) contem as regras de negocio relacionada a departamentos! :)


Então segue o dilema…

Eu deveria ter algo como
Negócio <-> Usuário
Usuário neste caso pode ser visto como um objeto também.

No entanto,
Meu objetos de negócios não sabem nada sobre banco de dados. Para isto, tem um AjudanteParaBd que sabe como “guardar” os objetos num banco de dados.
BD <-> AjudanteParaBD <-> Objetos <-> Usuário

Além disso, o usuário quer se conectar remotamente via http, mas meus objetos de negócio (por exemplo Departamento) nunca ouviram falar em "h-t-t- o que? ". Para existe um Servidor Web, que dá conta de converter o protocolo web em classes wrappers:
BD <-> AjudanteParaBD <-> Objetos <-> Servidor Web<-> Usuário

Mas, num dado momento um objeto terá que conhecer as regras de negócio e WebServer ou AjudanteParaBd.

Qual a prosposta para resolver este problema, tentando manter a clareza ?
Obs1: veja bem, eu to nem ai para performance e,
obs2: esta pergunta não é retórica.

De uma forma ou de outra, teremos que utilizar classes feias, que tem alguma coisa a ver com o negócio e com os problemas de tecnologia.

Se isto já não é tosco o suficiente, poderíamos querer uma série de coisas como escabilidade, segurança, transação, “etc e etc”, que seriam resolvidos de que maneira ???

E se você tiver utilizando ejbs para resolver o problema de “etc e etc”, mesmo que seja numa mesma máquina terá que utilizar um “objeto que não faz nada” (tipo um DTO), porque Departamento não sabe como notificar um funcionário sobre seu bônus, sem fazer uma chamada de jndi para algum serviço (banco de dados, ejb, etc), que altere o estado de alguma instância.

Talvez, você possa ter um Objeto de negócio com vários métodos abstratos, implementados por um objeto concreto que tenha as regras e os conhecimentos tecnológicos… Num sei…

Mas enfim, ejb != OO. E java também não é 100% OO. Se quiser algo bonito mesmo, use Smalltalk. E viva o GUS.

pcalcado

E quem exatamente falou que isso não ia ser necessário? Só não coloque suas classes de negócio lá.

Além das tradicionais, AOP ajuda bastante.

Pera…usar EJB te obriga a usar DTOs?

Ahco que vc está complicando demais as coisas… :roll:

Uma coisa é uma Linguagem OO, outra cosia é Programação OO. Ou você acha que não dá pra produzir código rpocedural em Smalltalk ou Eifell, ou utilizar Objetos em C?

No livro do Meyer tem uma seção só sobre como programar utilizando objetos em C, Ada, Fortran… e até esmo Java e C++ :wink:

louds

Porque um HashMap guarda uma tonelada a mais de informação.

class Exemplo {
 int um;
 String dois;
}

Na memoria de um pc comum um objeto Exemplo ficaria assim:

Já um HashMap teriamos:

Puxa, só isso? É menos de 2x maior! Mas não é só isso! Ainda tem MUITO mais.

Alem do objeto HashMap, temos os seguintes objetos acompanhando:

:arrow: array Entry[16] -> 40 bytes
:arrow: 2 HashMap.Entry -> 2 x 24bytes -> 48bytes
:arrow: 1 Integer -> 12 bytes

total: 128 bytes

As duas Strings de chave podemos dizer que são de graça pois normalmente vem de algum constant pool.

Ou seja, gastamos 8x mais memoria, criamos 5x mais trabalho pro GC e o tempo de busca de uma propriedade fica lento nessa proporsão.

Mas esse argumento para mim é apenas um detalhe perto da dificuldade de se trabalhar com código escrito usando HashMap Oriented Development.

cv1

*** aplausos pro louds ***

Rodrigo, sobre a sua duvida de como fazer os objetos do dominio falarem com o DAO e serem vistos pela UI ao mesmo tempo, dah uma lida na thread do Rafael Steil sobre o refactoring do JForum. Eh exatamente o que ele ta fazendo :wink:

rodrigousp

Eu li o tópico que vc falou… Ufa… Deu trabalho:
http://www.guj.com.br/posts/list/22689.java

Seguem as seguintes considerações:

  1. Existe a regra de ouro da refatoração:
    Mantenha isto simples. Faça a solução mais simples que resolva o problema de hoje. Caso você repita isto uma vez, preste atenção mas ainda não mude nada. Se acontecer denovo, refatore.
    _ é tão legal esta regra!!! Poupa um tempo evitando que gastemos horas com a solução mais flexível, ótima e elegante para besteiras sem repetição.
    _ corolário: você pode fazer copy & paste de uma parte do código uma única vez, mas pode.

  2. SmallTalk existe sem Interfaces. Mas, Interface é apenas a implementação Java (e de outras linguagens) do padrão Strategy o qual existe em SmallTalk. No entanto, você tinha absoluta razão naquela discussão, devido a regra de ouro da Refatoração.

  3. Finalmente o ponto sobre DTO. O que impede que eu extrai uma interface de um objeto que seja apenas uma visão parcial de seu estado?

Objetos em banco de dados podem conter um quantidade de informações que (para um ser contexto) seja irrelevante. Poderia tratar apenas parte dessas informações?

E outra: eu gostaria de fornecer a uma classe cliente informações sobre uma certa área de negócio. Poderia expor apenas os valores do objeto sem expor as regras de negócio , ou métodos que não me interessa que o cliente enxergue ?

Note, eu não estou falando em criar objetos com apenas getters e setters. Estou falando de expor uma interface de um pojo que contenha apenas os tais getters e setters. (em última instância um cliente “safado” poderia acessar os demias métodos do objeto por reflection ou por casting. Haveria alguma maneira de evitar isto?)

Valeu.

cv1

Expor uma interface mais limitada a objetos para clientes que nao deveriam acessar metodos “perigosos” nao tem problema algum. Eh uma boa ideia, alias, se vc nao souber quem esta do outro lado. Do contrario, nao vejo muito sentido - se o dominio so vai ter clientes que vc mesmo vai desenvolver, pula essa parte e documenta em algum lugar “este metodo nao deve ser chamado fora da camada tal” :wink:

rodrigousp

+4 pontos pela qualidade da resposta.
+1 pela velocidade…

Eu vejo um sentido. Para mim fica mais fácil… sem ter que consultar API sei (pelo código) o que pode ou não pode ser usado. E acho mais! Acho que isto ajuda num trabalho de equipe pois fica bem claro no “Ctrl + Espaço” o que pode ser usado.

Tipo uma programação defensiva:
http://c2.com/cgi/wiki?DefensiveProgramming

Pelo que o pessoal falou o serializeble do objeto é igual ao seu equivalente em DTO, uma vez que só o estado precisa ser “serializado”. É isto mesmo ?

Criado 14 de abril de 2005
Ultima resposta 16 de abr. de 2005
Respostas 33
Participantes 9