Mvc

34 respostas
M

Pessoal,

Estou com algumas dúvidas na hora de dividir na prática a minha aplicação.

Levando em consideração uma aplicação web, observem:

View => Minha interface com o usuário

Controller => O cara que serve que leva a informação do usuário para o model e vice-versa.

Model => Regras de negócio e persistência

Esta primeira parte está correta ?

Bom então vamos ao prático:

Numa aplicação web utilizando struts:

Views => minhas páginas JSP

Controller => o servlet do struts

Model => As minhas Actions e ActionForms(Regras de negócio), meus beans e meus DAOS (Persitência)

Isso está correto ?

Alguns desenvolvedores defendem que as regras de negócio não deveriam ficar dentro dos Actions/ActionForms. Onde ficariam ?

No contexto acima qual é a forma mais elegante de se dividir a aplicação ?

Obrigado Pessoal

34 Respostas

zelopes

E com razão pois, suas actions são controladores, ou pelo menos deveriam ser…

tu pode usar uma classe intermediaria entre controle e persistencia para tratar sua lógica de negócios, ou seja, na camada de modelo temos varias subcamadas digamos assim, as quais compoem o mesmo…entre elas a persistencia…

[]'s

pcalcado

Suas Actions fazem parte do Controller. O Struts (aliás, procure outro framework) é um framework, isso quer dizer que ele deve ser extendido. No caso você extende o controller do Struts com seus controllers (suas actions).

As regras de negócio ficam nos objetos de negócio. Mais detalhes Mundo Java #15 e #17.

P

Sou novo no GUJ mas já estou me habituando a escrever logo após ao pcalcado.

Só para aproveitar a deixa dele, um bom framework para aplicações MVC para web é o Spring MVC.

Ah, e se você está escrevendo toda a sua regra de negócio nas classes Action/ActionForm tome cuidado. Você está deixando seu código muito dependente do framework. De repente você quer trocar de framework (por algum motivo qualquer) e todo o código realmente seu (a lógica da sua aplicação) estará preso ao framework.

Abraços

M

Certo… era justamente isso que estava precisando entender. Isso que vocês me falaram batem com uns artigos que ando lendo. Na verdade as actions são controllers, elas são como auxiliares do servlet do struts. Pelo que li, elas são uma implementação do padrão Command.

Agora vamos supor que eu tenha uma entidade chamada cliente. Nesta entidade eu tenho as seguintes colunas: identificacao, nome e pessoa. Suponha ainda, que o campo pessoa irá receber JURIDICO se a identificação for um CNPJ e FISICO se na identificação for informado um CPF. Bom, isso é uma regra, certo ?

Pelo o que ando lendo e pelo que eu ando aprendendo trocando idéias com a galera aqui no GUJ, a minha distribuição ficaria assim:

MODELO

ClienteBean = Classe sem validações, sem regas somente com os atributos getters e setters.

ClienteDAO = Classe sem validações , sem regras responsável por pegar o ClienteBean e persistí-lo no banco.

ClienteNegocio = Classe sem os atributos da entidade. Deve conter somente métodos que representem as regras. No nosso caso ele teria o método: public void verificaPessoa(ClienteBean cliente) . SIMPLORIAMENTE FALANDO, esse método verificaria, através do tamanho do conteúdo da propriedade identificacao, o conteúdo do atributo pessoa. Se identificacao tiver 11 caracteres(CPF) , pessoa = FISICA, senão pessoa=JURIDICA .

CONTROLLER

No controller eu teria o servlet do struts(estou estudando vraptor, mas continuo aceitando sugestões)

AdicionaClienteAction AdicionaClienteForm = Cria e popula o bean, submete aos métodos da classe de negócio, e entrega o bean ao DAO para ser gravado no banco.

VIEW

Minha página cadastro-cliente.jsp

O que acham, está legal isso ?
Obviamente não influi no funcionamento , mas a nomenclatura está bacanal ? É assim mais ou menos assim que vocês utilizam ?

Valeu rapazeada !
Mais uma vez obrigado.

David

Pra que essa separação do ClienteBean e do ClienteNegocio? Não faz sentido ter essas duas classes. Por que não ter uma classe cliente com os atributos e métodos relativos ao comportamento de um cliente?

Ter uma classe apenas com atributos, getters e setters não é uma boa prática. Você está criando objetos burros.

nbluis

David, não concordo com sua afirmação sobre “objetos burros”, conhecidos value objets.

  • E quando temos um ambiente com a regra de negócio remota, como transitar seus dados/entidades entre eles?

Acho uma pior prática, trabalhar com objetos de negócio dentro dos teus requests para fazer a camada view em tags.

Isso sim fica feio… Hehe…

Até mais…

David

nbluis, no post acima eu coloquei um link para um artigo que explica o que são objetos burros. Já que você falou em “VO”, coloco agora um outro: Evitando VOs e BOs. Saiba que esse tipo de prática que você está defendendo não é muito OO não…

M

Como vai David…

Você está falando então que ficaria melhor estruturada, do ponto de vista O.O. se eu juntasse a minha classe ClienteBean com a ClienteNegocio e tivesse simplesmente uma classe Cliente ? Pelo que eu li, a principal tarefa do JavaBean é transportar a informação entre as várias camadas da aplicação, e que por isso não seria desejável que ela fosse carregada de outras coisas.

Como fica isso com relação a performace se os meus beans tiverem toda a regra de negócio junto ?

Obrigado.

cassio

Eu tenho uma concepção parecida com a do amigo maazevedo… Fico imaginando o custo a mais de ter uma única classe que una as características de um JavaBean e de uma classe de negócios… Esses objetos vão ficar transitando do banco (através dos DAOs ou coisa do tipo) até chegar à camada de apresentação, onde tudo o que eu preciso são dos atributos e nada mais… Mas na verdade conterão trocentos métodos que neste ponto serão inúteis pra mim. Como fica o custo desperdiçado de se criar estes objetos?

s4nchez

Depende. Você vai transmitir estes beans via rede? Vão ficar só em memória? Qual a estimativa de quantidade de beans que sua aplicação deve manter instanciados simultaneamente? Qual é a restrição de desempenho que você tem?

Criar soluções mirabolantes baseadas num problema que sequer sabe-se que existe é um dos maiores erros. Na dúvida, siga a linha: “Make it work. Make it right. Make it fast.”

cassio

s4nchez:
maazevedo:

Como fica isso com relação a performace se os meus beans tiverem toda a regra de negócio junto ?

Depende. Você vai transmitir estes beans via rede? Vão ficar só em memória? Qual a estimativa de quantidade de beans que sua aplicação deve manter instanciados simultaneamente? Qual é a restrição de desempenho que você tem?

Criar soluções mirabolantes baseadas num problema que sequer sabe-se que existe é um dos maiores erros. Na dúvida, siga a linha: “Make it work. Make it right. Make it fast.”

Mas e quanto a escalabilidade? Eu posso não ter problemas com desempenho hoje e o fato de ter classes “mais gordas” não interferir, mas amanhã o volume de acesso da minha aplicação pode dobrar e o que não era problema pode passar a ser…
Da mesma forma, hoje eu posso manter meus beans só na memória, mas amanhã posso querer que essa aplicação envie os objetos pela rede e a coisa toda forme um gargalo… terei reescrever a coisa toda?

Seguindo a linha de raciocínio de que os beans devem possuir os métodos que cuidam das regras de negócio, não fica muito claro pra mim como esse tipo de problema pode ser solucionado (ou até msmo previsto)…

s4nchez

cassio:
s4nchez:
maazevedo:

Como fica isso com relação a performace se os meus beans tiverem toda a regra de negócio junto ?

Depende. Você vai transmitir estes beans via rede? Vão ficar só em memória? Qual a estimativa de quantidade de beans que sua aplicação deve manter instanciados simultaneamente? Qual é a restrição de desempenho que você tem?

Criar soluções mirabolantes baseadas num problema que sequer sabe-se que existe é um dos maiores erros. Na dúvida, siga a linha: “Make it work. Make it right. Make it fast.”

Mas e quanto a escalabilidade? Eu posso não ter problemas com desempenho hoje e o fato de ter classes “mais gordas” não interferir, mas amanhã o volume de acesso da minha aplicação pode dobrar e o que não era problema pode passar a ser…
Da mesma forma, hoje eu posso manter meus beans só na memória, mas amanhã posso querer que essa aplicação envie os objetos pela rede e a coisa toda forme um gargalo… terei reescrever a coisa toda?

Seguindo a linha de raciocínio de que os beans devem possuir os métodos que cuidam das regras de negócio, não fica muito claro pra mim como esse tipo de problema pode ser solucionado (ou até msmo previsto)…

Este aumento no volume de acesso já é algo previsto? Se for, estabeleça parâmetros concretos, faça os devidos testes e então decida se vale a pena implementar assim ou não. Se isso não é um problema agora, por que complicar?

Quanto ao gargalo, dificilmente você terá que reescrever a aplicação toda. Pense que pode ser bem mais fácil você modificar uma parte conhecida e testada partindo de um problema real, do que tentar criar algo novo para um provável problema.

M

Pessoal,

Eu não sabia que este assunto era tão polêmico. A OO defende que dados e comportamentos relacionados estejam juntos. PORÉM, muitos livros e muitos cursos de java pra internet pregam JavaBeans e Classes de negócio separados.

E ainda tem mais uma - A persistência - onde fica ???

David

Se os livrosque pregam que Dados e Negocio devem ficar separados (nunca li um assim, ainda bem) falam que isso é OO eles estão errados. E qual o problema com a persistência? Não vejo nenhuma diferença.

F

Olá,

Duas perguntas…

Primeiro: Voce acha mesmo que esse seria o maior problema pra escalabilidade se seu sistema dobrar a quantidade de acesso?

Segundo: Voce ja serializou uma massa de objetos com todos atributos, metodos, etc dentro dele e outro DTO pra ver realmente a diferenca de tamanho deles?

]['s

F

Acredito que esses livros que tu fala estejam falando de sistemas usando EJB e/ou sistemas de servico com acesso remoto onde a aplicacao roda em mais de uma JVM, ai sim pode ser que vale a pena manter essa separação, mas isso PODE ser teria que avaliar caso a caso.

No banco? :stuck_out_tongue:

]['s

M

Desculpa, acho que não fui claro. Vou melhorar a pergunta: Onde seria correto colocar os inserts, updates, deletes ? Neste caso(persistência) você utilizaria uma classe separada?

Valeu…

M

Ah sim… mais uma coisa. Vocês podem me indicar livros que vocês já leram sobre o assunto…

Obrigado.

F

maazevedo:
David:

E qual o problema com a persistência? Não vejo nenhuma diferença.

Desculpa, acho que não fui claro. Vou melhorar a pergunta: Onde seria correto colocar os inserts, updates, deletes ? Neste caso(persistência) você utilizaria uma classe separada?

Valeu…

No DAO normalmente.

]['s

F

maazevedo:

Ah sim… mais uma coisa. Vocês podem me indicar livros que vocês já leram sobre o assunto…

Obrigado.

Comece por esse e estara bem servido.

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/[telefone removido]

]['s

M

Valeu fabgp2001…
Obrigado.

David

Boa sugestão do Fábio… Domain Driven Design é excelente. Sobre a persistência, use um DAO para colocar os métodos que você falou.

pcalcado

Bom, vamos devagar…

JavaBeans não são classes apenas de dados, são um modelo de componente falido da Sun. Hoje em dia um JavaBean é uma classe que obedece a convenção de métodos com nome de get/set, não diz [bnada[/b] sobre terem dados, lógica ou qualquer otura coisa.

Sobre “classes de daos x classes de lógica”, se algum livro menciona isso (fora do cotnexto EJB 2.x, por favor) me indique porque eu estou atraz desta literatura faz tempo.

Quanto á escalabilidade, ter classes de dados e de lógivca separados não vai ter ajudar. Classes de dados não são DTOs de verdade, DTOs são criados pensando em como otimizar tráfego por uma rede, não mapear conceitos de negócio. A Mundo java #15 fala disso .

Os outros questionamentos sobre o uso de objetos de verdade (“classes gordas”) e não structs não possuem argumentos. Por que haveria perda de desempenho? Não há problema de escalabilidade em utilizar objetos.

“Tudo que preciso são dos atributos” foge completamente aod esenvolvimento OO. O que você precisa, seja em qual camada for, é de objetos, e eventualmente mostrar alguma dimensão (um atributo, comaprando porcamente) do estado deste. Logo você passa o objeto e exibe a dimensão, sem maiores problemas.

A questão não é ‘ficar melhor estruturada do ponto de vista O.O.’ a questão é de que simplesmente se você não tem objetos possui estruturas de dados e funções, e se você possui estruturas de dados e funções você não está num sistema OO e sim num sistema procedural, exatamente como os construídos em Pascal ou C.

O tal ‘desperdício’ de criar objetos com métodos que não serão utilizados não procede. A JVm (assim como a maioria das plataformas) cria apenas uma vez o espaço destinado a código em memória, logo não há repetição não utilizada.

Leiam os artigos, eles trazem muitas informações sobre isso.

cassio

Olá pcalcado,

Quer dizer então que se eu tenho 20 objetos, eu tenho em memória o estado destes 20 objetos (diferentes valores para seus atributos), mas a área de código que é igual para todos os objetos (no nosso caso o código dos métodos) é alocado uma única vez?

Obrigado!

pcalcado

Sim. Os bytecodes são os mesmos para todas as instancias de uma dada classe.

Rodrigo_Vieira_Pinto

Ainda bem que é assim, já pensou se tivessemos uma tela complexa feita em swing, com muitos botões por exemplo e cada um deles fosse um objeto separado? Imagina então se a máquina do usuário for um pentium 2 com 16MB de memória…

asclows

Desculpe a ignorância de minha parte, mas só pra matar as últimas dúvidas bestas que tenho sobre o assunto.

Implementando, corretamente a action do modo como foi comentado aqui e desprezando o modo como o framework carrega a classe de negócio, seria?

Cliente cliente = new Cliente();
... chamada aos setters para atributos de cliente
cliente.verificaPessoa();

ClienteDao dao = new ClienteDao();
dao.save(cliente);

ou

Cliente cliente = new Cliente();
... chamada aos setters para atributos de cliente
cliente.verificaPessoa();

ClienteDao dao = new ClienteDao();
cliente.save(dao);

1º) Qual seria o mais correto do ponto de vista OO?
2º) Se Cliente salvar a si mesmo não ficaria atrelado esse a metodo 'save' da interface do dao?

cassio

Minha dúvida é similar à do amigo que postou acima…
Se eu deixar que meu bean cuide tbm das regras de negócio, é correto então instanciar o DAO dentro do bean? Se não for essa a maneira correta, qual seria? Existem alternativas?

Obrigado!

David

Eu particularmente não gosto muito da idéia de criar uma dependência da classe de dominio com o DAO, portanto escolheria dao.save(cliente). Mas isso é questão de persistência e não regra de negócio.

cassio

David:
Eu particularmente não gosto muito da idéia de criar uma dependência da classe de dominio com o DAO, portanto escolheria dao.save(cliente). Mas isso é questão de persistência e não regra de negócio.

Mas eu faria algo assim?

public class MinhaClasse{
   //atributos

   //getters and setters

   //public String save(){
      MeuDAO dao = new MeuDAO();
      //mais código...
      dao.save(this);
      //mais código...
   }
}

Quer dizer, é correto instanciar o DAO dentro da classe ?

asclows

O que me intriga é o caso dos fantoches que o Phillip menciona, daí parto para o pré-suposto de que o save deveria pertencer ao cliente, mas logo se passo um dao pra ele crio um acoplamento do meu objeto de negócio com a interface de persistência.

Mas pensando por outro lado, não estaria preso à uma classe Dao em si, somente à interface disponível, ou seja, o meio de comunicação a qual meu objeto precisa saber para salvar a si mesmo, daí independe se vai ser persistido em banco de dados relacional, arquivo XML ou outro meio.

Será que essa linha de pensamento poderia ser considerada como viável?

Sua reusabilidade poderia ser menor do que no caso dao.save(cliente), onde a classe Cliente é independente e poderia ser reutilizada em qualquer outro projeto.

Phillip? David?

P.S.: O assunto parece estar fugindo do tópico, mas se perceberem ele é complementar ao MVC porque o que estamos discutindo é praticamente o que fica na Action, e pergunta do criador do tópico foi “… qual é a forma mais elegante de se dividir a aplicação ?”

cassio

Ao meu ver na action deve existir APENAS o controle da aplicação, isso é, para onde o usuário é direcionado a cada intereção com o aplicativo, o que acontece com a camada de apresentação, quais componentes são chamados, etc. Eu ainda tenho dúvidas quanto a ter regras de negócio nos meus beans, entretanto tenho certeza de que regra de negócio na action não pode!

pcalcado

Calma calma, saímos do projeto e chegamos á arquitetura do sistema.

Todas as dúvidas quanto a “objetos de lógica” e “objetos de dados” serem ruins sanadas?

Próximo passo: Camadas.

Apresentação, Negócios e Persistência são geralmente implementadas como Camadas diferentes. Dêem uma olhada nestes slides e procurem a MundoJava #15.

Quanto ao DAO, existem duas estratégias básicas: DataMapper e ActiveRecord. As duas têm utilizade mas geralmente o Mapper é preferida. para abstrair o DAO pode-se utilizar um repositório, mais detalhes MundoJava #17 ou uma busca por domain driven design (tem um post recente sobre isso no meu blog).

brunohansen

Que susto levei aqui! VO é um objeto burro?
Tudo bem estou mais acostumado com o VO do Fowler que diz: Um objeto pequeno e simples, como dinheiro ou intervalo de datas, cuja a igualdade não é baseada em identidade e sim em valores.

Repare que no artigo do shoes ele disse:
Um dos padrões deste catálogo era chamado de Value Object, ou VO. Posteriormente este objeto foi renomeado para Transfer Object por haver um conflito de nomes dele e outro padrão (interessante notar que a documentação oficial ainda faz uso do nome antigo nos diagramas) e porque trata-se de uma adaptação do padrão Data Transfer Object, também do Fowler.

O VO antes chamado pela Sun hj é Transfer Object. (Esse sim é meio burro mas pode ser utilizado bem em comunicação de redes).
O VO do Fowler não tem nada de burro!

Resumo bom do livro DDD http://www.infoq.com/minibooks/domain-driven-design-quickly

[]s

Criado 20 de fevereiro de 2007
Ultima resposta 1 de mar. de 2007
Respostas 34
Participantes 12