Domain na Camada de Apresentação (Preciosismo?)

[quote=Paulo Silveira][quote=sergiotaborda][quote=emerleite]

Isso é o que eles querem que vc acredite.
O ponto em questão é levar os dados (do dominio) até à camada de apresentação. Isso é inerentemente um problema de transporte. Logo é a própria definição de um objeto de transfrencia de dados, de transporte (TO)

Um caso particular do uso disse é quando fazemos chamadas remotas, mas isso é apenas um caso particular de um padrão mais genérico.
[/quote]

Particular? A Sun, O Fowler e todos os lugares que voce encontrar a descricao, voce vai ver que fala que é para evitar o acumulo de chamadas remotas de granularidade fina:
http://java.sun.com/blueprints/patterns/TransferObject.html
http://www.martinfowler.com/eaaCatalog/dataTransferObject.html
[/quote]

Pois, e vc acredita. Como eu disse " Isso é o que eles querem que vc acredite. "
Pense dois minutos. Qualquer objeto composto que vc passa num argumento de um método é um TO. Afinal todo o objetivo de fazer isso é inerente à propria OO : encapsular vários dados num só.
O detalhes que a chamada do método é remota é só um detalhe. O objetivo do padrão TO é alterar a granularidade. E isso pode ser feito pelas mais variadas razões. Serialização é apenas uma delas: a mais conhecida.

O pessoa do EJB começou a usar TO porque eles definiam chamadas assim :

metodo ( String a, String b, int c);

E rápidamente entenderam que seria melhor assim

class X {
String a; String b; int c;
}

class Bean {
metodo (X x );
}

O fato de X ser Serializable era uma obrigação do modelo do EJB que era remoto por default. O padrão TO não precisava disso. Era o EJB quem precisava. Afinal o EJB corre junto do Web container , porque chamadas remotas ? Porque o EJB não definia chamadas locais.
Quando começou a fazê-lo na nova versão do EJB com o LocalInterface o uso de TO não parou. Porquê?
Se o TO fosse para poupar invocações remotas, ele não seria mais necessário, já que elas não existiam mais.

Mas o objetivo do TO nunca foi esse. Sempre foi diminuir a granularidade. Por isso que mesmo com o advento do LocalInterface o TO continuou sendo usado.

[quote]
Em que caso usariamos esse padrao mais generico, e onde ha a descricao? nao consigo ver a utilidade de usar DTo/TO sem ser para transferir dados entre TIERS (e nao layers).[/quote]

Pense mais dois minutos: Num sistema web com EJB quantos tiers vc normalmente tem ? UM! (os casos em que vc tem mais que um são raros)
E então porque vc usava objetos remotos ? Porque o EJB obrigava (nas primeira versões)
Quando o LocalInterface chegou porque vc não parou de usar TO ? Afinal continuavamos tendo apenas UM tier e agora sem invocação remota: a razão de usar TO para diminuir invocações remotas não existia mais.
Então porque se continuou usando TO ? Porque continuou importante a necessidade de usar objeto coarse-grain.

Entendam que essa era a falha fatal do EJB pré-3 : todos os objetos eram serializáveis e invocados remotamente mesmo quando só existia um TIER. Aliás, mesmo quando só existia uma JVM.
Mesmo com o advento das interfaces locais que eximiam o EJB de fazer chamadas remotas as pessoas continuaram usando TO. Então estavam usando TO para passar objetos apenas entre camadas , já que a JVM era a mesma. O Tier era o mesmo !

Não precisa de literatura para entender este fato historico se vc alguma vez trabalhou com EJB e TO.
SEMPRE só houve um tier! Isos é ainda mais evidente com o uso de LocalInterface. Não me venham com essa conversa que objetos passados entre camadas não são TO que isso é completamente absurdo. O objetivo do padrão é alterar a granularidade. Apenas isso.

Hoje o Seams faz sucesso por implementar o obvio. Aquilo que o EJB deveria ter sido do inicio. Mas o EJB nasceu do Corba que é remoto por natureza. Esse foi o erro. Isso foi o que fez nascer coisas como o DDD e o Spring e o proprio EJB 3.

A única ocasião onde faz sentido falar em mais do que um tier era quando a interface não era web ( swing por exemplo) onde vc realmente tinha vários tiers. Ou quando vc comunicava com algum legado via CORBA.
Mas isso sempre foi raro. Rápidamente se percebeu que usar Web era muito mais vatajoso exactamente porque tudo estava no mesmo tier. A tecnologia não evoluio para o EJB 3 com interfaces locais porque a maioria dos sistema tem clientes remotos ou acessa legados remotos.

[quote=emerleite]

hummm… é possivel também que eu tenha citado essas mesmas fontes entre outras e tirado minhas própria conclusões. Essas eram as conclusões em que me baseie para responder e por isso citei o meu blog. Afinal um padrão que serve para “poupar invocações remotas” parece no minimo tosco. Tem que haver uma razão mais primitiva para que algo seja considerado um padrão. Mas como já tive que me explicar no outro posto , peço que o leia.

Eu sei isso. Veja no meu blog o artigo sobre arquitetura se estiver interessado.

// sem métodos danosos


class Pessoa {
    private String name;
    private Date birthday;
 
     // get/set
 
    public int idade ( Date day ){
   // calcula idade baseado em birthday e day
 // este não é um método danoso
   } 
  
}

class Pedido {

     public void addItem(Item item){
          // adiciona o item ao pedido
             // este não é um metodo danoso
     }
}

class DAO{

   updateObject o);
}

// com métodos danosos e interfaces “mascara”


interface ActiveRecord {

     public save();
}

class AbstractActiveRecord {
@Inject DAO dao;

     public void save(){
        dao.update(this);
     }

}
interface Pessoa {
    // get/set
    int idade(Date day);
}

class PessoaImpl extends AbstractActiveRecord implements Pessoa {
    private String name;
    private Date birthday;
 
     // get/set
 
    public int idade ( Date day ){
   // calcula idade baseado em birthday e day
 // este não é um método danoso
   } 
  
}

interface Pedido{
   //getset
   addItem(Item item);
}
class PedidoImpl extends AbstractActiveRecord implements Pedido{

     public void addItem(Item item){
          // adiciona o item ao pedido
             // este não é um metodo danoso
     }
}

class DAO{

   updateObject o);
}

Estou usando o ActiveRecord porque é um exemplo claro de métodos que altera o estado do sistema , mas poderia ser quaisquer outros métodos como por exemplo uma implementação assim:


class Pedido {

@Inject DAO dao;

     public void addItem(Item item){
          // adiciona o item ao pedido
             dao.update(item);
             dao.update(this);
     }
}

Vantagens do uso de entidades seguras:

  1. menos codigo é necessário
  2. Não ha necessiade de criar objetos especiais que traduzem entre o dominio e o resto
  3. garantia que o utilizador da classe não faz m!@#@#
    Desvantagem:
  4. Expõe os objetos de entidade ao mundo.

Vantagens do uso de entidades não seguras:

  1. Não expõe os objetos de entidade ao mundo.
  2. Não ha necessiade de criar objetos especiais que traduzem entre o dominio e o resto já que isso é feito declarando interfaces/classes diferentes.
    Desvantagem:
  3. Mais codigo é necessário
  4. Não ha garantia que o utilizador da classe não faz m!@#@# passando o objeto com interface/classe errada
    permitindo a invcação dos métodos não seguros.

O ponto é: É mais simples não ter métodos danosos do que mascará-los com interfaces.
(conhece a Navalha de Occam ? é por ai…)

Como vocês classificam os objetos fakes como aqueles necessários em relatórios ad-hoc, que são apenas uma customização de dados do domínio? (claro, dentro da mesma tier)

[quote=rob1980a]Tenho acompanhado as discussoes sobre “domains” e para levar um dominio ate a camada de apresentação. Voces acham que é interessante levar um objeto de dominio ate a camada de apresentacao, pq alguem pode chamar um metodo de negocio dele?

Num JSF voces mapeam o Managed Bean com os mesmos campos do domain?

Vlw![/quote]

O que é um objeto de domínio? Uma entidade, um VO, um service, um repositorio?

Não vejo problema na apresentação chamar metodos de negócio mas as entidades especificamente têm um ciclo de vida que interessa ao domínio e sua exposição pode levar a perder esse foco.

Como não pertencentes ao domínio.

Você quer dizer estado persistente ne?

Eu não acho que uma entidade seja considerada mais “rica” pela capacidade de se persistir. Mas entendi seu ponto!

editado: não é necessário TO, basta lancar uma excecao caso a entidade não esteja num contexto persistente.

Talvez tenha me expressado mal Moscoso, que ele não é domínio já esta implícito na sua condição de customização do domínio, não era a isso que me referia.

Se ele não é um VO (esse nome hoje tem uma referencia mais forte a sua definição em DDD), não é um TO/DTO (isso é, se você toma como convenção que essa padrão se aplica somente em invocações remotas)… então do que podemos chamar esses objetos que muitas vezes são necessários? Não me recordo do registro de algum padrão específico (se convencionarmos que DTO = remoteCall ) que dá nome para essa situação necessária em muitos casos.

Essa perguntinha é muito boa porque demonstra que TO tem muitas mais aplicações. :lol:
Infelizmente não sei se o pessoal vai apreciar toda a complexidade de responder a isso :cry:

Acho que o problema para que alguem responsa a isso é a forma como as pesquisas são normalmente feitas.

Acho que a maioria faz uma frase SQL directo no jasperreport via ireport e nem pensa em usar objetos.
Para aqueles que utilizam objetos usam os do próprio dominio (porque na realidade eles usam apenas objetos burros então não ha grande diferença )
Uma pequena minoria já utilizou objetos diferentes daqueles do resto do sistema. E só nesse caso saberiam responder à pergunta.

Mesmo tendo feito isso a minha primeira ideia foi responder “flyweight”, só depois me liguei que eram TO.
Muito boa pergunta, muito inteligente.

Boa pergunta Lezinho eu estou com essa dúvida tb…

[quote=Lezinho]Talvez tenha me expressado mal Moscoso, que ele não é domínio já esta implícito na sua condição de customização do domínio, não era a isso que me referia.

Se ele não é um VO (esse nome hoje tem uma referencia mais forte a sua definição em DDD), não é um TO/DTO (isso é, se você toma como convenção que essa padrão se aplica somente em invocações remotas)… então do que podemos chamar esses objetos que muitas vezes são necessários? Não me recordo do registro de algum padrão específico (se convencionarmos que DTO = remoteCall ) que dá nome para essa situação necessária em muitos casos.
[/quote]

Será que precisamos de um padrão pra isso?

Eu apenas uso o sufixo Helper ou Result.

[quote=cmoscoso]
Será que precisamos de um padrão pra isso?

Eu apenas uso o sufixo Helper ou Result.[/quote]

Essa sua pergunta tem tantas implicações que não me atrevo a descrevê-las todas. O essencial é:

  1. Prefixos e Sufixos não fazem padrões.
  2. Um objeto segue padrões mesmo quando vc não sabe que eles os segue ou não o desenhou pensando em algum padrão. Por vezes é institivo.

É como fazer 2+2=4 alheio ao fato disse ser possivel porque o conjunto dos inteiros é um grupo para a adição. Ignorar que é , não impede de usar.

E qual a vantagem de estar sob as rédeas de um padrão que impõe várias restrições sendo que não vou utiliza-lo no contexto para qual ele foi criado?

Design Patterns, em sua maioria, costumam ser remendos que a linguagem ou a tecnologia nao conseguem suprir… É assim mesmo…

Foi assim, por “instinto”, que concluiu isso? :stuck_out_tongue:

So pra deixar claro. Nao é pra criar Local DTO e copiar e colar todos seus atributos. E sim quando voce quer decorar, diminuir, expor algo de maneira diferente para o outro layer.

[quote=cmoscoso]
Foi assim, por “instinto”, que concluiu isso? :stuck_out_tongue: [/quote]

É, o Sergio entendeu voce ao contrario denovo ai.

Não precisamos usar padrão se assim preferirmos para nada Carlos. Contudo é uma forma para referirmos aos mesmos problemas e suas respectivas soluções.

O exemplo que citei é uma situação dessas. Como mencionado pelo Sérgio, você pode transferir uma SQL diretamente ou uma entidade de domínio, optar por um novo objeto customizado é uma solução diferente para a mesma motivação, que sabemos ser bem mais razoável do que os outros approachs.

Mais uma vez não tenho palavras para explicar como isso é um tremendo erro. Design Patterns são, sim, na sua maioria corolários do uso do Principio da Separação de Responsabilidade e/ou do Principio da Inversão do Controle. Não são rememdos. São mecanismos formais diretamente relacionados aos principios de OO.

Se colocar um numero de pessoas desenhando sistema OO durante um bom tempo, depois de algum tempo eles vão chegar na conclusão que estão criando sempre o mesmo tipo de objetos. O seguimento das regras de OO leva naturalmente a isso. Como essas implementações especiais , esses trade-off especiais se repetem , ele são catalogados. E isso é um pattern : um conjunto de aplicações de principios o OO que para um determinado problema sempre resultam na mesma solução. Então, sabendo o problema e a solução catalogada vc poupo o tempo e a pericia de utilizar os principios OO do zero. Afinal , não é todo o mundo que sabe fazer isso.

É mais ou menos como na fisica. Vc tem formulas. Mas elas são derivadas de principios primários. As formulas são apenas ajudas catalogadas para não derivar tudo do principio cada vez que é necessário.

Contudo, vc é livre de começar dos principios cada vez e chegar no objeto final. Muitas vezes isso é feito naturalmente - por instinto - se que vc se aperceba que aquilo é um padrão já catalogado. Aliás, para vc reconhecer isso vc tem que conhecer o padrão primeiro.

Me assusta que vc jogue no lixo todo um conjunto de teorias e principios que estão pode detrás de OO e reduza tudo a “remendos”…

ah, isso me lembra velhas discussões

:wink:

T+

Mais uma vez isso nada tem a ver com o padrão TO/DTO. O que você citou é um Refactoring Pattern chamado Introduce Parameter Object, que nada tem a ver com TO/DTO.
http://www.refactoring.com/catalog/introduceParameterObject.html

[quote=sergiotaborda]
O fato de X ser Serializable era uma obrigação do modelo do EJB que era remoto por default. O padrão TO não precisava disso. Era o EJB quem precisava. Afinal o EJB corre junto do Web container , porque chamadas remotas ? Porque o EJB não definia chamadas locais.
Quando começou a fazê-lo na nova versão do EJB com o LocalInterface o uso de TO não parou. Porquê?
Se o TO fosse para poupar invocações remotas, ele não seria mais necessário, já que elas não existiam mais.

Mas o objetivo do TO nunca foi esse. Sempre foi diminuir a granularidade. Por isso que mesmo com o advento do LocalInterface o TO continuou sendo usado. [/quote]
Tanto isso não é verdade que na prova de Certificação em EJB geralmente caia uma pergunta sobre o uso dos Transfer Objects e a única resposta correta era para diminuição de chamadas remotas. O fato do TO não ter morrido na documentação da Sun se da mais pelo fato da falta de atualização correta, tanto que tem algumas paginas deles que ainda chamam esses objetos de VOs.

Não está correto seus argumentos. Quando você diz que sempre houve um só TIER, você ignora o fato do EJB 1.x não ter interfaces locais e por isso a criação dos padrões Session Façade e Transfer Object.

[quote=sergiotaborda]
hummm… é possivel também que eu tenha citado essas mesmas fontes entre outras e tirado minhas própria conclusões. Essas eram as conclusões em que me baseie para responder e por isso citei o meu blog. Afinal um padrão que serve para “poupar invocações remotas” parece no minimo tosco. Tem que haver uma razão mais primitiva para que algo seja considerado um padrão. Mas como já tive que me explicar no outro posto , peço que o leia. [/quote]
Esse padrão para poupar invocações remotas surgiu de uma limitação dos Entity Beans e era a maneira recorrente de resolver o problema. Por isso um padrão.