Estrutura da Aplicação - MVC

31 respostas
F

Gostaria de saber a opinião da galera sobre a estrutura das classes da aplicação.

-Cidade _ Bean apenas com os atributos com gets e sets

int codigo;

String descricao;

Vou dar um exemplo:
-Tela de cadastro de cidade.
Esta tem uma instância de CidadeControll.

  • CidadeControll _ Tem os metodos para inserir/alterar, apagar e recuperar uma cidade. Caso alguma operação cause exceção ela tem a função de disparar um JOptionPanel

A Tela de Cadastro instancia o Bean Cidade e passa como parâmetro para por exemplo o método inserir para gravar no banco.

A CidadeControll por sua vez tem uma instância de CidadeDAO que implementa uma interface com os metodos para inserir/alterar, apagar e recuperar.

-CidadeDAO _ Pega uma connection e o parâmetro, no caso o objeto Cidade e grava no banco.

31 Respostas

Rafael_Steil

Ta ok… soh uma coisa: se a tua Control sempre for delegar direto pro DAO, voce poderia usar o DAO direto ( ao menos que a tua classe control decida para qual implementacao de dao delegar… ou seja, se ela for algo como / acessar um factory de dao’s )

Rafael

F

Olá,

O teu bean é um VO?

]['s

F

Seguinte, não mensionei mas essa arquitetura é pra usar EJB.

Estou amadurecendo a idéia e gostaria de receber sugestões !!!

F

Refatorei e está mais ou menos assim, citando um exemplo:

:arrow: Tela de venda (FM_Venda)

:arrow: RN_Venda
Possui uma instância de RN_Cliente e de RN_NotaFisal

:arrow: RN_Cliente
Possui uma instância de DAO_Cliente com os métodos insert, update, …, sendo que estes apenas invocam os metodos da DAO

:arrow: DAO_Cliente
Peja uma connection de uma classe especializada e executa os métodos insert, update, …

:arrow: RN_NotaFiscal
Possui uma instância de DAO_NotaFiscal com os métodos insert, update, …, sendo que estes apenas invocam os metodos da DAO

:arrow: DAO_NotaFiscal
Peja uma connection de uma classe especializada e executa os métodos insert, update, …

RN = Regra de Negócio

cv1

Ta legalzinho, mas… http://java.sun.com/docs/codeconv/ :wink:

F

FmVenda
RnVenda
RnCliente
DaoCliente
RnNotaFiscal
DaoNotaFiscal

e agora cv?

Tem alguma outra sugestão?

cv1

Bom, ja que a gente ta falando sobre nomenclatura… Rn e Fm nao fazem o menor sentido na primeira olhada… pq nao algo mais descritivo como Venda e VendaForm, ao inves de RnVenda e FmVenda? :smiley:

F

FormVenda
RegraNegocioVenda
RegraNegocioCliente
DaoCliente
RegraNegocioNotaFiscal
DaoNotaFiscal

RegraNegocio = Achei meio extenso.
DataAccessObject (Dao) = Acho que ficaria mais extenso ainda.

FormVenda ou VendaForm
DaoCliente ou ClienteDao

Peguei o espírito ou ainda tá meio confuso?

F

Olá,

RegraNegocio não precisa colocar.

ClienteForm
Cliente
ClienteDAO

]['s

F

fabgp2001, deixe-me ver se entendi:

ClienteForm - tranquilo
ClienteDAO - tranquilo

:arrow: Cliente - Este tem os atributos tipo: codigo, nome, endereço com os gets e sets.
Do jeito que vc está me sujerindo ele também teria os métodos insert, update, … que com uma instância de ClienteDAO faria a persistência.

É isso mesmo?

Rafael_Steil

Nao necessariamente. O teu ClienteDAO poderia receber uma instancia de Cliente, ao inves do Cliente chamar o ClienteDAO.

Rafael

F

Pois é, mas era isso que eu estava fazendo.

Tenho por exemplo a Tela de cadastro de Cidade. Esta tem uma instância de RnCidade que controla as regras de negócio da cidade.
A regra de negócio da cidade é que tem uma instância de CidadeDAO onde faço a persistência.

A dúvida é a seguinte. Tenho uma classe chama Cidade somente com parâmetro e gets e sets. (Está classe está correta?)
Quanto pego os valores dos textfields da tela instâncio a Cidade (na tela mesmo) e passo para a RnCidade. Esta verá se esta tudo preenchido corretamente e repassará para a CidadeDAO fazer a persistência.
Ex.:

Cidade cidade = new Cidade(codigo, descricao);
RnCidade rnCidade = new RnCidade();
rnCidade.salvar(cidade);

Isso tudo na tela

A RnCidade recebe todos os erros que podem ocorrer quanto a persistência e validação, trata e repassa em forma de String para ser exibida na Tela em uma JOptionPane por exemplo.

cv1

Isso é um anemic domain model. Nao que seja ruim, por si só, mas pode ser melhor: http://www.martinfowler.com/bliki/AnemicDomainModel.html

E

Eu também tenho dúvidas a respeito da melhor estrutura para um modelo MVC… acho que a discussão fugiu um pouco do foco…

Então gostaria de retomar o assunto: qual seria a melhor estrutura MVC para o modelo proposto pelo Fabricio? É interessante ter uma classe de Negócio + uma classe Bean + uma classe DAO (considerando que poderíamos ter uma factory de DAOs)?

gcobr

Olá cv

Estive lendo o artigo que você mencionou e pude identificar a presença de um Anemic Model no projeto em que trabalho.
Temos muitos EJBs (Session Beans) que tratam várias regras de negócio da aplicação. Alguns deles são inclusive statefulls.
Os objetos de domínio como (exemplo: Cliente, Produto, Venda, Pedido …) são planos e sem nenhuma codificação, exceto getters e setters.
A principal razão para isso é de que temos uma interface gráfica Swing que acessa esses Session Beans no servidor de aplicação (JBoss nesse caso). Isso implica na serialização de todos esses objetos de domínio, a fim de transportá-los pela rede até a máquina cliente, e portanto, quanto mais enxutos eles forem, mais rápido é o transporte.
Outro aspécto importante, é que várias regras de negócio da aplicação em questão (e algumas validações) precisam ser forçadas na própria interface, para torna-la altamente interativa. Para resolver isso, acabamos implementando várias classes que consideramos “modelos” no lado cliente. Esses modelos são geralmente implementados no estilo MVC, para exibir os dados em uma enorme variedade de formulários e controles visuais Swing extremamente complexos.

Para tornar meu relato ainda mais claro, darei alguns exemplos da interatividade que sempre buscamos:

Suponha que você tenha um formulário de entrada de dados para um objeto que representa uma “venda” no sistema. O usuário terá que associar à essa venda um objeto “cliente” já existente e também um objeto “pedido”,
Agora imagine que o esse objeto “pedido” possui uma coleção de “itens”, que representam todos os itens solicitados pelo “cliente”.
Imagine também, que o objeto “venda” também possui uma coleção de “itens” que representa todos os itens que foram realmente vendidos ao cliente, e para os quais foi emitida uma nota fiscal por exemplo.
Para criar, tal formulário tivemos que desenvolver uma classe que chamamos de “Lookup”. Essa classe se encarrega de criar uma janela modal na qual é exibida uma lista dos objetos que se deseja vincular. Por exemplo, uma lista de todos os clientes ou pedidos do sistema, que pode ser filtrada de acordo com alguns valores que podem ser informados pelo usuário nessa mesma janela. Para conseguir isso, a classe “Lookup” tem que recorrer ao servidor de aplicação para executar métodos de busca e obter as listas de objetos para exibição.
Suponha então, que ao associar um objeto “pedido” localizado através de um “Lookup” como mencionei antes, você tenha que criar automaticamente “itens” correspondentes na venda, pré supondo que todos os itens do pedido tenham sido efetivamente vendidos.
Levando em consideração que esses “itens” de venda devem ser exibidos em uma grade (JTable) tivemos que desenvolver um TableModel adequado para esse fim. Nesse caso, tal TableModel precisa acessar diretamente o objeto “venda” que estiver sendo editado para apresentar seus itens. Foi necessário ainda criar métodos auxiliares nesse TableModel para que se pudessem incluir, remover e alterar itens da lista dinamicamente, já que o usuário poderá querer incluir, remover ou alterar itens da venda antes de finalizá-la. Esses métodos, além de providenciarem a atualização do JTable também alteram a lista de itens do objeto “venda”.
Outra sofisticação comum, seria por exemplo, mandar um aparâmetro para o “Lookup” dos pedidos de forma que ele só pudesse exibir “pedidos” do “cliente” previamente informado. Ou no “Lookup” de “clientes” só poderiam ser exibidos os clientes que tivessem algum pedido que ainda não tivesse sido associado a nenhuma venda!
Na inclusão de novos itens na venda por exemplo, poderia ser necessiário verificar a dispobilidade de estoque da quantidade vendida, antes de permitir a inclusão do item no formulário.
Por fim a venda poderia ser enviada para o método “insert” de um Session Bean no servidor de aplicação que faria sua persistência e atualizaria o estoque debitando as quantidades dos itens vendidos.

(Agora imagine, que esse exemplo é bem mais simples do que o que realmente temos que implementar no sistema real…)

Se anlisarmos esse requisitos em um estilo mais OO e mais abstrato, poderiamos chegar a algumas conclusões mais lógicas em relação ao domínio de objetos, que com certeza seria mais “rico”.

  • A lógica de validação do pedido e do cliente poderia estar dentro dos respectivos métodos set na classe da venda. Ou poderia haver um método set para associar os 2 ao mesmo tempo.
  • A lógica de “copia” dos itens do pedido para a venda poderia também estar encapsulada dentro de um método set para o pedido dentro da classe venda. Ou poderia haver um método na classe venda específico para esse fim.
  • A validação do item da venda em relação ao estoque poderia ser feita no método addItem (que inclui um item na venda) ou então no método que associasse o pedido.
  • Para efetuar as baixas no estoque poderia também haver um método na própria classe da venda, ou poderia ser feito em Session Bean mesmo.

Entretanto, essa abordagem traria os seguintes problemas …

  • Teriamos objetos do domínio acessando Session Beans para buscar/validar informações e isso parece muito estranho.
  • Teriamos bastante código nas classes do domínio, aumentando bastante o seu custo de transporte pela rede.
  • A interatividade do formulário com o usuário seria perdida ou sua implementação se tornaria ainda mais complexa do que já é.

Para concluir …

Gostaria de perguntar se você vê alguma maneira de tornar esse modelo, menos “anêmico”, ou se você consegue identificar alguma falha de design em algum desses raciocínios…

E caso esse exemplo inspire mais alguém que também desenvolva uma interface Swing para uma aplicação J2EE, comentários serão bem vindos.

Saudações,
Gabriel C. Oliveira

cv1

Opa! Valeu pela otima explicacao, Gabriel! :D

"gcobr":
Se anlisarmos esse requisitos em um estilo mais OO e mais abstrato, poderiamos chegar a algumas conclusões mais lógicas em relação ao domínio de objetos, que com certeza seria mais "rico".

Um modelo de domínio rico tem algumas vantagens, e a primeira e mais importante de todas é que vc consegue representar, de forma realmente OO, os requisitos do seu sistema, e as funcionalidades dos seus objetos. Se voce parar pra pensar bem, um modelo de objetos anemico (feito de VOs, como no seu caso) é programação procedural, e um objeto que só tem getters e setters não é muito diferente de uma struct em C :(

"gcobr":
- A lógica de validação do pedido e do cliente poderia estar dentro dos respectivos métodos set na classe da venda. Ou poderia haver um método set para associar os 2 ao mesmo tempo.

Pode ser, o importante aqui não é em que método colocar, mas sim que a lógica de negócio de um determinado objeto esteja contida nele, mesmo que através de delegação. Delegacao, alias, faz com que a gente ganhe o melhor dos dois mundos. É possivel, por exemplo, usar o Command Pattern, aliado a Decorators, e se divertir bastante:

public class Cliente ... {

  public void addPedido(Pedido p) {
    new CommandExecutor(new AddPedido(this, p)).execute();
  }

}
public class AddPedido ... {

  public AddPedido(Cliente c, Pedido p) {
    this.cliente = c;
    this.pedido = p;
  }

  public void execute() {
    // ...
    // checa todas as regras, joga excecoes, etc
    // ...

    c.getPedidos().add(p);
    p.setCliente(c);
  }

}

Dentro do CommandExecuter, voce pode se divertir decorando o command com transacoes, configuracoes extras, etc e tal. Mas quem tá de fora, ou seja, sua interface, não fica nem sabendo sobre o que está debaixo dos panos. O importante aqui é isolar os problemas. Persistência, distribuição e esse tipo de coisa podem ser isolados dentro do seu modelo de objetos, sem que a interface fique se preocupando muito com isso. O que tem de tão horrível em chamar um monte de setXXX() e addXXX() em um objeto de negocio, e quando terminar de trabalhar chamar um save()? ;)

Agora, quanto aos "contras" de se ter um modelo de objetos rico:

"gcobr":
- Teriamos objetos do domínio acessando Session Beans para buscar/validar informações e isso parece muito estranho.

Nao necessariamente. Como eu expliquei acima, os objetos do seu dominio so precisam servir de fachada pra um monte de outras esquisitices por baixo. E, dessas esquisitices, ninguem mais precisa ficar sabendo alem dos seus objetos de negocio ;)

"gcobr":
- Teriamos bastante código nas classes do domínio, aumentando bastante o seu custo de transporte pela rede.

A quantidade de codigo nao aumenta o custo de transporte. A quantidade de dados, sim. Lembre-se que a serializacao não transporta o codigo toda vez que vc serializa um objeto, mas só o estado daquele objeto.

"gcobr":
- A interatividade do formulário com o usuário seria perdida ou sua implementação se tornaria ainda mais complexa do que já é.

Não senhor, e alias muito pelo contrario. Eh possivel fazer TableModels mais inteligentes quando vc trabalha com objetos mais "completos". Uma JTable que representa os Itens de um Pedido pode ser um Observer do Pedido, e adicionar um novo item ao pedido modifica a JTable, e nao o contrario (modificar a JTable causa uma alteracao no Pedido). Mais facil, mais OO, e com certeza usando menos codigo :D

dukejeffrie

Cara, adorei essa thread!

Eu tb nunca tinha lido sobre o modelo anêmico, e percebi que grande parte das coisas que eu tenho desenvolvido sofre um pouco desse mal.

Geralmente a gente fala de separação de interesses (Separation of Concerns, até hoje não achei uma tradução definitiva pra isso) e acaba separando dado do código.

Pois eh, olha como já tá na cabeça que os objetos de domínio são por natureza passivos…

Eu acho que o vício (bom, hoje, e nesse contexto, parece um vício, quem sabe em alguns anos volta a ser moda) surge em parte pela grande quantidade de material que a gente lê e que é feita pensando num ambiente web, com HTTP, etc. Quase todos os meus value objects são pensados pra mapear valores que vêm de um POST, ou que vão ser exibidos numa página. Esses caras não têm nenhum motivo pra implementar regras de negócio.

Na verdade, escrevi tudo isso pra fazer essa pergunta: esses objetos devem e serão sempre value objects? Alguém já implementou algo diferente?

[]s!

cv1

Eu lembro de ter usado o bom, velho e infame HashMap no lugar dos objetos POSTados, sem muito problema. Eu tinha quase uma centena de forms ridiculamente diferentes pra mapear, e criar classes pra tudo isso (mesmo que fossem Actions do Struts/WebWork/Spring/SeuFrameworkFavorito) ia ser uma trabalheira proibitiva :smiley:

Depois que eu tinha os dados num Map, copiar eles pros lugares certos era relativamente tranquilo (os objetos de negocio recebiam o Map no construtor e se populavam). :wink:

F

Vamos ver se entendi.
Então os VOs deixariam de ter apenas os gettes e setters e passariam a ter todos os métodos de alteração do estado do objeto.

O que aconteceria com a minha classe com regras de negócio ou business object?

F

Vi que no guj2 os VOs tem apenas os getters e setters.

O guj2 segue os conseitos de anemic model?

cv1

Nao confundir VO com Bean. VOs sao JavaBeans “burros”, sem codigo. Num dominio rico, vc nao usaria VOs, mas sim JavaBeans.

“fabriciogiordani”:
Vi que no guj2 os VOs tem apenas os getters e setters.

O guj2 segue os conceitos de anemic model?

Sim. :frowning:

Daniel_Quirino_Olive

Bom, antes que comecem a dizer por aí que usar VOs são prejudiciais à saúde, que eles causam hipertensão arterial e afins, VOs são úteis quando você precisa encapsular dados obtidos através de fontes remotas, diminuindo a quantidade de “transações” e aumentando a performance na obtenção de dados. E só!

http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html

F

Então o modelo anêmico seria ideal para trabalhar com EJB.

Estou certo?

Daniel_Quirino_Olive

“fabriciogiordani”:
Então o modelo anêmico seria ideal para trabalhar com EJB.

Estou certo?

Não. O modelo anêmico nunca é ideal. O que eu quis dizer é que VOs só servem para encapsular dados para transferi-los de um ponto a outro da sua aplicação quando você usa mecanismos distribuídos de acesso a dados.

V

Eu procuro constantemente aprender coisas novas em java. Eu gosto bastante de aprender design patterns. Eu entendo o MVC mas não conseguir absorver completamente a forma como ele é aplicado.

Depois de ler esse tópico conclui que um dos gurus (leia-se: cv, DQO e CIA.) do java, ou todos eles, deveriam escrever um artigo sobre o assunto como resultado dessa discusão. No GUJ encontramos muitos artigos interessantes mas não tem nenhum sobre MVC genérico (Tem um que fala de MVC com WebWork)! :-o Acho que seria de grande utilidade para a comunidade um artigo que deixasse claro como usar o MVC idependente até da linguagem OO utilizada. :slight_smile:

Alguém topa? :roll:

Daniel_Quirino_Olive

Sugestão anotada. Aliás, bem que vocês poderiam mexer um pouco mais suas bundas e começar a escrever algumas coisas para o GUJ também, né? Não sei se vocês sabem, mas escrevendo artigos para o GUJ vocês correm sérios riscos de ganherem vale-livros da Livraria Tempo Real (livros na faixa -ou quase, dependendo do preço do livro), aprenderem melhor sobre um determinado assunto (já que, para escrever sobre algo, você precisa pesquisar e estudar para colocar com suas palavras aquilo que você aprendeu), além de se tornarem celebridades do GUJ :smiley:

gcobr

Lendo os comentários de cv e os demais posts deste thread refleti um pouco mais sobre o design de uma aplicação em que estou trabalhando e cheguei a algumas conclusões que gostaria de expor:

Até o momento, uma grande parte da lógica de negócios do já desenvolvi está codificada em Stateless Session Beans. Outra grande parte está implementada em modelos e controladores de MVC na interface gráfica Swing da aplicação. Ou seja, não há nada nos objetos reais do domínio.
As regras que estão nos modelos e controladores do MVC são basicamente para controlar a entrada de dados na aplicação e facilitar o preenchimento de formulários. Com base nas sugestões do cv estou pensando em maneiras de move-las para dentro objetos de domínio. Principalmente porque algumas dessas regras são validações complexas da associação entre certos objetos e implicam em acessos a um ou mais Session Beans para executar métodos de pesquisa.

Parece-me mais adequado deixar em Session Beans regras de negócio que tenham um impacto mais global sobre a aplicação, como por exemplo um controle de saldos de estoque:
Supondo que tivéssemos um objeto que representasse um lançamento de estoque (débito ou crédito) poderíamos ter um Session Bean com um método addLancamento que além de cuidar da persistência do objeto poderá fazer um cálculo de preço médio para um produto associado ao lançamento.
Isso porque um “estoque” é algo de certa forma “global” no sistema. Qualquer aplicação cliente poderá acessar o Session Bean do estoque para obter o saldo atual de um produto.

Podemos então, ver que existem outras regras que ficam “isoladas” nas instâncias dos objetos a que dizem respeito. Por exemplo: Se para adicionarmos um objeto produto a um objeto venda precisamos verificar antes a sua disponibilidade de estoque, esse código poderá ser colocado no próprio objeto venda (que obviamente acessará o Session Bean do estoque para consultar). Essa verificação diz respeito somente a uma venda, e não interessa para a aplicação como um todo. Esse objeto venda só terá um impacto maior quando for persistido por um método de um outro Session Bean que também vai se encarregar de criar lançamentos de estoque correspondentes (de débito) e adiciona-los ao estoque usando o método addLancamento que comentei antes.

Bem … apesar desse raciocínio todo ter uma certa lógica, não consigo imaginar que outros tipos de regras eu conseguiria encaixar nos objetos de domínio além das mais diversas validações que podem existir em um sistema.

São muitas as divagações possíveis à cerca desse assunto, e por isso termino esse post aqui.

Comentários serão muito bem vindos.

[]’s
Gabriel C. Oliveira

cv1

Gabriel, esqueca um pouco a historia dos Session Beans (isso é detalhe de implementação, afinal, basta dizer que é um objeto remoto, ou um “serviço”).

O importante, no seu caso, é determinar quais operações devem ser executadas no servidor (consumindo, assim, mais CPU e menos rede) e quais devem ser executadas no cliente (consumindo menos CPU e mais rede). Geralmente, as operacoes mais legais de se executar no cliente sao aquelas curtinhas, meio-do-caminho, como adicionar um produto a uma venda que ainda nao foi finalizada. A operacao de finalizar a venda, no entanto, eh algo ideal para se fazer no servidor: alem de vc ter a chance de persistir tudo de uma vez, comitar a transacao e ainda fazer mais umas continhas no meio do caminho, vc economiza bastante no quesito largura de rede, e ainda deixa o usuario trabalhar com o sistema caso haja algum problema com o servidor.

Me parece que vc esqueceu de desenhar o “estoque” como um objeto de dominio… será? :smiley:

gcobr

Bem, entendo …

Na verdade o meu objeto de domínio para o estoque seria o próprio EJB. Mas eu também poderia criar um objeto de domínio no mesmo nível dos demais que internamente usaria o EJB para executar as suas operações.

[]'s
Gabriel C. Oliveira

gcobr

Sinto que esse tópico ainda vai mais longe.

Uma vez que tenhamos um domínio de objetos rico, com uma quantidade significativa de regras de negócio que não fossem implementados na forma de EJBs, mas ao contrário disso fizessem uso de EJBs de sessão e outros em um servidor de aplicação qualquer, como ficaria a “plugabilidade” de diferentes interfaces com o usuário?

Se tais objetos de domínio estiverem dentro de uma aplicação cliente Swing por exemplo, não estaríamos unindo as regras de negócio à interface? Ou seria o caso de pensar em uma 4a. camada?

Por outro lado … se não tivéssemos o domínio de objetos próximo da interface, seria difícil implementar um MVC com eles, seja para uma interface Swing, ou seja para Web …

Entre tantas divagações, começo a pensar ser utópico um cenário onde a interface possa ser totalmente separada do domínio de objetos.

Alguém concorda?

cv1

Reescreva isso como:

“Se tais objetos de dominio forem usados dentro de uma aplicacao cliente Swing por exemplo, nao estariamos unindo as regras de negócio à interface?”

E a resposta fica clara dentro da própria pergunta: não, a UI é apenas cliente dos servicos oferecidos pelo domínio. :wink:

http://www.guj.com.br/forum/viewtopic.php?t=11438 :smiley:

Criado 14 de abril de 2004
Ultima resposta 23 de abr. de 2004
Respostas 31
Participantes 9