Como vcs passam multiplos parametros de pesquisa entre camadas?

Tenho algumas telas de pesquisa com uma quantidade razoavel de parametros (10-20).

Qual a melhor forma de passar esses parâmetros entre a camada de apresentação e a camada de negócios?

Pensei em 3 formas:

1) Passar todos um a um, na assinatura do método.

Ex: public pesquisaAlgumaCoisa(int arg1, String arg2, double arg3…) {…} - Vantagem: type-safe

  • Desvantagem: como são muitos parametros, a visualizacão do metodo fica complicada; necessario alterar a assinatura qdo os parametros forem alterados;

2) Passar todos os parâmetros dentro de um Map<Object,Object>

Ex: public pesquisaAlgumaCoisa(Map<Object,Object> mapParametros) {…}

  • Vantagem: a assinatura do metodo fica simples e não sera necessario alterar a assinatura do metodo quando for adicionar novos parametros
  • Desvantagem: não eh type-safe

3) Criar uma classe “DTO” para setar os parâmetros e passar uma instância dessa classe como argumento.

Ex: public pesquisaAlgumaCoisa(DtoConsulta dtoParametrosConsulta) {…}

  • Vantagem: a assinatura do metodo fica simples e não sera necessario alterar a assinatura do metodo quando for adicionar novos parametros; type-safe;
  • Desvantagem: Tendencia a ter varios DTOs

Enfim,

nao cheguei ainda a uma conclusao qual a melhor forma, por isso gostaria de saber como vcs fazem.

Valeu

Eu particularmente utilizo a segunda opção, não só pra campos de pesquisa mas pra passagem de parâmetros em geral entre as camadas de apresentação e aplicação. E uso um Map<String, String> ao invés de Map<Object, Object>. Não realizo nenhuma conversão na view.

Qual o problema de passar a propria classe como parametro?

Se os parâmetros não forem consistentes com as regras de negócio, não será possível instanciar a classe com os parâmetros informados. A não ser, claro, que suas entidades sejam simples DTOs, que armazenem apenas os dados.

Um exemplo: supondo que estejamos consultando o CPF de uma pessoa, cuja classe está listada abaixo. Se o usuário estiver consultando por um CPF inválido, não será possível instanciá-la para realizar a consulta.

[code]public class Pessoa {
private String cpf;

public Pessoa(String cpf) {
    if (!cpfValido(cpf)) {
        throw new IllegalArgumentException("CPF inválido: " + cpf);
    }

    this.cpf = cpf;
}

}[/code]

Pq avançar nas camadas com algo supostamente errado(cpf)? Neste exemplo o método que chamou a validação deveria fazer o devido tratamento e avisar ao usuário.

Se a classe não possui os atributos necessários para a “pesquisa” tem algo muito errado na modelagem do sistema.

Reli o post e vi que entendi errado a pergunta do marcosurata. Ele perguntou qual a melhor forma de passar argumentos entre as camadas de apresentação e negócio, mas eu tinha lido entre as camadas de apresentação e aplicação.

Continuando com o exemplo, você tem razão: não faz sentido conduzir o cpf errado até a camada de negócios. Se instanciamos a classe Pessoa na apresentação com o cpf inválido, a exceção será tratada ali mesmo e a mensagem será mostrada ao usuário.

Acredito que cada caso é um caso, mas EU não gosto da idéia de passar um Map, acho que fica difícil de se achar no código fonte, principalmente se o sistema inteiro estiver desta forma…

Agora se for um simples filtro acho que faz mais sentido passar a própria Entidade…

Se for uma regra muito complexa que envolve muitos parâmetros de lugares diferentes, eu prefiro a idéia de criar um DTO com os parâmetros

Acredito que há muito preconceito com uso de DTOs, VOs, TOs ou o nome que preferirem.

Depois de muito apanhar disso, sou da seguinte opinião: Não duplique a sua entidade, agora se precisar de algo muito diferente da Entidade, prefiro criar um DTO.

[quote=ignacio83]Acredito que cada caso é um caso, mas EU não gosto da idéia de passar um Map, acho que fica difícil de se achar no código fonte, principalmente se o sistema inteiro estiver desta forma…

Agora se for um simples filtro acho que faz mais sentido passar a própria Entidade…

Se for uma regra muito complexa que envolve muitos parâmetros de lugares diferentes, eu prefiro a idéia de criar um DTO com os parâmetros

Acredito que há muito preconceito com uso de DTOs, VOs, TOs ou o nome que preferirem.

Depois de muito apanhar disso, sou da seguinte opinião: Não duplique a sua entidade, agora se precisar de algo muito diferente da Entidade, prefiro criar um DTO.[/quote]
De fato, não faz sentido mesmo usar um Map para passar dados entre apresentação e negócios. Mas quando eu estou desenvolvendo uma aplicação que tem uma camada de aplicação - que fica entre apresentação e negócios, nem sempre é necessário utilizá-la - eu prefiro usar um Map para passar os parâmetros entre apresentação e aplicação.

Quanto aos DTOs, não é que exista preconceito: já foi amplamente discutido aqui no fórum que, se você não tem transferência de dados entre camadas físicas - e não lógicas - não há motivo para utilizá-lo, pois originalmente o padrão não foi feito para transferir dados entre camadas lógicas.

Digo que é preconceito porque se eu escrevesse assim:

“Se for uma regra muito complexa que envolve muitos parâmetros de lugares diferentes, eu prefiro a idéia de criar um POJO com os parâmetros sendo acessados via getters e setters.”

Acredito que poucas ou nenhuma pessoa iria questionar…

[quote=ignacio83][quote]
Quanto aos DTOs, não é que exista preconceito: já foi amplamente discutido aqui no fórum que, se você não tem transferência de dados entre camadas físicas - e não lógicas - não há motivo para utilizá-lo, pois originalmente o padrão não foi feito para transferir dados entre camadas lógicas.
[/quote]

Digo que é preconceito porque se eu escrevesse assim:

“Se for uma regra muito complexa que envolve muitos parâmetros de lugares diferentes, eu prefiro a idéia de criar um POJO com os parâmetros sendo acessados via getters e setters.”

Acredito que poucas ou nenhuma pessoa iria questionar…[/quote]

DTO não é um POJO, pois não possui métodos, apenas atributos.

[quote=aleck][quote=ignacio83][quote]
Quanto aos DTOs, não é que exista preconceito: já foi amplamente discutido aqui no fórum que, se você não tem transferência de dados entre camadas físicas - e não lógicas - não há motivo para utilizá-lo, pois originalmente o padrão não foi feito para transferir dados entre camadas lógicas.
[/quote]

Digo que é preconceito porque se eu escrevesse assim:

“Se for uma regra muito complexa que envolve muitos parâmetros de lugares diferentes, eu prefiro a idéia de criar um POJO com os parâmetros sendo acessados via getters e setters.”

Acredito que poucas ou nenhuma pessoa iria questionar…[/quote]

DTO não é um POJO, pois não possui métodos, apenas atributos.

[/quote]

Assim como um POJO pode possuir métodos ou não…
Não obrigatoriamente ele deve seguir o padrão JavaBeans…
Vejo o DTO como um container de dados que podem possuir ou nao metodos getters e setters

Esta thread perdeu um pouco do foco.

Mas acredito que vou acabar seguindo a linha da opção 3, i.e., criar DTOs para armazenar os parametros de pesquisa para os casos em que forem muitos parâmetros.

Um outro problema de se usar o Map eh pq na hora de fazer refactorings nas estruturas dos dados, como normalmente a chave vai ser uma String, vai ser mais dificil detectar o impacto das mudanças.

Valeu

Só para constar:

http://fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs

[quote=aleck]Só para constar:

http://fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs[/quote]

Certo,

mas o contexto do VO aqui eh completamente diferente. Não estou discutindo o uso do VO/DTO para a modelagem da camada de dominio, mas sim a melhor forma de passar multiplos parametros de entrada de pesquisa da camada de apresentacao para a proxima camada (aplicacao ou negocio, dependendo da arquitetura do sistema).

No caso do amigo o DTO daria conta do recado, soh que o DTO eh bem aplicado quando pensamos em integracao de sistemas. Se fosse eu daria uma nova validada na sua arquitetura, vc vai querer mesmo ter um monte de DTO inuteis na sua aplicacao?

Iriam ser objetos tao especificicos a essa situacao(problema) que vc nao conseguiria reaproveita-los em nenhum momento, sem contar que colocando eles na assinatura da regras de negocio voce poderia estar inutilizando(acabando com o reaproveitamento) alguns metodos da camada de negocio.

Se for possivel voce desenvolver objetos que possam agregar a sua aplicacao contendo logica de negocio, ou mesmo sem logica que soh o nome ja faca sentindo que nao seja aquela coisa presa e amarrada, derrepente de todos esses parametros vc possa fazer tres objetos, mas tres que agregam a aplicacao.

Geralmente quando temos muitos atributos em uma chamada ou o existe um problema no design da sua aplicação ou você pode usar Parameter Object catalogado por Fowler.

E só pra lembrar pela 87978979 vez que DTO só faz sentido para diminuir trafego de rede e para os casos que aqui foram apresentados não se aplica.

[]s

Vi a descrição desse padrão no livro do Fowler e, na minha opinião, é soh mais um nome bonito para um Value Object.

Como já dito, quando temos faixas de valores (Data, preço, etc). Inclusive isso é dito no livro do Fowler, quando ele fala de Parameter Object. Passei por uma situação dessa há dois meses, com uma view que envia 2 faixas de datas para a Facade e estas datas estão quebradas em dia, mes e ano. Estou usando DWR.

Além das faixas de data, a view ainda manda outros parâmetros de busca.

[quote=Emerson Macedo]Geralmente quando temos muitos atributos em uma chamada ou o existe um problema no design da sua aplicação ou você pode usar Parameter Object catalogado por Fowler.

E só pra lembrar pela 87978979 vez que DTO só faz sentido para diminuir trafego de rede e para os casos que aqui foram apresentados não se aplica.

[]s[/quote]

Também para mim, é a solução perfeita.

[quote=marcosurata]Vi a descrição desse padrão no livro do Fowler e, na minha opinião, é soh mais um nome bonito para um Value Object.
[/quote]

Cara, não vejo por esse lado. Creio que o conceito de VO está vinculado ao conceito de BO, como entendi na Sun e pela idéia de Anemic Domain Model.

Acredito que o Parameter Object se pareça com o VO, mas divergem no conceito.

Na minha opnião, o problema do VO está quando você quebra o princípio primordial da OO que é manter estado e comportamento no mesmo artefato de software. Dessa forma, você estará programando como em qualquer linguagem que tenha o conceito de Record (Estado) e que permita agrupar as funções em um artefato separado - um prg, uma Unit, etc (Comportamento).

Matando “Artefato = Estado + Comportamento” você mata o encapsulamento de 2º nível, transformando a sua vida em um inferno.

Se não for usado nesse sentido, não vejo problemas em ter um objeto somente com valores.

Enfim, é o meu ponto de vista.

Abraços.

Olá!

Algo parecido com um Criteria (até tentei colocar um link mas o site do Hibernate está fora) seria mais uma opção, apesar que não sei se é uma boa idéia colocar um objeto de persistência na camada de apresentação/domínio. É claro que não precisa ser necessáriamente o Criteria do Hibernate, mas algum outro objeto que tenha o mesmo conceito, sendo apenas um objeto utilitário (infraestrutura) para ajudar nos critérios de busca. A vantagem de utilizar essa abordagem é que ela fica genérica para qualquer tipo de pesquisa e a desvantagem é que ela vai no final das contas ser um map um pouco mais enfeitado.

De todas as opções acho a de passar a entidade de negócio como parâmetro mais razoável e mais OO. Se por acaso precisar passar mais atributos, acredito que seja melhor rever o design e criar consultas mais específicas.

Abraços

[quote=Link_pg]Olá!

Algo parecido com um Criteria (até tentei colocar um link mas o site do Hibernate está fora) seria mais uma opção, apesar que não sei se é uma boa idéia colocar um objeto de persistência na camada de apresentação/domínio. É claro que não precisa ser necessáriamente o Criteria do Hibernate, mas algum outro objeto que tenha o mesmo conceito, sendo apenas um objeto utilitário (infraestrutura) para ajudar nos critérios de busca. A vantagem de utilizar essa abordagem é que ela fica genérica para qualquer tipo de pesquisa e a desvantagem é que ela vai no final das contas ser um map um pouco mais enfeitado.

De todas as opções acho a de passar a entidade de negócio como parâmetro mais razoável e mais OO. Se por acaso precisar passar mais atributos, acredito que seja melhor rever o design e criar consultas mais específicas.

Abraços[/quote]

Dessa forma você prende a sua aplicação a usar sempre hibernate.
E se quisermos mudar toda a camada de persistência de dados sem precisar mudar as GUIs implementadas? Teria que refatorar muita coisa, imagine se tivermos uma apresentação SWING e uma WEB?