DTO - dúvida conceitual

Essa teria graça se não fosse triste.
Padrões não são receitas de bolo, realmente. Não são “10 passos para a classe maravilhosa”. Isso é verdade.
Mas daí a menosprezar os padrões … peraí …
Padrões são coisas série. Ou vc segue ou não segue. Mesmo que vc se sinta inspirado, se vc não segue o padrão à risca,
o que vc obtem não é uma implementação do padrão. O detalhes é saber o que é o “padrão à risca” e isso sim é uma coisas metafisica. Mas isso apenas porque os livros de padrões são catálogos e não teses sobre axiomática.
Vc pode definir os padrões sob a forma de teoremas derivados “matemáticamente” da axiomática de OO. Mas isso seria um texto
chato que 95% das pessoas passaria longe. Com a ideia de que o padrão é uma receita (embora não seja realmente, sim) essas 95% das pessoas pelo menos vão aceitar a ideia.

O que é triste é ter que ler que prototype , mediator e façade são tipos semelhantes de padrões. Essa doeu.
Claro que quem defende que padrões são felxiveis, não são sérios e são meros “guias” dá-se ao luxo de dizer uma coisa dessas.
Para quem acha que padrões são colorários dos axiomas de OO isso equivale a dizer que a operação de soma, divisão e conjugação são tipos semelhantes de operação…

Existe necessidade de ser agressivo quando se posta no forum???
Juro que não entendi a agressividade gratuita. :shock:

De qualquer forma, seu argumento vai de encontro à definição de padrão. Se padrões são soluções recorrentes, identificado em situações diferentes… ninguém estava seguindo nada à risca. Nas palavras do fowler: [quote]“One of the interesting things here is that a singular solution can often lead to a recurrent pattern. This usually crops up when you see two different singular solutions which look completely different on the surface, yet have a deeper similarity”[/quote].

Padrões são sérios, e são coisas importantes. Mas é preciso entendê-los e não vê-los como receitas.
Um ótimo exemplo disso é o DTO. O padrão fala do problema de usar vários getters e setters entre sistemas distribuídos. Isso seria muito ruim… Ao invés disso, sugere-se enviar um objeto que encapsule todas essas informações. Ponto.

O padrão não dita que você não pode colocar código de validação, comportamento, etc nos DTOs.

Outro excelente exemplo é o padrão strategy. Sugiro que as pessoas leiam a descrição do padrão e comparem com a idéia de Interface do Java. Observe que no C/C++ e no Smalltalk não existe Interface… O que você acham? O conjunto List + implementações (ArrayList, LinkedList, etc) não implementa o padrão Strategy? Pattern é isso, uma solução recorrente (um conjunto de melhores práticas) para problemas recorrentes.

Aos participantes gostaria de indicar este livro:

REFATORAÇAO PARA PADROES
Autor: KERIEVSKY, JOSHUA
Editora: ARTMED
Assunto: INFORMATICA-PROGRAMAÇAO

O autor aconcelha a ler o livro com a presença de outro livro do Mr. Martin Fowler REFACTORING IMPROVING THE DESIGN OF EXISTING CODE pois ele faz várias referencias sobre este livro.

P.S. O livro é em ingles mas o traduzido está com a qualidade aceitavel, vale a pena dar uma olhada.

Ahhh…já ia esquecendo neste livro não fala de DTO rsrsrsrsr.

flw

rs…
engraçadinho…

Ahhh…já ia esquecendo neste livro não fala de python. hahahahah!

[quote=rodrigousp]Existe necessidade de ser agressivo quando se posta no forum???
Juro que não entendi a agressividade gratuita. :shock:
[/quote]

Juro que não entendi onde está a agressividade gratuita.

Nas minhas próprias palavras:
“Padrões são colorários dos axiomas de OO”

Eles não aparecem do nada como o Fowler expressa , eles está lá sempre.
Se vc seguir as regras OO ( os axiomas , como SoC, IoC , encapsulamento, etc…) vc tem um código enxuto . Mesmo que vc não saiba os nomes dos padrões que acabou de usar, eles estão lá.
Quando vc identifica uma solução isso não acontece porque vc está notou uma coincidencia, e sim porque vc está vendo as regras funcionarem. Elas funcionam sempre da mesma forma e por isso as “coincidencias” são recorrentes.

Pois não. Mas regras mais importantes ditam, como o SoC.
O que vc está dizendo é que se eu pegar um pojo da vida o fizer serializable e colocar um monte de codigo de validação, colocar o construtor privado , colocar get/set paras os atributos, colocar um método estático para retornar o objeto que eu crio dando clone de um atributo estático privado e final na classe eu estarei usando : Prototype (clone copy), Factory-Method (método de criação), TO (serializable) e Bean (get/set).
Não. Vc está fazendo apenas uma salada de frutinhas e pior, violando o SoC.
Em suma, se viola o SoC o seu codigo não pode ser considerado bom, muito menos um padrão.

Interfaces são constutos uteis ao padrão strategy, mas não são a “implementação do padrão strategy” isso é absurdo. Strategy pode ser feito com herança normal se não existissem interfaces.
ArrayLisr , etc… sim são estratégias de List que por sua vez é estratégia de Collection. Isso sim. Mas nunca “interface” per se será um padrão.

Como os texto que citou falam : padrão é algo que não existe na linguagem. É algo que vc faz com a linguagem.

Padrões não são conjuntos de melhores práticas, são o resultado direto do seguimento coerente dos principios de OO. Quando vc aplica os principios de OO a um problema vc obtem um resultado. Se aplicar de novo os mesmos princípios vc obtem o mesmo resultado. A aplicação dos principios é complexa, por isso vc pula essa fase. Dai quand vc tem um problema vc tem a solução. Mas ela não aparece magicamente.

Um exemplo, a lei de pitagoras para a relação entre os catetos e a hipotenusa de um triangulo retangulo pode ser usada diretamente sem ter que a deduzir a todo o momento. O mesmo que a as leis de newton.
Ou seja, se vc tem um problema vc aplica o que já sabe e obtem um resultado. Vc não perde tempo deduzindo a solução a partir de principios básicos cada vez que tem um problema. Da mesma forma vc não deduz a solução para um problema de OO a cada vez que precisa, vc faz isso as primeiras vezes e depois vc já sabe a solução e aplica. Vc cataloga as soluções para fácil uso e pronto.
As solução advem dos principios. Os padrões são atalhos. Dado um problema o padrão dá a solução. Mas o padrão contêm em si todo o processo de aplicação dos princípios da OO.

Padrão não são receitas de bolo, mas são mais que guias: são corolários. Ou seja, não é possivel, para o mesmo problema encontrar outra solução diferente. Se fosse guias ou receitas poderiam ser encontradas outras formas.

O que temos diferente são as implementações. Ai sim, existem muitas variantes. Mas o padrão não inclui a implementação, por isso a variedade de implementações não afeta em nada a realidade de que o padrão é univocamente definido pelo problema e pela aplicação dos axiomas de OO.

[/quote]

Esse assunto é muito jóia…

Eu enfatizo que o conceito do padrão é mais importante que a estrutura. Veja:

ok

A validação pode ficar nos setters, correto!? Se os getter e setters só atribuirem/devolverem os valores da propriedades seriam só idiossincrasia para acessar a propriedade internas do objeto.

Huh(vamos ver…)

ok

Ops…

ok! Se é interessante clonar seu objeto, não tem nada de errado com isso. Ainda não vi a motivação mas pode ser que faça sentido. Sei lá, vai ver que você esteja fazendo um joguindo de carros e o servidor disponibiliza novos modelos de carros. Cada cliente recebe os modelos de carro e permite que usuário faça modelos personalizados a partir desses. (Serializável e clonável). Nesse caso o modelo segue o Prototype.

Aí não. Eu falei que o conceito do padrão é importante, não a estrutura. Usar um método para criar outro não faz um “factory method”. Existe uma motivação para o Factory Method e não existe nenhuma motivação na saladinha.

Pode ser que sim… desde que a motivação coincida com o padrão. No exemplo do jogo do carrinho seria uma estupidez os clientes serem informados de propriedade por propriedade de cada modelo. É mais inteligente o servidor enviar todo o objeto. Esse é um exemplo do uso do DTO.

Isso também não. Para começar que um Javabeans é um componente de software, não um padrão. E existe uma especificação que dita quando uma classe Java pode ser chamada de Javabeans… De forma simplificada:

Ainda no exemplo dos carrinhos, o código não precisa ser um padrão. Mas, alguns padrões podem ser encontrados na resolução desse problema.

Concordo plenamente!!!

Sobre a parte de corolários, etc… acho que não podemos fazer tal afirmação. A demonstração rigorosa que um padrão deriva matematicamente de “axiomas de OO” não deve ser alguma coisa fácil, talvez nem seja possível… Seria realmente incrível provar que dado um contexto(limitações) e um problema (necessidades) não seria possível encontrar um modelo melhor do que o modelo de um certo padrão. Mas por enquanto isso é uma especulação (conjectura) não um teorema.

Vc passou longe do ponto. O ponto era :misturar um monte de pedaços de cada padrão não significa usar o padrão.
Tlv vc defenda que o conceito do padrão é mais importante que a implementação. Tudo bem. Mas não era isso que o blog que vc apontou como justificativa defendia. Ha uma enorme confusão de padrões lá. Era disso que estava falando.

Eu não falei em javabean eu falei em bean. Sim, JavaBean é um componente e uma especifiação, mas bean é algo mais simples.
Todos os javabeans são beans, mas o contrário não é verdade.

Dificil ? … hummm… não importa se é difícil, importa que é possível. O ponto é que padrão tlv sejam encontrados empiricamente, mas eles têm uma base teórica. Sem ela, não existe padrão. É no máxima uma boa prática e no pior caso uma gambiarra.
Mas nem é tão dificil assim:
O padrão Composite, por exemplo, nasce diretamente do conceito de composição que é uma forma de relacionar objetos.
O padrão Composite não é qualquer tipo de composição. É um tipo especial onde o composto é da mesma classe do componente. è isso que marca a diferença e o padrão. Não é difícil entender que composição é uma relação de objetos diretamente derivada do próprio conceito de objeto e portanto o Composite é um padrão derivado matematicamente de axiomas OO ( a existência de objetos é o primeiro axioma)

Desculpa ai (1)… Eu estava só provando o que eu havia falado antes: que o padrão DTO NÃO dita um Objeto anêmico.

Desculpa ai (2) … Na literatura que eu conhecia, beans e Javabeans eram sinônimos. E um Javabeansprecisava ter construtor sem parâmetros público. Então apesar dos getters e setters, não poderíamos chamar aquele exemplo de Javabeans.

Eu não diria que esta essa é a demonstração mais formal que conheço. Na minha opinião seria preciso tomar o padrão composite, como apresentado pelo Gof e sua “Estrutura”: Component, Composite and Leaf. Então, seria preciso demonstrar que aplicando os aximos do OO teríamos essas entidades e teríamos que tomar o cuidado para mostrar como cada uma dessas partes atuam não deixando dúvidas se Component pode ou não ter
métodos de manipulação de listas, se um autorelacionamento pode ou não desempenhar o papel de composição, etc.

Eu concordo plenamente que existe uma base teórica importante sobre os padrões de projeto.
Mas volto a enfatizar que o conceito é mais importante que a estrutura.

Não foi intenção ser formal. Embora “formal” seja relativo aqui.

Ora ai é que está. Porque como paresentado pelo GoF ? Eles são algum tipo de deuses ? E aliás as ideias deles são para C++
Se é verdade que a base toerica é mais importante que a implementação não importa que seja em C++, mas vai dai, também não importa que seja do GoF.

não. A implementação é irrelevante. métodos de manipulação de listas são irrelevantes. Podem ser adicionados se necessário Por exemplo, se a composição for imutável esses métodos não podem existir. Mas isso é detalhe de implementação.
Auto-relacionamento é um tpo de relacionamento e portanto auto-relacionamento pode ser composição e pode ser visto como um corolário do padrão. Esse tipo de coisas não entram no padrão.

O padrão é definido como a composição (operação entre objetos) recursiva. Ou seja, um objeto da classe X pode ser composto por objetos da classe X. É só isso. (Em uml um tipo - classe, interface - tem relação de composição consigo mesmo. )

Se o objeto composto é adicionado a si mesmo é uma auto-composição ( um ciclo fechado) Se o objeto não é composto por mais nenhum objeto então ele é diretamente um leaf. Ou seja, o leaf advém da propria regra e não é necessário presupor a sua existencia à partida.

Se o objeto leaf é especializado isso não é mais um problema do padrão Composite. Isso é a implementação de outro padrão: Strategy. Normalmente isso é legal ( Swign por exemplo) mas não é uma condição sin qua non para ter composite.

Ou seja, o ponto, é que não é tão complexo assim derivar as coisas, mas a principio isso não é feito no dia-a-dia, dai a necessidade de catálogos. Tlv os catálogos não enfatizem o suficiente a relação que os padrões têm com as regras de OO. Isso é uma pena, porque leva muita gente a achar que padrões são coisas apenas empíricas.

É que achando que são apenas empíricas sentem-se no direito das dobrar à sua situação, descaracterizando os principios de OO e portanto o padrão.

O exemplo classico: o cara cria um objeto com variável static private e um método para retorna essa instancia. Ai ele diz que isso é a implementação de singleton. Esse é o problema. Não é a implementação de singleton pela simples razão que não cumpre as regras do padrão em particular : um único objeto da classe deve existir a qualquer momento.
( se o construtor é publico, por exemplo, outros objetos podem ser criados.)

Ressucitando um tópico do passado …

Lendo algumas referências, inclusive muitas apresentadas aqui, consigo entender o que é o DTO e quando usar.

Agora a minha dúvida é bem pontual.

Suponha que eu tenha um método de acesso ao banco que me retorna um result set, eu preciso que este método retorne para o cliente - a camada que vai usá-lo, seja view ou business sei lá - uma lista formatada que seja de fácil iteração.

O que eu quero dizer com isso? Quando eu faço

[code]List list = new ArrayList();
while (rs.next()) {
Pessoa p = new Pessoa();
p.setNome(rs.getString(“nome”));
p.setIdade(rs.getInt(“idade”));

list.add§;
}[/code]

Fica fácil no meu cliente saber iterar na lista e fazer o que for preciso.

Mas isso seria ruim? Pois a classe Pessoa muito provavelmente só teria sentido em ter os seus atributos e os seus gets e sets.

Uma sugestão - primeira página do tópico - seria passar o que o programmer chamou de um array de structs tipados.

Eu já tinha visto esta alternativa antes, mas isso pode ser ruim pois eu toda classe que precisasse eu teria que ter uma estrutura dessas.

Uma outra alternativa seria você criar um hashmap e depois um iterator pra facilitar as coisas. Mas será que o esforço vale a pena?

Achei um link interessante que trata da mesma situação

http://consultingblogs.emc.com/jaddy/archive/2009/10/01/how-not-to-use-dtos-in-domain-driven-architectures.aspx

Na sessão Our solution ele diz

Seria essa uma boa idéia? Não seria um tiro de canhão para matar uma mosca?? :roll:

O que vocês costumam fazer? Ou usam o VO Pessoa mesmo??

a minha duvida tem a ver com a frase acima tb, no caso que eu coloquei não tenho uma aplicação distribuida …

Como que é sua aplicação?

É client x server?

flws

sim, entretanto as camadas que eu mencionei rodam no mesmo ambiente. eu posso até estar fazendo acesso a um banco de dados remoto, mas não há necessiade de trafegar estes objetos pela rede…

[quote=André Fonseca]Ressucitando um tópico do passado …

Lendo algumas referências, inclusive muitas apresentadas aqui, consigo entender o que é o DTO e quando usar.

Agora a minha dúvida é bem pontual.

Suponha que eu tenha um método de acesso ao banco que me retorna um result set, eu preciso que este método retorne para o cliente - a camada que vai usá-lo, seja view ou business sei lá - uma lista formatada que seja de fácil iteração.

O que eu quero dizer com isso? Quando eu faço

[code]List list = new ArrayList();
while (rs.next()) {
Pessoa p = new Pessoa();
p.setNome(rs.getString(“nome”));
p.setIdade(rs.getInt(“idade”));

list.add§;
}[/code]

Fica fácil no meu cliente saber iterar na lista e fazer o que for preciso.

Mas isso seria ruim? Pois a classe Pessoa muito provavelmente só teria sentido em ter os seus atributos e os seus gets e sets.

Uma sugestão - primeira página do tópico - seria passar o que o programmer chamou de um array de structs tipados.

Eu já tinha visto esta alternativa antes, mas isso pode ser ruim pois eu toda classe que precisasse eu teria que ter uma estrutura dessas.

Uma outra alternativa seria você criar um hashmap e depois um iterator pra facilitar as coisas. Mas será que o esforço vale a pena?

Achei um link interessante que trata da mesma situação

http://consultingblogs.emc.com/jaddy/archive/2009/10/01/how-not-to-use-dtos-in-domain-driven-architectures.aspx

Na sessão Our solution ele diz

Seria essa uma boa idéia? Não seria um tiro de canhão para matar uma mosca?? :roll:

O que vocês costumam fazer? Ou usam o VO Pessoa mesmo?? [/quote]

Se a sua aplicação é orientada ao dominio obrigatoriamente vc terá uma List<Entidade> e portanto vc é obrigado a criar objetos dessa entidade.
Contudo, vc não é obrigado a criar esses objetos à mão, nem a criá-los junto à leitura do resultSet.

Para não os criar à mão vc usa reflection. Todos os frameworks fazem isso. Conceptualmente isso não passa de uma forma de injeção. Vc injeta um monte de outros objetos na classe da entidade.
O fato deles serem dados da entidade é um detalhe.

Vc não precisa criar o list e populá-lo com a leitura do resultset; Vc pode usar o padrão Fastlane Reader. Este padrão poupa objetos na memoria e apenas traduz o rs para o objeto quando necessário.
Nestes casos o uso de List ou outro tipo de collection não é aconcelhável a menos que vc tenha codigo legado escrito dessa forma.

Você pode abstrair esse codigo até ter algo que funciona para qualquer classe. Basicamente vc estará fazendo o que o Hibernate faz. Mas para isso dar certo vc precisa de algum tipo de metadados.
Sem metadados o unico jeito e´fazer na mão. Reflection oferece muitos metadados, mas podem ñ ser suficientes. Por exemplo, não contém nome de tabelas e colunas…

Este tipo de trabalho não se caracteriza como o uso de DTO. O uso de DTO implica duas coisas : orientação a dados (data) e distribuição (transfer). Usar entidades descaractetiza o uso de dados e o fato de estarem na mesma jvm descaracteriza transfer ( todos os DTO são serializable, entidades não precisam ser).

Cuidado com a confusão entre DTO e VO. Tem muita coisa sobre isso no guj é questão de procurar, mas resumindo : VO não são DTO e DTO não são VO.

[quote=sergiotaborda]Este tipo de trabalho não se caracteriza como o uso de DTO. O uso de DTO implica duas coisas : orientação a dados (data) e distribuição (transfer). Usar entidades descaractetiza o uso de dados e o fato de estarem na mesma jvm descaracteriza transfer ( todos os DTO são serializable, entidades não precisam ser).

Cuidado com a confusão entre DTO e VO. Tem muita coisa sobre isso no guj é questão de procurar, mas resumindo : VO não são DTO e DTO não são VO. [/quote]

Sendo assim (client x server), também concordo com que o Sergio disse.

flws

Achei interessante (porque reflete a situação do Java) é que a opção mais simples que é do hashmap é considerado um “esforço”. :slight_smile:

Existe uma derivação do DTO chamada HashDTO que usa um map para a transferencia. O problema é que isso não é fortemente tipado e leva a um monte de outros problemas.

Existe uma derivação do DTO chamada HashDTO que usa um map para a transferencia. O problema é que isso não é fortemente tipado e leva a um monte de outros problemas. [/quote]

Ele é fortemente tipado, é um hashmap. :slight_smile:

Não é um tipo específico da sua aplicação, e nem vejo motivo para tal, visto que é apenas para trafegar objetos entre modulos distintos. Não ter que manter código de infraestrutura é uma vantagem IMO, principalmente numa linguagem que impõe tanta cerimônia na definição de tipos.

Existe uma derivação do DTO chamada HashDTO que usa um map para a transferencia. O problema é que isso não é fortemente tipado e leva a um monte de outros problemas. [/quote]

Ele é fortemente tipado, é um hashmap. :slight_smile:
[/quote]

imagine a classe pessoa com nome (String) e data de nascimento (Date). Faça um map tipado para isso. :twisted:

O melhor que vc vai conseguir é Map<String, Object>

“Object” significa “não sei qual é o tipo”.
Existem alternativa que envolvem utilizar metadados que têm que estar presentes dos dois lados.
Funciona, mas dá muito trabalho e como já disse tem problemas.

[quote]
Não é um tipo específico da sua aplicação, e nem vejo motivo para tal, visto que é apenas para trafegar objetos entre modulos distintos. Não ter que manter código de infraestrutura é uma vantagem IMO, principalmente numa linguagem que impõe tanta cerimônia na definição de tipos.[/quote]

Na ideia é boa, na prática não é util.

oi

não estou me referindo a este value object mas sim ao value object criado pela sun e que depois foi renomeado para DTO.

Vou procurar estudar um pouco sobre o que falou, principalmente sobre esse Fastlane Reader.

Sobre as outras sugestões a minha dúvida fica para quando eu não tenho os frameworks ou então o uso dos metadados fica dificil…

Na verdade nem sei se seria mesmo o VO, mas o que eu queria saber era uma forma de empacotar os dados de uma forma que fosse facil de iterar depois, algo semelhante a uma struct de dados do C… A minha dúvida é saber se é ruim usar esta classe pessoa com seus gets e sets só para agrupar o retorno do result set ou se tem uma forma melhor de fazer isso…

Tanto em termos de performance como também de manutenção, já que fica difícil quando precisarmos um dia de alterar esta classe ou bean ou sei la se o atributo nome mudar para primeiroNome e ultimoNome…

Neste caso concordo que usar reflection ou metadados vai facilitar bastante…

abs