DTO: Por que usar uma coisa dessas?

55 respostas
saoj

Me deparei com um projeto onde estão usando DTO na camada de serviço. Algo como:

List<UserDTO> searchUsers( … );

Na minha cabeça isso é o lixo do lixo.

Por que estavam fazendo isso?

:arrow: Para definir o formato da resposta do WebService que é em JSON. Ex: o User pode ter um atributo firstName mais a resposta do protocolo pode esperar name.

:arrow: Por que estavam usando um conversor de object para Json (JacksonView do Spring) que por reflection acessava todas as propriedades do objeto, carregando toda a hierarquia e até causando loop infinito em dependências cíclicas ManyToMany. (Obrigado Hibernate!)

O que eu falei para os malucos:

:arrow: Camada de serviços só pode trabalhar com modelo, entidades reais, nunca DTO.

:arrow: Quando precisar formatar alguma resposta, evitar lazy loading, trocar nome das propriedades, etc. Só há duas opções: 1) template engine (Velocity ou FreeMarker) ou 2) DTO genérico = Map

Isso é para um webservice que retorna respostas em JSON.

Então ficou a pergunta. Quando se justifica usar um DTO. Quem inventou isso?

55 Respostas

Hebert_Coelho

Eu estou estudando EJB pelo EJB3 In Action e nele ele fala que o DTO foi “criado” para realizar a transmissão de objetos entre contextos diferentes. Pois ele não é o objeto em si, apenas uma representação dele. Ex.: Pessoa e PessoaDTO (conteria apenas strings por exemplo)

Eu trabalhei em um sistema que usava DTO como meio de transporte de informação da View para o Controller. Ao invés de se passar um monte de String picada para o controller trabalhar, passava o DTO que já era o objeto que a View montou.

Mais info, aqui ó.
http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html


http://www.theserverside.com/discussions/thread.tss?thread_id=32389

Rubem_Azenha

http://martinfowler.com/eaaCatalog/dataTransferObject.html

Exemplo tosco e mal pensado mas que ajuda a explicar:

Voce tem um servico remoto que calcula imposto de cada produto de um carrinho de compras.

Se por acaso seu carrinho tem milhares de itens, serao geradas milhares de chamadas remotas, gastando muito com I/O.

Alguem poderia fazer algo assim:

Pra economizar chamadas remotas.

Alexandre_Saudate

Eu partilho da sua aversão a DTO. Acho que ele é um ótimo pattern… pro ano 2000. Hoje em dia, não tem a menor necessidade, seja em qualquer contexto, web services ou não, porque:

  1. Se for um ambiente Java puro, o EJB3 pode muito bem trafegar sem carregar as dependências desnecessárias.

  2. Se for um ambiente composto de web services, só anotar os atributos que não desejamos trafegar. Isso inclui, claro, referências a listas.

Acho que o único caso em que se aplica, se for, é o caso em que eu desejo apresentar diferentes visões dos objetos para diferentes clientes. Só que, isso já muda o Design Pattern, já que DTO é feito para falar de transferência de dados e não de máscara de dados. Não sei qual seria o nome do pattern, então, só sei que DTO é que não é.

[]´s

Alexandre_Saudate

Rubem Azenha:
http://martinfowler.com/eaaCatalog/dataTransferObject.html

Exemplo tosco e mal pensado mas que ajuda a explicar:

Voce tem um servico remoto que calcula imposto de cada produto de um carrinho de compras.

Se por acaso seu carrinho tem milhares de itens, serao geradas milhares de chamadas remotas, gastando muito com I/O.

Alguem poderia fazer algo assim:

Pra economizar chamadas remotas.

OK, mas com a velocidade de transferência de que dispomos hoje, talvez seja mais interessante (às vezes) trafegar várias vezes pacotes pequenos, dando a chance de outros consumidores efetuarem também pequenos processamentos, do que cada um enviar um pacote muito grande, não? Assim, se der algum problema em alguma das chamadas (a rede não é perfeita), o processamento todo não é perdido. O que você acha?

[]´s

Rubem_Azenha

asaudate:

OK, mas com a velocidade de transferência de que dispomos hoje, talvez seja mais interessante (às vezes) trafegar várias vezes pacotes pequenos, dando a chance de outros consumidores efetuarem também pequenos processamentos, do que cada um enviar um pacote muito grande, não? Assim, se der algum problema em alguma das chamadas (a rede não é perfeita), o processamento todo não é perdido. O que você acha?

[]´s

Eu acho que DTO é uma pattern que deve ser aplicada apenas se e quando depois de medir o desempenho da aplicacao, utilizando um profiler ou outra ferramenta adequada, for identificado que o I/O gerado pelas multiplas chamadas é o gargalo. Realmente nao deve ser a abordagem default para servicos remotos.

saoj

Sim, mas vc pode usar um Map que é um DTO genérico para qualquer objeto. Ficar criando um DTO para cada comunicação que vc precisa fazer é overkill.

Como eu falei: acredito que o certo nesse caso é passar os próprios objetos do negócio para a view e ela se encarrega de apresentá-los da maneira que ela quiser via templates, JSP, tags, etc. No meu caso a minha view usava reflection para converter o objeto para JSON, o que poderia ser um problema. Então teria que ter uma camada intermediária para preparar um Maps (DTO genérico) para a view. Mas isso nunca deveria ter sido feito na camada de serviços.

saoj

Rubem Azenha:
http://martinfowler.com/eaaCatalog/dataTransferObject.html

Exemplo tosco e mal pensado mas que ajuda a explicar:

Voce tem um servico remoto que calcula imposto de cada produto de um carrinho de compras.

Se por acaso seu carrinho tem milhares de itens, serao geradas milhares de chamadas remotas, gastando muito com I/O.

Alguem poderia fazer algo assim:

Pra economizar chamadas remotas.

Não entendi.

Vc vai passar o objeto de negócio Produto ou vai passar um ProdutoDTO. Mesma coisa para o CarrinhoDeCompras.

A comunicação entre sistemas deve ser feita via JSON ou XML. O que se faz é usar DTO como TEMPLATE para FORMATAR essa resposta. Meu ponto é que o melhor é usar template engine ou um DTO genérico (MAP).

saoj

O que vejo é que as pessoas estão usando DTO como TEMPLATE ENGINE. No teu caso, cada cliente seria direcionado para um template diferente. Se vc não quiser usar templates, vc teria um IF onde um Map seria preparado de maneira diferente para cada cliente. Depois esse MAP seria convertido para JSON ou XML. No caso aqui estou falando de WebService. Se fosse uma aplicação web vc teria um IF dentro do seu JSP ou dois JSPs diferentes.

O que me deu vontade de fazer foi o seguinte.

:arrow: Para web services

:arrow: Ao invés de dar um forward para um JSP ou TEMPLATE ENGINE que fai gerar a resposta a partir dos OBJETOS DE NEGOCIO.

:arrow: Vc dá um forward para um Objeto Java que vai preparar o MAP. Depois esse MAP é convertido para JSON e pronto.

:arrow: Seria uma maneira de organizar as versões por examplo, para vc não ter um milhão de IFs gerando o seu map no futuro.

Rubem_Azenha

saoj:
Não entendi.

Vc vai passar o objeto de negócio Produto ou vai passar um ProdutoDTO. Mesma coisa para o CarrinhoDeCompras.

A comunicação entre sistemas deve ser feita via JSON ou XML. O que se faz é usar DTO como TEMPLATE para FORMATAR essa resposta. Meu ponto é que o melhor é usar template engine ou um DTO genérico (MAP).

Sergio, o ponto é voce agregar varios objetos num objeto só e fazer uma só chamada com esse objeto. Nao tem nada haver com JSON ou XML e sim como vai ser a interface do servico. Nao tem nada haver com template ou formato.
E nao precisa chamar “ProdutoDTO”. Nao tem nenhuma regra.
E DTO generico nao é uma boa idéia, se nao voce perde completamente o sentido de ter uma interface e um contrato.

bestlinux

Aqui usamos como Template para relatorios.

Hebert_Coelho

saoj:
Sim, mas vc pode usar um Map que é um DTO genérico para qualquer objeto. Ficar criando um DTO para cada comunicação que vc precisa fazer é overkill.

Como eu falei: acredito que o certo nesse caso é passar os próprios objetos do negócio para a view e ela se encarrega de apresentá-los da maneira que ela quiser via templates, JSP, tags, etc. No meu caso a minha view usava reflection para converter o objeto para JSON, o que poderia ser um problema. Então teria que ter uma camada intermediária para preparar um Maps (DTO genérico) para a view. Mas isso nunca deveria ter sido feito na camada de serviços.

Um map? Não entendi… Se eu tenho uma classe Pessoa com 5 atributos …

Como vc passaria isso em um map (Sem ser objeto pessoa)?

Supondo uma busca de pessoa por nome, na primeira classe java que recebe o request (servlet/action/sei lah) vc recebe uma chave “nomePessoa” vc fala que é melhor criar um objeto Pessoa e passa-lo para o controle? Já conversaram comigo sobre esse tipo de ação, nunca trabalhei com ele não.

O problema dessa aplicação era o fato de que era algo legado e o framework não tinha como ser atualizado… aí complica né? =/

saoj

Então vc está efetivamente criando mais uma entidade para o seu modelo chamada CarrinhoDeCompras porque alguém precisa receber CarrinhoDeCompra. Vc não está pegando o CarrinhoDeCompra e formatando ele via um CarrinhoDeCompraDTO para que vc possa passá-lo na rede. O problema é usar DTO como TEMPLATE. É o que encontrei no projeto aqui. :frowning: Me corrijam se eu estiver errado, mas qualquer formatação pode e deve ser feita com MAPs.

saoj

Vc pode converter qualquer objeto em um MAP. Até propriedades que são objetos, arrays, listas, etc. O seu objeto pessoas acima pode ser facilmente convertido num Map. Jogado na rede em JSON ou XML e reconstruído do outro lado.

O ideal seria usar Reflection para fazer isso, mas porque vc pode ter um objeto via Hibernate, cheio de lazy loading, com hierarquia de objetos longa e até ciclica (obrigado Hibernate) vc provavelmente vai querer fazer isso na mão.

Rubem_Azenha

saoj:

Então vc está efetivamente criando mais uma entidade para o seu modelo chamada CarrinhoDeCompras porque alguém precisa receber CarrinhoDeCompra. Vc não está pegando o CarrinhoDeCompra e formatando ele via um CarrinhoDeCompraDTO para que vc possa passá-lo na rede.

Eu nao estou criando uma entidade nova no sistema… estou criando uma classe. So nao chamei ela pelo sufixo DTO. Voce nao precisa criar uma classe nova, pode ser que a classe ja existe no sistema. Provavelmente nao vai existir, ai vc cria uma nova, mas eu nao acho que ela precisa ser uma entidade e nao acho que ela precisa ter o sufixo DTO.

saoj:

O problema é usar DTO como TEMPLATE. É o que encontrei no projeto aqui. :frowning: Me corrijam se eu estiver errado, mas qualquer formatação pode e deve ser feita com MAPs.

Nao entendi o que significa DTO como Template. E nao é uma boa ideia usar um Map ao inves do uma classe “de verdade”.

*EDIT: Pensando bem, nao é bom reaproveitar classes do sistema para transformar em DTOs… O ideal criar uma classe nova para isso e deixar claro que ele serve apenas para agregar varios objetos numa chamada remota.

saoj

Rubem Azenha:
saoj:

Então vc está efetivamente criando mais uma entidade para o seu modelo chamada CarrinhoDeCompras porque alguém precisa receber CarrinhoDeCompra. Vc não está pegando o CarrinhoDeCompra e formatando ele via um CarrinhoDeCompraDTO para que vc possa passá-lo na rede.

Eu nao estou criando uma entidade nova no sistema… estou criando uma classe. So nao chamei ela pelo sufixo DTO. Voce nao precisa criar uma classe nova, pode ser que a classe ja existe no sistema. Provavelmente nao vai existir, ai vc cria uma nova, mas eu nao acho que ela precisa ser uma entidade e nao acho que ela precisa ter o sufixo DTO.

Uma classe que representa alguma coisa concreta: CarrinhoDeCompra. Se ela vai ser persistida no banco de dados ou não, não interessa muito. Por que vc não quer chamá-la de entidade? Um carrinho de compras é uma entidade. Se você quer criar apenas um AGRUPADOR de coisas, então use COLLECTIONS.

“Rubem Azenha”:

Por que? Melhor usar um MAP do que usar um CarrinhoDeCompraDTO, ou seja, um mero formatador para o CarrinhoDeCompra. Consigo ver algumas vantagens de usar DTO. Type checking. As propriedades são métodos e não Strings como Maps, etc. Mas ainda fico com a flexibilidade e limpeza dos Maps.

saoj

Se vc quer usar DTO como template para exibir objetos, tudo bem. É factível. Eu consideraria primeiro MAPs e TEMPLATE ENGINE. O Map é um DTO genérico muito poderoso e flexível.

Agora NUNCA meter DTO no meio dos serviços, algo to tipo como encontrei aqui:

List<UserDTO> searchUsers( ... )
Paulo_Silveira

Rubem Azenha:

Eu nao estou criando uma entidade nova no sistema… estou criando uma classe. So nao chamei ela pelo sufixo DTO.

Eu gosto dessa abordagem do Azenha: nao usar sufixo. Evita-los ao maximo.

As vantagens em relacao ao Map sao as que voce mesmo citou: ganha type safety e clareza quando for ler codigo de outra pessoa. Ficar jogando Map de um lado pro outros vai fazer a gente trabalhar com a famosa POS: Programacao orientada a strings. Map voce ganha flexibilidade, e de quebra, complexidade para manter. A escolha é sua.

O ponto importante é so lembrar de usar DTO quando tem inumeras invocacoes remotas que poderiam ser feitas tudo numa so. E, como o Azenha ja frisou, nao tem pra que usar o sufixo DTO.

Felagund

Li toda a discusão e não entendi essa cisma em usar MAP para gerar XML e JSON recorrendo a reflection para buscar os campos, vc vai converter um objeto inteiro para transmitir inclusive usa hierarquia? Acreido que seria a hora de migrar a aplicação para MongoDB ou Couch…

Eu não preciso criar um CarrinhoDeComprasDTO, só crio um CarrinhoDeCompras e ele não vai ser perssisto, vc substituiria isso:

public class CarrinhoDeCompras{
    private Collection&lt;ProdutoCarrinho&gt; produtos;
    
}

public class ProdutoCarrinho{
    private Produto produto;
    private Integer quantidade;

}

Só ilustrando o que eu entendi dos posts do Rubem (se eu entendi errado por favor me corriga), pra usar um MAP ou COLLECTION?

Me diga vou perder legibilidade e conseguetemente TypeSafe por qual motivo?

Rubem_Azenha

saoj:

Por que? Melhor usar um MAP do que usar um CarrinhoDeCompraDTO, ou seja, um mero formatador para o CarrinhoDeCompra. Consigo ver algumas vantagens de usar DTO. Type checking. As propriedades são métodos e não Strings como Maps, etc. Mas ainda fico com a flexibilidade e limpeza dos Maps.

Ja que é pra apelar, faz assim na tua classe:

public static Object executa(Map parametros, String nomeServico)

Limpo e flexivel.

Alexandre_Saudate

Aliás, insisto, o melhor é não usar DTO (ou, pelo menos, evitar ao máximo).

[]´s

saoj

Paulo Silveira:
“Ruben Azenha”:

Eu nao estou criando uma entidade nova no sistema… estou criando uma classe. So nao chamei ela pelo sufixo DTO.

Eu gosto dessa abordagem do Azenha: nao usar sufixo. Evita-los ao maximo.

O ponto importante é so lembrar de usar DTO quando tem inumeras invocacoes remotas que poderiam ser feitas tudo numa so. E, como o Azenha ja frisou, nao tem pra que usar o sufixo DTO.

[/quote]

Perfeito. Lembrando duas coisas:

:arrow: que se vc quer agrupar um monte de coisas para jogar para o outro lado vc pode e deve considerar o uso de COLLECTIONS.

:arrow: no caso do CarrinhoDeCompras, a chance é grande desse cara virar um objeto do modelo de negócios. Então ele merece uma classe pra ele que não tem nada haver com DTO.

Entendo o seu ponto, mas acho que Maps não introduzem complexidade. Usando reflection vc pode facilitar bastante as coisas.

InjectionUtils.addToMap(map, user, "username", "firstName", "email");

Imagine a situação onde vc tem duas páginas, ou dois web services: São idênticos, mas um espera dateOfBirth e o outro espera birthDate. Vc vai criar um novo DTO só por causa disso. Com Map isso se torna ridículo. Eu gosto dessa flexibilidade.

saoj

Rubem Azenha:
saoj:

Por que? Melhor usar um MAP do que usar um CarrinhoDeCompraDTO, ou seja, um mero formatador para o CarrinhoDeCompra. Consigo ver algumas vantagens de usar DTO. Type checking. As propriedades são métodos e não Strings como Maps, etc. Mas ainda fico com a flexibilidade e limpeza dos Maps.

Ja que é pra apelar, faz assim na tua classe:

public static Object executa(Map parametros, String nomeServico)

Limpo e flexivel.

Hehehe. Engraçado. Mas não. Me refiro apenas para quando vc tem que TRANSMITIR dados de um lado para o outro. Ou formatá-los.

maior_abandonado

ja deu pra ver que isso é uma questão de opinião… mas como isso aqui é um fórum de discussão, a minha é que o map sem duvida deixa mais versatil, porém tem um outro lado negativo, tabalhando com uma classe, ou melhor… com uma interface, você sabe exatamente o que esperar… você vai ter um metodo getXXX por exemplo, que vai te retornar a informação xxx… ok, com a classe você sabe exatamente o que você pode ter nela… com o mapa você pode ter qualquer coisa la… claro que você pode num exemplo simplista iterar a chave e saber todos os pares de chave/valor que tem la, mas isso é bem mais complicado, fica um código mais sujo, fora de padrão, que você só sabe o que tem la realmente em tempo de execução, diferente de usar uma classe DTO…
Numa boa, você até pode criar um “util” para trabalhar com o seu mapa que se refere a alguma coisa trafegada… mas isso parece simplificar alguma coisa? Ao menos não para mim…

quanto a usar o sufixo DTO ou mesmo VO, eu acho um tanto relativo… quando você tem um web service por exemplo para trocar informações com parceiros, tem até uma probabilidade alta de que quando o seu parceiro veja que você está retornando para ele um objeto Boleto, por exemplo, ele deduza que seja um VO, mas pode ser que ele não deduza isso, então o sufixo VO torna essa possibilidade dele entender isso mais fácil (e a poluição gerada é pequena, ao menos na minha opinião, sendo trocada essa poluição por um código mais fácil de entender), por isso eu sou a favor de se utilizar este sufixo “dependendo do escopo do projeto”.

G

Impressionante como o pessoal quer programar em Java como se fosse PHP. Todo mês aparece aqui no GUJ algum tópico de alguém reclamando de lazy-load e DTOs. Mas o mais incrivel é ver que falam sem mesmo conhecer para que serve realmente um DTO.

Obvio que o principal fundamento do DTO é para trabalhar com aplicações onde você possui módulos EJB remoto. Porém mesmo em aplicações onde você não possui a separação de projetos eu prefiro usar o DTO, pois assim eu entrego para a camada client os dados já formatados e carrego somente (e tudo) o que eu preciso.

Eu já havia escrito isso há algum tempo, quando um usuário do Vraptor reclamou do lazy-exception. Lendo esse post dá para entender bem porque os DTOs são necessários. http://guj.com.br/posts/list/15/204519.java#1039241

Agora quando ao sufixo DTO eu uso para diferenciar uma entidade Customer dos seus DTOs CustomerDTO e CustomerDetailsDTO, assim como uso CustomerBean e CustomerRemote no nome dos EJBs. Mas creio que isso seja uma questão de gosto.

saoj

garcia-jj:
Impressionante como o pessoal quer programar em Java como se fosse PHP. Todo mês aparece aqui no GUJ algum tópico de alguém reclamando de lazy-load e DTOs. Mas o mais incrivel é ver que falam sem mesmo conhecer para que serve realmente um DTO.

Acho que vc se empolgou.

Sim. Essa é a definição. Mas quando vc vê alguém fazendo isso:

List<UserDTO> users = searchUsers( ... )

Vc percebe que o cara não entendeu DTO.

Continuo achando melhor usar Map do que DTO. Não gosto de ter um milhão de DTOs. Como dei o exemplo. Se um serviço requer a mesma resposta, com apenas uma propriedade diferente, exemplo: username tem que sair e entrar gamertag, então vc vai ter que fazer um novo DTO só para isso, quando se vc estivesse usando um Map, a coisa seria ridícula.

E Lazy loading pode ser um saco, principalmente quando vc tem relações ManyToMany cíclicas. E pelo jeito não sou o único que reclama. Mas o Hibernate oferece muitas outras vantagens que vale a pena passar por cima disso. Pelo jeito não sou o único que não gosta de lazy loading.

G

Sérgio, entendi seu ponto de vista. Só penso que usando Map você perde a tipagem, e também você não sabe o que você tem no seu objeto sem fazer instrospecção ou ler a documentação. Em um DTO se você tem uma propriedade UserDTO.getNome você de cara vê que é o nome. Além disso em alguns momentos você pode precisar fazer type-cast, além de que você deixa uma margem para que alguém por engano mande um String ao invés de um Date.

Eu tenho usado uma estrutura semelhante ao que a Sun propoe do DTO. Se eu tenho uma entidade User e tenho uma dela de listagem e outra de detalhe eu crio dois DTOs: UserDTO e UserDetailDTO. No UserDTO coloco apenas as propridades que precisa para listagem, e a UserDetailDTO estende UserDTO com as demais propriedades. Isso tem atendido bem meus atuais projetos com EJB remoto.

luistiagos

Paulo Silveira:
Rubem Azenha:

O ponto importante é so lembrar de usar DTO quando tem inumeras invocacoes remotas que poderiam ser feitas tudo numa so. E, como o Azenha ja frisou, nao tem pra que usar o sufixo DTO.

bem isto não e nada… pior e em uma empresa que trampei que eles chamavam as tabelas do banco com o sufixo de tb, exemplo: cliente_tb… :shock:

G

Ou então campos mn_processo, ds_processo, dt_processo. :shock:

Mas quando aos DTOs, se eu não usar sufixo, fico com classes com o mesmo nome. Exemplo: Usuario (entidade), Usuario (DTO), UsuarioDetalhe (DTO). :shock:

R

No caso de cliente Flex com BlazeDs, usar DTO nao seria o mais adequado?

B

Depende![/resposta padrão]

A questão é trafegar dados entre duas aplicações, e o custo de cada uma dessas chamadas remotas, que é bem caro. Se tiver que gastar mais de uma chamada p/ transferir um conjunto de dados, e houver a necessidade de diminuir este custo, aí empacotar os objetos(somente o mínimo de dados necessários) em um DTO pode valer a pena.

Senão, beleza, pode continuar como já está.

Hebert_Coelho

A sim, tinha esquecido de falar.

No livro que ainda estou lendo (EJB3 In Action) o autor fala que quando tratamos com XML (E não DTO ou Objeto) o processamento da máquina cai muito.
Que chega a ser inviável em alguns casos.

Alexandre_Saudate

jakefrog:
A sim, tinha esquecido de falar.

No livro que ainda estou lendo (EJB3 In Action) o autor fala que quando tratamos com XML (E não DTO ou Objeto) o processamento da máquina cai muito.
Que chega a ser inviável em alguns casos.

Me diga quem é o autor, pra que eu possa falar bastante mal dele =P

Esse autor nunca ouviu falar de web services, não???

Hebert_Coelho

asaudate:
jakefrog:
A sim, tinha esquecido de falar.

No livro que ainda estou lendo (EJB3 In Action) o autor fala que quando tratamos com XML (E não DTO ou Objeto) o processamento da máquina cai muito.
Que chega a ser inviável em alguns casos.

Me diga quem é o autor, pra que eu possa falar bastante mal dele =P

Esse autor nunca ouviu falar de web services, não???

Bem, não entendo muito mas… Como é o relacionamento de EJB com Web Service? Não sei te falar exatamente o pq ainda, mas sei que está aí o problema. [=

G

Esse assunto de XML lento ou não é bem off-topic, mas vamos lá. Sim, o webservice é mais pesado que você usar EJB remoto, por exemplo. Nos projetos na qual eu participo sempre aconselho o pessoal a usar webservice se você precisa realmente trabalhar com transporte via HTTP ou então comunicação entre projetos de linguagens diferentes. Se for um projeto full-Java indico a usar EJB.

Hebert_Coelho

Off topic né não. Pq uma das soluções apresentadas aqui, para não se usar DTO, foi usar XML. :slight_smile:

B

Off topic né não. Pq uma das soluções apresentadas aqui, para não se usar DTO, foi usar XML. ^_^

What the fuck? :? Como assim? Que non sequitur é esse?

Alexandre_Saudate

Bom, é off-topic mesmo. Mas, só pra falar um pouco… eu sou consultor SOA (ou seja, eu trabalho com web services o tempo inteiro). E, mesmo assim, no momento estou trabalhando numa aplicação que precisa de baixíssimo tempo de resposta (do tipo: faz qualquer um arregalar os olhos). Dá- se um jeito :wink:

[]´s

G

Off topic né não. Pq uma das soluções apresentadas aqui, para não se usar DTO, foi usar XML. ^_^

DTO não tem nada a ver com XML e vice-versa. DTO é apenas uma classe que serve para transporte de dados. XML/Webservices serve para outra coisa :slight_smile:

Hebert_Coelho

Off topic né não. Pq uma das soluções apresentadas aqui, para não se usar DTO, foi usar XML. ^_^

DTO não tem nada a ver com XML e vice-versa. DTO é apenas uma classe que serve para transporte de dados. XML/Webservices serve para outra coisa :)

Eu sei mano. Oq foi dito lah no começo deste tópico foi. Ao invés de usar DTO usar um MAP ou um XML. É isso q eu to falando.

Ao invés de passar ClienteDTO passar e assim vai…

saoj

jakefrog:

Eu sei mano. Oq foi dito lah no começo deste tópico foi. Ao invés de usar DTO usar um MAP ou um XML. É isso q eu to falando.

Ao invés de passar ClienteDTO passar e assim vai…

Para a comunicação, seja lá o que vc estiver usando vai ter que ser convertido para XML, JSON, Java Serialization, XXXX.

Isso não tem nada haver com DTO. O ponto do Map foi:

Um Map pode ser convertido tão bem quanto um DTO para um desses acima. Se vc quer apenas agrupar um monte de coisas para jogar para o outro lado, vc pode usar uma Collection pra isso, não precisa criar um objeto agrupador.

Mas isso vai cair no gosto de cada um. Usar um DTO tem vantagens e desvantagens, assim como um MAP. Eu não gosto de ter um milhão de DTO’s na minha aplicação. Vai ter algum esperto que vai jogar eles no meio da lógica e cagar tudo. Eu prefiro MAP. Mas use o que vc preferir e seja feliz ! Acho que não é pecado nem um nem outro… :slight_smile:

RicardoCobain

Acredito que usar Map, resolve… mas não acredito que seja a melhor solução…
pois como foi falado anteriormente (no forum guj) quando eu coloco alguma coisa no Map, eu não sei nem o que se “esta la dentro”, a não ser que eu saiba o que “eu coloquei”, eu não vou ter um map.getNome(), map.getIdade(); isso pode quebrar o contrato da aplicação e nunca vai dar um erro de compilação se eu errar a grafia (se eu usar MAP e passar name ao inves de nome, não da erro nem nada , ai o cara se perde aos poucos . a O.O se perde…)

Alem que a programação fica massante e redundante…
o cara faz…:

<blockquote>List<Cliente> clientes = dao.listAll();

List<Map> clienteMap = new ArrayList<Map>();

… dai vcs sabem o resto…(um new map >> alimenta map >> add into list)

código procedural…

</blockquote>

e sem falar que a refatoração fica impossivel, se eu quise mudar um nome de algum atributo do cliente… tenho que sair catando os maps, e ir mundando as strings… isso é chato…

Map é uma solução rápida, mais não eficiente…
Bem na minha humilde opinião. =)

diogopontual

Acho que o pessoal está confundindo Alhos com Bugalhos…

Alguns conceitos para embasar meus argumentos:

DTO => É uma "classe/estrutura de dados", serve para: Estruturar dados… Um Map também é uma estrutura de dados… Ambos podem ser usados nas mesmas situações (e devem ser usados apenas em situações bem especĩficas).

XML => eXtensible Markup Language… No contexto da thread serve apenas como formato no qual os dados transitarão na rede… Não compete nem com os mapas, nem com os DTO’s… Ambos podem ser serializados em XML, para transitar na rede. (Normalmente eu uso JSON pq é bem menos verboso).

Fujam de DTO, a não ser quando eles forem usados na fronteira entre duas camadas heterogêneas, em termos de máquinas, ou tecnologia ou coisas assim… Ou seja: Só use DTO’s quando precisar estabelecer uma barreira bem clara para os seus objetos de negócio (a causa dessa fronteira pode ser um requisito de segurança, máquinas diferentes, tecnologias diferentes…). Não os use para tráfegar dados dentro da fronteira da sua própria aplicação…

saoj

diogopontual:

Fujam de DTO, a não ser quando eles forem usados na fronteira entre duas camadas heterogêneas, em termos de máquinas, ou tecnologia ou coisas assim… Ou seja: Só use DTO’s quando precisar estabelecer uma barreira bem clara para os seus objetos de negócio (a causa dessa fronteira pode ser um requisito de segurança, máquinas diferentes, tecnologias diferentes…). Não os use para tráfegar dados dentro da fronteira da sua própria aplicação…

Falou bonito Diogo !!! Bom encontrar pessoas que conseguem entender o nosso ponto de vista. Concordo que no meu caso, em todos os aspectos mundanos, isso é raro. O que pode ser bom… ou não…

Minha resposta ao Ricardo:

Posso estar enganado, mas acho que os benefícios apontados pelo Ricardo são ilusórios. Por que?

Não, o OO não se perde mas sai ganhando. Porque vc fica obrigado a usar as entidades na lógica e não um monte de DTO ou MAPs. Não é para usar DTO nem MAP na lógica e sim usar os domain objects (User, Product, etc). Se vc concorda com isso, então a tarefa de FORMATAR o resultado passa a ser da ACTION ou da VIEW. No caso aqui estamos falando de JSON, então cada resposta em JSON terá que ser formatada por um DTO diferente. Talvez vc consiga reutilizar um ou outro, mas vai se tornar uma bagunça de DTOs. O benefício que vc citou de refatoração não se aplica, porque se vc muda “nome” para “name”, vc vai ter que se lembrar de ir lá nos DTOs e mudar getNome por getName. Isso na mão. Ou não? Logo não vejo diferença em usar um MAP. Teria diferença se o seu DTO estivesse espalhado pela aplicação inteira, mas aí o problema seria outro.

Então vc prefere que o DAO já retorne um DTO ??? Errado e impossível, porque dependendo da action / request o cliente vai ter que ser convertido para um DTO diferente. Vc pode ter uns esquemas bem espertos para popular um MAP a partir de um BEAN, pegando só as propriedades que lhe interessam. Usando DTO vc terá que fazer a mesma coisa, pois na minha opinião um DAO nunca deveria retornar um DTO (incluindo MAP que é um DTO genérico).

Posso não estar vendo alguma coisa, mas na minha cabeça com DTO vc tb não tem refatoração. DTO é uma coisa burra, sem lógica, que serve apenas para ESPECIFICAR um objeto. Se o cliente passa a esperar nome ao invés de name, então vc vai ter que catar todos os DTO’s que possuem getName e trocá-los para getNome.

Acho que a confusão parte do seguinte: Não estou propondo usar MAP em tudo que é lugar. Isso realmente seria péssimo. Proponho usar um MAP na hora de FORMATAR um resultado, ou seja, no ULTIMO passo do processo, assim como um JSP é o último passo do processo. Lembrando que isso só se aplica para JSON por cause do problema do lazy loading com reflection.

O que não estou vendo? (posso estar errado)

PS: No final, o Ricardo teve uma idéia melhor do que um MAP. Um BeanView que implementa Map. Por que tem que implementar Map ??? Por que o danado do JSON-LIB sabe transformar map em Json. Mas se não for mapa ele vai procurar por getters pensando que é um DTO. Ou seja, o proprio JSON-LIB, por querer ou sem querer, já assume que vai ter gente usando MAP como DTO genérico.

saoj

Só para colocar um pouco mais lenha nessa fogueira, pelo menos no meu caso, a causa que determinou a necessidade de usar DTOs foi:

:arrow: Lazy-loading do Hibernate que faz com que o banco todo seja carregado na view (exagerando claro), dependências cíclicas gerando loop infinito que de alguma maneira surgiu no modelo por culpa do hibernate e do maluco que fez a relação ManyToMany (eu diria por culpa dos dois). O fato inevitável de que para renderizar em JSON o JSON-LIB usa reflection procurando por getters, quando não é map.

Conclusão: como o Diogo falou fuja de DTO sempre que possível. E eu deixo mais uma dica. Se beber muito da mágica do Hibernate não dirija. Ou use iBatis ou JDBC + um query builder/helper.

diogopontual

Caramba, tivemos esse problema aqui na empresa. JPA é muito maneiro, mas a equipe tem que entender direitinho o Lazy Load, e como fazer os relacionamentos. Havia um many-to-many, com as coleções nas duas pontas, e tentava-se serializar uma delas para mandar para um cliente Flex, e tomávamos um StackOverflow na testa… Linda oortunidade para se usar (direito) DTO.

Por uma série de motivos, e por causa dos riscos envolvidos, eu preferi, em um novo projeto, abandonar JPA e utilizar as facilidades que o Spring oferece para a camada de dados, usando JDBC mesmo. Pelo menos está me parecendo mais elegante!!!

saoj

Exatamente o mesmo problema que encontrei no projeto aqui.

Exatamente o que faço. Sempre que possível irei abandonar o Hibernate e usar iBatis ou JDBC com query helper. Fica mais limpo, fica mais previsível, fica mais gerenciável, fica mais flexível. Mas ir contra o dogma do Hibernate é uma heresia, vc deve saber disso.

Engraçado como pensamos parecido. Seria legal se trabalhássemos juntos em algum projeto. Entre em contato comigo por email para mantermos o contato. sergio ponto oliveira ponto jr at gmail ponto com.

Rubem_Azenha

É uma heresia ir contra o dogma “aprenda a usar corretamente a ferramenta antes de fazer uso da mesma, mesmo que para isso tenha que ler um manual de 200 páginas”.

maniacs

Certo, vamos ver se entendi o que foi discutido, usar DTO para formatar os dados para determinada resposta é errado, o que realmente me parece errado, independente da reposta o DTO deveria ser igual.
Usar o MESMO DTO para passar dados entre camadas (Negócio/View) seria o correto ? Claro que eu poderia fazer isso usando MAP, mas em meu ponto de vista ficar usando reflection para isso não parece certo, prefiro usar o DTO para isso.
No caso o DTO seria apenas para isso, mostrar / limitar / padronizar os dados enviados da camada de negócio para a view, que formataria a reposta.

Correto?

Andre_Fonseca

maniacs:
Certo, vamos ver se entendi o que foi discutido, usar DTO para formatar os dados para determinada resposta é errado, o que realmente me parece errado, independente da reposta o DTO deveria ser igual.
Usar o MESMO DTO para passar dados entre camadas (Negócio/View) seria o correto ? Claro que eu poderia fazer isso usando MAP, mas em meu ponto de vista ficar usando reflection para isso não parece certo, prefiro usar o DTO para isso.
No caso o DTO seria apenas para isso, mostrar / limitar / padronizar os dados enviados da camada de negócio para a view, que formataria a reposta.

Correto?

oi,

bom, deixa eu dar a minha opinião

  • se no java tivessemos algo como um struct do C usariamos ele ao invés desses DTO’s ou VO’s ou o que seja… (seria o tal template engine?)
  • é errado pegar um objeto de negócio e colocar um monte de gets e sets nele só para facilitar o “agrupamento” desses dados que serão lidos pelo cliente
  • não gosto de maps por temos que ficar trabalhando com strings como disseram…
  • concordo com a sua ultima afirmação
  • supondo que eu tenha que passar para a minha view informações da Empresa e dos Funcionarios, eu criaria um objeto ViewEmpresaFuncionarios e jogaria nele os
    atributos que eu preciso e passaria para a view, não mexeria na camada de negócio
  • dá uma lida no que o Sergio Taborda falou sobre saco de propriedades
T

Posso desenterrar o tópico?

Bom, entrei em um projeto onde é usado DTO apenas nos relatórios e nos webservices. E a idéia já é ir migrar o projeto para SOA e usando Rest ao invés de soap.

E a primeira coisa que pensamos foi criar um dto pra todas as entidades, bem como seus “converters”, principalmente para separar, onde o serviço recebe somente dto e devolve somente dto, outro motivo que me apresentaram também foi a questão de tráfego, onde o principal consumidor é mobile.

Só que eu encontro esse tópico apresentando vários contras este pattern, eu vi que o DTO pode não ser o melhor cara para isso, aí eu deixo aqui a pergunta, se realmente ainda são contra o uso de DTO, e melhor ainda, se tiverem sugestões de outro pattern para essa questão. :slight_smile:

Alexandre_Saudate

TJvargas:
Posso desenterrar o tópico?

Bom, entrei em um projeto onde é usado DTO apenas nos relatórios e nos webservices. E a idéia já é ir migrar o projeto para SOA e usando Rest ao invés de soap.

E a primeira coisa que pensamos foi criar um dto pra todas as entidades, bem como seus “converters”, principalmente para separar, onde o serviço recebe somente dto e devolve somente dto, outro motivo que me apresentaram também foi a questão de tráfego, onde o principal consumidor é mobile.

Só que eu encontro esse tópico apresentando vários contras este pattern, eu vi que o DTO pode não ser o melhor cara para isso, aí eu deixo aqui a pergunta, se realmente ainda são contra o uso de DTO, e melhor ainda, se tiverem sugestões de outro pattern para essa questão. :)

REST tem diversas técnicas que incentivam a performance, como cache nativo do protocolo HTTP e gerenciamento de concorrência.

Em compensação, eu acredito que, enquanto o uso de JAX-RS 2 não foi mais difundido, você deve usar DTO’s nos seus serviços REST justamente por causa do HATEOAS (para quem não conhece, é a prática de colocar links para outras ações e entidades relacionadas à corrente).

[]'s

T

Alexandre Saudate:

REST tem diversas técnicas que incentivam a performance, como cache nativo do protocolo HTTP e gerenciamento de concorrência.

Em compensação, eu acredito que, enquanto o uso de JAX-RS 2 não foi mais difundido, você deve usar DTO’s nos seus serviços REST justamente por causa do HATEOAS (para quem não conhece, é a prática de colocar links para outras ações e entidades relacionadas à corrente).

[]'s

Legal, eu conheci o HATEOAS pelo seu livro de SOA, aliás parabéns pela obra;

E falando de SOA, já queria aproveitar para te perguntar Alexandre, se vc considera uma boa solução (à caminho do SOA) tranformar todos os serviços do Sistema(EJB) em EJB REST, inclusive os que o JSF consome, onde até os ManagedBeans passariam a consumir os serviços via REST também;

Alexandre_Saudate

TJvargas:
Alexandre Saudate:

REST tem diversas técnicas que incentivam a performance, como cache nativo do protocolo HTTP e gerenciamento de concorrência.

Em compensação, eu acredito que, enquanto o uso de JAX-RS 2 não foi mais difundido, você deve usar DTO’s nos seus serviços REST justamente por causa do HATEOAS (para quem não conhece, é a prática de colocar links para outras ações e entidades relacionadas à corrente).

[]'s

Legal, eu conheci o HATEOAS pelo seu livro de SOA, aliás parabéns pela obra;

E falando de SOA, já queria aproveitar para te perguntar Alexandre, se vc considera uma boa solução (à caminho do SOA) tranformar todos os serviços do Sistema(EJB) em EJB REST, inclusive os que o JSF consome, onde até os ManagedBeans passariam a consumir os serviços via REST também;

Na verdade, não. A grande vantagem de EJB em cima de um web service é que ele oferece um protocolo mais rápido, e encarar mudanças utilizando EJB é mais fácil do que essas mesmas mudanças em REST. Além do que, poderia trazer um grande risco de utilização inadequada, já que JAX-RS tem uma maneira de uso própria, que é diferente dos EJB’s.

O que poderia ser feito seria analisar quais desses EJB’s vale a pena expôr para outras linguagens e aí, sim, expô-los. Mas o sistema em JSF continuaria falando com a “faceta EJB”, digamos.

[]'s

T

Certo… obrigado pelas respostas Alexandre.

E vc comentou no livro que está escrevendo a continuação do mesmo.

Estamos aguardando!! :smiley:

Alexandre_Saudate

TJvargas:
Certo… obrigado pelas respostas Alexandre.

E vc comentou no livro que está escrevendo a continuação do mesmo.

Estamos aguardando!! :D

Ih, ainda estou escrevendo um sobre REST. Vou começar com essa continuação depois que acabar o de REST. =)

[]'s

Criado 12 de agosto de 2010
Ultima resposta 23 de mai. de 2013
Respostas 55
Participantes 17