DTO e Integração entre Sistemas

Pessoal,

Seria uma má prática a utilização de DTOs como retorno de WebServices para fazer integração entre 2 aplicações?

Gostaria de iniciar uma discussão sobre os prós e os contras desta prática, e qual a alternativa para isso.

Valeu
Luiz

Segundo essa definição aqui acho que nao. Esta coerente.

Não vejo problemas, ainda mais se forem imutáveis.
O que não pode acontecer é eles poluírem o sistema estando no centro dele. Como eles estão na periferia, acho que tá ok.

[quote=GutomCosta]Pessoal,

Seria uma má prática a utilização de DTOs como retorno de WebServices para fazer integração entre 2 aplicações?

Gostaria de iniciar uma discussão sobre os prós e os contras desta prática, e qual a alternativa para isso.
[/quote]

Se vc usa as funcionalidades de webservice automáticas do java vc já usa TO ( DTO). Os Webservices SOAP são apenas uma forma de serialização de arvores de DTO.

A interface dos TO é que forma o contrato do Webservice junto com os métodos do próprio serviço.
Aliás não tem outro jeito de fazer.

Obrigado pelas repostas pessoal. :smiley:

Outra coisa, como vocês fazem o montagem de um DTO?
Atualmente eu venho seguindo uma idéia do Martin Fowler no exemplo do capítulo de DTOs do livro PeeA, que é a utilização de um objeto Assembler que faz a tradução de um objeto de domínio para um DTO.
Só acho essa abordagem um pouco trabalhosa para objetos que tenham apenas uma parte de seus dados no DTO.
Exemplo:

public class Produto{
  private Long id;
  private String descricao;
  private String tipo;
  private Date dataCriacao;
  private Usuario usuarioQueCriou;
  private Collection<Sku> Skus;
 ...
}

Preciso de um DTO que contenha apenas alguns atributos desta classe:

public class ProdutoDTO{
  private Long id; 
  private String Descricao;
  ..
}

Para estes casos, não seria conveniente ter um método em minha classe de domínio que criaria um DTO? De acordo com o padrão
Information Expert , esta classe tem todas as informações necessárias para a criação deste objeto.
Exemplo:

public class Produto{
private Long id;
  private String descricao;
  private String tipo;
  private Date dataCriacao;
  private Usuario usuarioQueCriou;
  private Collection<Sku> Skus;
 ...

  public ProdutoDTO criarProdutoDTO(){
      ProdutoDTO produtoDTO = new ProdutoDTO(this.id, this.descricao);
      return produtoDTO;
     
  }

}

O que vocês acham deste tipo de abordagem? Estaria eu atribuindo uma responsabilidade “estranha” para meu objeto de domínio? :roll:

Valeu
Luiz

IMHO deveria existir um jeito de você poder “plugar” funcionalidades no objeto de domínio…

Eu acho uma boa forma por que se você fosse fazer essa conversão fora dessa classe, ela precisaria de muitos getters. Falo isso por que não gosto de getters e setters de todos os atributos fora de classes DTO.

Vc só precisa de um builder de TO. (Pelo amor de Deus não use o sufixo TO nas classes, coloque-as em outro pacote. vou usar aqui só para que se entenda).

Se o seu objeto original segue o padrão bean, com um pouquinho de reflection vc cria um builder que le os dados do objeto original. O nome deste padrão é Assembler.

[code]
Produto produto = … produto normal
ProdutoTO pto = assembler.assembleFrom(produto,ProdutoTO.class);

public class Assembler {

public T assembleFrom(Object original , Class type){

T to = type.newInstance();
 
// via reflection pega os getter de original e os setters de to. 
// por convenção ele têm os menos nomes então é só invocar o getter e passar o resultado ao setter

// para todos os pares get/set faça
setter.invoke(to, getter.invoke(original));

return to;

}
}[/code]

[quote=sergiotaborda][quote=GutomCosta]
O que vocês acham deste tipo de abordagem? Estaria eu atribuindo uma responsabilidade “estranha” para meu objeto de domínio?
[/quote]

Vc só precisa de um builder de TO. (Pelo amor de Deus não use o sufixo TO nas classes, coloque-as em outro pacote. vou usar aqui só para que se entenda).

[/quote]

Sergio,

Concordo com você com relação aos nomes dos objetos, utilizei mais para exemplo mesmo.

Gostei da sua idéia do objeto Assembler, eu tenho utilizado assembler aqui também, mas com BeanUtils (acho que é da apache). O problema é que as vezes existem objetos, como o que eu coloquei no exemplo, em que o DTO é apenas parte de seus atributos.
Não seria uma responsabilidade deste objeto criar o DTO?

Obrigado pelas respostas.

Valeu
Luiz

Se você se apoiar no padrao [url=http://en.wikipedia.org/wiki/Information_expert#informationexpert]Information Expert[/url] vai descobrir que não precisa dos assemblers, uma vez que seu objeto conhece toda a informação sobre ele mesmo. Neste caso não iria importar se vc quer transferir toda informação do objeto ou apenas parte dela. 

Mas seu objeto produto, por exemplo, é um objeto de dominio. E como objeto de dominio deveira possuir métodos que fossem relevantes ao dominio, por esta razão acredito que você deva continuar a utilizar os assemblers.
Os assemblers isolam a montagem do DTO, e mais importante garantem que este código de “infraestrutura”, não irá poluir seu objeto de dominio, que deve tratar das questões de dominio

Epero ter ajudado. :stuck_out_tongue:

Serginho

Um adendo: se você possui tantos DTOs (o que é comum em algumas APIs muito completas mas não é lá muito normal) pode ser interessante criar um Presentation Model.

Não. Embora o objeto existente tenha a informação ele não tem a responsabilidade. É a falta dessa característica que impede que seja o objeto existente a produzir o outro. (da mesma forma o TO tb não pode conter um método que se auto-lê do objeto existente. seria a mesma violação da mesma responsabilidade mas do ponto de vista do outro objeto).

Se vc forçar o Produto a gerar o TO vc estará acoplando um ao outro, além de acoplar a logica “que copia” um no outro.
Isto é inerentemente ruim.

Lembre-se que o principio fundamental de OO é a Separação da Responsabilidade. Não a “união da informação” ou “ponha a ação onde está a informação” :wink: normalmente é exatamente ao contrário.

[quote=sergiotaborda][quote=GutomCosta]
Gostei da sua idéia do objeto Assembler, eu tenho utilizado assembler aqui também, mas com BeanUtils (acho que é da apache). O problema é que as vezes existem objetos, como o que eu coloquei no exemplo, em que o DTO é apenas parte de seus atributos.
Não seria uma responsabilidade deste objeto criar o DTO?
[/quote]

Lembre-se que o principio fundamental de OO é a Separação da Responsabilidade. Não a “união da informação” ou “ponha a ação onde está a informação” :wink: normalmente é exatamente ao contrário.

[/quote]

Por acaso esse “ponha a ação onde está a informação” é o “dados e comportamento juntos”?

[quote=fabim][quote=sergiotaborda][quote=GutomCosta]
Gostei da sua idéia do objeto Assembler, eu tenho utilizado assembler aqui também, mas com BeanUtils (acho que é da apache). O problema é que as vezes existem objetos, como o que eu coloquei no exemplo, em que o DTO é apenas parte de seus atributos.
Não seria uma responsabilidade deste objeto criar o DTO?
[/quote]

Lembre-se que o principio fundamental de OO é a Separação da Responsabilidade. Não a “união da informação” ou “ponha a ação onde está a informação” :wink: normalmente é exatamente ao contrário.

[/quote]

Por acaso esse “ponha a ação onde está a informação” é o “dados e comportamento juntos”?[/quote]

Não.

DTOs preenchidos pela metade dão bastante dor-de-cabeça.
O melhor mesmo, na minha opinião, seria criar uma outra classe DTO para isso, ou seja, seguir essa abordagem mesmo que seja chata e trabalhosa.

[quote=Sergio Azevedo] Se você se apoiar no padrao Information Expert vai descobrir que não precisa dos assemblers, uma vez que seu objeto conhece toda a informação sobre ele mesmo. Neste caso não iria importar se vc quer transferir toda informação do objeto ou apenas parte dela.
Mas seu objeto produto, por exemplo, é um objeto de dominio. E como objeto de dominio deveira possuir métodos que fossem relevantes ao dominio, por esta razão acredito que você deva continuar a utilizar os assemblers.
Os assemblers isolam a montagem do DTO, e mais importante garantem que este código de “infraestrutura”, não irá poluir seu objeto de dominio, que deve tratar das questões de dominio

Epero ter ajudado. :stuck_out_tongue:

Serginho

[/quote]

Muito bom. Valeu Sérgio…

[quote=sergiotaborda][quote=GutomCosta]
Gostei da sua idéia do objeto Assembler, eu tenho utilizado assembler aqui também, mas com BeanUtils (acho que é da apache). O problema é que as vezes existem objetos, como o que eu coloquei no exemplo, em que o DTO é apenas parte de seus atributos.
Não seria uma responsabilidade deste objeto criar o DTO?
[/quote]

Não. Embora o objeto existente tenha a informação ele não tem a responsabilidade. É a falta dessa característica que impede que seja o objeto existente a produzir o outro. (da mesma forma o TO tb não pode conter um método que se auto-lê do objeto existente. seria a mesma violação da mesma responsabilidade mas do ponto de vista do outro objeto).

Se vc forçar o Produto a gerar o TO vc estará acoplando um ao outro, além de acoplar a logica “que copia” um no outro.
Isto é inerentemente ruim.

Lembre-se que o principio fundamental de OO é a Separação da Responsabilidade. Não a “união da informação” ou “ponha a ação onde está a informação” :wink: normalmente é exatamente ao contrário.

[/quote]

Eu concordo com você, obrigado pelas respostas.
Pensando melhor, não seria legal acoplar o objeto de domínio ao DTO. Como muitos disseram, apesar de ser possível a criação do DTO a partir do objeto de domínio, esta responsabilidade não é deste objeto.

Valeu.

DTOs preenchidos pela metade dão bastante dor-de-cabeça.
O melhor mesmo, na minha opinião, seria criar uma outra classe DTO para isso, ou seja, seguir essa abordagem mesmo que seja chata e trabalhosa.[/quote]

Victor,

Na verdade estes DTOs não são preenchidos pela metade. Eles são outros objetos que não tem todas as informações que o objeto de domínio tem.
A criação de outra classe aconteceria de qualquer forma, o que estava questionando (mas acho que já mudei de idéia), é a utilização de um Assembler ou não.

Valeu
Luiz

Phillip,

Os DTOs que existem são utilizados como retorno dos métodos de alguns Web Services.
Estava lendo sobre Presentation Model e não sei se entendi muito bem. Este não seria o papel de um objeto Controlador?
Atuamente meus Ws simplesmente delegam as chamadas para objetos de controle, e estes cuidam da lógica de execução do negócio e eventualmente utilizam os Assemblers para criação dos DTOs necessários.
Quando digo lógica de negócio, quero dizer a coordenação dos meus objetos de domínio, não a execução da lógica neste objeto de controle.
Estes objetos que tenho na minha aplicação como controladores, fariam o papel de um Presentation Model ou eu estou viajando?

Valeu
Luiz

Esqueci-me de comentar este pedaço.
O TO para o werbservice ProdutoWS tem os mesmos campos que o Produto, ou menos. Pode inclusive ter campos de tipos diferentes, já que o WS tem a sua propria logica e o seu próprio domínio. É comun converter enums em inteiros em vez de strings, collecções em arrays , coisas assim para ter maior compatibilidade com outras linguagens.
O ponto é que o assembler baseado em reflection vai-se basear no objeto do WS e ler do objeto original os campos que lhe interessam. Ou seja, mesmo o TO do WS não tendo todos os campos a reflection ainda funciona.