Passando dados da view para a camada de aplicação

Olá

Há algum tempo eu postei aqui uma pergunta de como seria uma maneira legal de se passar os dados da camada view para a camada de aplicação(service, manager ). Seguem os links da pergunta.

http://www.guj.com.br/posts/list/33027.java#177354
http://www.guj.com.br/posts/list/30/33027.java#179979

O projeto que eu trabalhava na época adotou a 3ª opção.

“Começar a criar o obj na action, a parte simples tipo setNome e etc, e passar esse quase obj para o factory method terminar o serviço.”

Problemas encontrados: Os managed beans (JSF) ficaram inchados e muitas vezes com alguma lógica de negócio. Isso aconteceu naturalmente um vez que o objeto é instanciado no próprio MB. Existem muitas injeções de dependência neles pois o domínio do projeto tem muitas relações, é quase impossível criar um objeto sem que ele seja relacionado com uma penca de outros.
Outro problema foi o tratamento dos updates, para não ter o problema de ler dois objetos com o mesmo ID na mesma sessão do hibernate.

Solução: Eu estava fazendo um projeto para testar o Spring2 JPA e etc e tive a seguinte idéia. Usar a opção 2:
"No caso de um app web (o meu caso) passar o form bean (Struts), ou managed bean(JSF)."
Mas com algumas diferenças, uma interface com as propriedades que eu preciso do Managed Bean (Ex. getNome, getTelefone…). O MB implementa essa interface. Meu service recebe como argumento um tipo dessa interface para salvar no repository.

Segue o código de exemplo:

Interface RawData

[code]/**

  • Interface que fornece os dados para serem gravados na entidade.

  • @author Fábio J. Mendes
    */
    public interface UsuarioRawData {

    String getNome();

    String getTelefone();

    String getEstadoCivilStr();

    String getRua();

    Integer getNumero();

    String getComplemento();

    String getCep();
    }[/code]

Service, o insert recebe um tipo RawData e o update recebe um id e o RawData:

[code]/**

  • @author Fábio J. Mendes

*/
public interface UsuarioService {

List<Usuario> findAll();

Usuario findById(Long id);

void insert(UsuarioRawData data);

void update(Long id, UsuarioRawData data);

void remove(Long idUsuario);

}[/code]

Action chamando o service e passando this como argumento:

[code]public class CadastroUsuarioAction extends ActionSupport implements UsuarioRawData {

//Propriedades…

@Override
public String execute() throws Exception {
	try {
		if(idUsuario == null) {
			log.debug("Salvando um novo usuário");
			usuarioService.insert(this);
		} else {
			log.debug("Salvando o usuario - id: " + idUsuario);
			usuarioService.update(idUsuario, this);
		}			
	} catch (RuntimeException e) {
		return ERROR;
	}		
	return SUCCESS;
}

//getters & setters e outros metodos…

}[/code]

O que vocês acham dessa solução?

Poxa sei lá me pareceu estranho CadastroUsuarioAction implementar UsuarioRawData. Pois ela é uma action ou é um UsuarioRawData? Me parece que esta faltando coesão ai!

Desculpe não li seus posts antigo não sei se esta lá mas, porque não criar uma classe usuário e deixar esse negocio UsuarioRawData de lado?

Se você ler os posts antigos vai ficar mais fácil de entender mesmo.
Existe uma classe usuário. A questão é que ela é instanciada/criada no negócio (UsuarioService) e a solução é uma forma de passar os dados da view para o negocio poder construir o objeto Usuario.

[quote=[JUZAM]]Se você ler os posts antigos vai ficar mais fácil de entender mesmo.
Existe uma classe usuário. A questão é que ela é instanciada/criada no negócio (UsuarioService) e a solução é uma forma de passar os dados da view para o negocio poder construir o objeto Usuario.[/quote]

Após eu ter postado acima eu fui lá dar uma olhadinha e vi que eu ja tinha lido aquele post!

Alguns pontos:

  1. Continuo achando que sua action ali de cima ta sem coesão;
  2. Por que a view não pode criar usuário? Não vejo nenhum problema nisso ainda mas se seu usuário for um POJO. Será que alguém vê?;
  3. Se você realmente não quiser a 2, você pode derrepente criar uma JavaBean ou um DTO para passar dados da view para a camada de negócio popular o usuário que será criado.(Muitas pessoas não gostam de usar DTO entre camadas lógicas, dizem que o melhor uso do DTO é entre camadas físicas para otimizar comunicação entre as mesmas. Neste caso eu concordo com as outras pessoas até porque eu escolheria a opção 2);
  4. Se vc quiser seguir a bíblia do mago fowler da refatoração e utilizar a refatoração Introduzir objeto parâmetro, derrepente você vai acabar chegando a 3.

Se vc quiser comentar os pontos citados acima sera muito bem vinda sua opinião sobre eles!

[]s

Eu vejo problemas. Só você ver a parte dos problemas encontrados ao implementar essa solução.

Outro problema é quando o Usuario não é apenas um Bean simples.

Quanto a coesão, eu não vejo problemas. A action está apenas implementando um interface, e o acoplamento está sendo feito através de uma abstração.

Eu acho que esta solução está muito parecida com a do DTO, só que não existe o DTO concreto, e sim uma especificação dele (a interface).

JUZAM, toda esse discussão são os pêlos que ainda temos que cortar na maldita camada de apresentação que se integra mal e porcamente ao Domain Model no paradigma OO atual.

Não tem jeito, tudo que fazemos tem vantagens e desvantagens. É uma droga trabalhar com beans que são abstrações de um form html. O padrão html não ajuda nada também.

Desculpa postar sem te ajudar em nada, mas acho que o teu problema é que você deve estar desconfiado que está fazendo alguma coisa errada e deve estar esperando alguém aqui postar alguma coisa nova… mas acho que nesse caso, bemvindo ao time dos “você não tem outra opção”. :cry:

Na verdade, eu postei para saber a opinião de vocês sobre esta solução. Era para ser um topic para gerar discussão sobre outras idéias ou patterns que o pessoal conhece para este tipo de problema.

Aproveitei o gancho para falar sobre como foi a adoção de outra estratégia que eu fiz no passado e não deu muito certo.

Na verdade eu não sei se eu foi claro ao colocar o exemplo, o bruno achou que não existia a entidade usuário por exemplo. Eu omiti o exemplo dela porque achei desnecessário e porque se você ver a interface do negócio ela retorna um tipo usuário.

Ainda não testei na prática este modelo do RawData, mas acredito que vai dar certo…

O tempo dirá :smiley:

Só este paragrafo acho que já ajuda muito a todos inclusive a mim! Que sempre sinto mal cheiros que nunca consigo eliminar e fico empacado. Acho, que como eu, temos que aprender a dozar as coisas e sempre andar frente. Acho que é isso ai vestir a camisa do time!