MVC em aplicativo Desktop

Colegas, dá para implementar o padrão MVC em um aplicativo Java Desktop? Como fazer?
Alguém conhece algum exemplo simples?

O Swing em si já implementa o MVC.

Model: Casses como TableModel e ListModel
Controler: Tratado pelos Listeners
Views: Componentes Visuais como ComboBoxUI.

O Swing encapsula isso criando as Classes J… como JComboBox e JTable.

Cara, até que dá…
Conforme o tamanho da aplicação, não importa o meio, desktop ou web, você acaba tendo que usar essas metodologia e outras, para organizar as coisas e separar as regras de negócio.

Mas a única forma que conheço de fazer isso em desktop é na mão. Não sei se existe um framework para isso (como acontece com JAVA EE).
Deve existir alguma coisa… dá uma procurada.

[quote=marcelo.garces]O Swing em si já implementa o MVC.

Model: Casses como TableModel e ListModel
Controler: Tratado pelos Listeners
Views: Componentes Visuais como ComboBoxUI.

O Swing encapsula isso criando as Classes J… como JComboBox e JTable.
[/quote]
O Swing é assim, mas acho que ele quis dizer sobre o restante da aplicação.

Geralmente, o modelo MVC é pesado demais para uma aplicação desktop.

A Oracle e a MS recomendam um modelo MVC simplificado, onde model e view ficam juntos:
http://java.sun.com/products/jfc/tsc/articles/architecture/

Isso porque, uma view desktop garante várias coisas que uma view web não garante (validação de campos, acesso correto à view seguinte, etc).

O MVC é um padrão arquitetural que mostra como comunicar a camada de apresentação com o model. Ele não especifica nada sobre como o restante da aplicação deve se comportar. Portanto, só faz sentido falar em MVC a respeito da interação do Swing com os componentes da camada de baixo.

MVC é um padrão de arquitetura de software que independe da plataforma.
O mesmo modelo (model) usado em uma aplicação Desktop pode ser usado em uma aplicação Web, sem necessidade de alterações (pelo menos é como deveria ser).
O controlador (controller) também pode ser usado em diferentes plataformas, sem necessidade de alterações, porém exige uma estruturação para tal coisa.

Abraço.

[quote=ViniGodoy]Geralmente, o modelo MVC é pesado demais para uma aplicação desktop.

A Oracle e a MS recomendam um modelo MVC simplificado, onde model e view ficam juntos:
http://java.sun.com/products/jfc/tsc/articles/architecture/

Isso porque, uma view desktop garante várias coisas que uma view web não garante (validação de campos, acesso correto à view seguinte, etc).

O MVC é um padrão arquitetural que mostra como comunicar a camada de apresentação com o model. Ele não especifica nada sobre como o restante da aplicação deve se comportar. Portanto, só faz sentido falar em MVC a respeito da interação do Swing com os componentes da camada de baixo.[/quote]

Eles até podem recomendar, mas pela minha experiência é melhor separar para uma aplicação grande por dois motivos:

  1. Uma mesma tela pode ser utilizada para visualizar dados diferentes ou até duas telas podem compartilhar o mesmo controlador.
  2. A view por si só se torna gigantesca. Retirando a camada de controle, facilita a manutenção e a expansão.

Para mim (novamente conforme o tamanho da aplicação) a view deve ser responsável apenas pela lógica de visualização.

[quote=andredf]Colegas, dá para implementar o padrão MVC em um aplicativo Java Desktop? Como fazer?
Alguém conhece algum exemplo simples?

[/quote]

De uma olhada no livro Use a Cabeça: Padrões de Projeto! Lá tem um exemplo bem simples de MVC usando Swing!

1 curtida

Aproveitando a pergunta do colega. Alguém tem alguma estratégia para testar o controller e a view?

[quote=x@ndy]
O MVC é um padrão arquitetural que mostra como comunicar a camada de apresentação com o model. Ele não especifica nada sobre como o restante da aplicação deve se comportar. Portanto, só faz sentido falar em MVC a respeito da interação do Swing com os componentes da camada de baixo.[/quote]

Eles até podem recomendar, mas pela minha experiência é melhor separar para uma aplicação grande por dois motivos:

  1. Uma mesma tela pode ser utilizada para visualizar dados diferentes ou até duas telas podem compartilhar o mesmo controlador.
  2. A view por si só se torna gigantesca. Retirando a camada de controle, facilita a manutenção e a expansão.

Para mim (novamente conforme o tamanho da aplicação) a view deve ser responsável apenas pela lógica de visualização.[/quote]

Sua experiência é com desktop?
Trabalhei por 6 anos com uma aplicação gigantesca em Swing e nunca senti falta.

Em boa parte das aplicações, é bastante raro duas views distintas compartilharem o mesmo controlador. Geralmente, o que acaba acontecendo, é que views terão diversos métodos específicos. Ainda que o compartilhamento ocorra, há soluções orientadas a objetos e bastante elegantes em Swing para evitar duplicação de código: Criação de componentes, Documents, criação de classes auxiliares e classes model (que no fundo, são controladores). O fato da aplicação desktop ser em geral monolítica, e não depender de comunicação roundtrips com servidores torna isso possível

Não concordo que retirar a camada de controle facilita a manutenção. A inserção de uma camada intermediária praticamente sem função enche o projeto de arquivos praticamente mortos. Boa parte da tarefa de implementar um controle em aplicações desktop é meramente burocrática.

Claro, se sua aplicação tem como característica compartilhar views, como no caso de ter várias telas similares para tipos de usuários distintos, ou se você usa um servidor de aplicação com RMI e seu desktop é no fundo apenas um frontend, aí sim, justifica separar a camada de controle. Claro, cabe ao arquiteto do sistema analisar e decidir pela melhor opção. É o tipo de resposta que quem pergunta não gosta de ouvir, mas cada caso é realmente um caso.

Eu tendo a preferir usar o modelo simplificado em aplicações desktop monolíticas.

O controller testavamos por TestCases comuns. Estimulavamos os TestCases como se fossemos a view.
Já a parte da View usavamos o Rational Functional Tester. É similar ao AutoIt (embora bem mais pesado), mas funciona com componentes Swing.

Sim, é em desktop.

[quote=ViniGodoy]
Trabalhei por 6 anos com uma aplicação gigantesca em Swing e nunca senti falta.

Em boa parte das aplicações, é bastante raro duas views distintas compartilharem o mesmo controlador. Geralmente, o que acaba acontecendo, é que views terão diversos métodos específicos. Ainda que o compartilhamento ocorra, há soluções orientadas a objetos e bastante elegantes em Swing para evitar duplicação de código: Criação de componentes, Documents, criação de classes auxiliares e classes model (que no fundo, são controladores). O fato da aplicação desktop ser em geral monolítica, e não depender de comunicação roundtrips com servidores torna isso possível

Não concordo que retirar a camada de controle facilita a manutenção. A inserção de uma camada intermediária praticamente sem função enche o projeto de arquivos praticamente mortos. Boa parte da tarefa de implementar um controle em aplicações desktop é meramente burocrática.

Claro, se sua aplicação tem como característica compartilhar views, como no caso de ter várias telas similares para tipos de usuários distintos, ou se você usa um servidor de aplicação com RMI e seu desktop é no fundo apenas um frontend, aí sim, justifica separar a camada de controle. Claro, cabe ao arquiteto do sistema analisar e decidir pela melhor opção. É o tipo de resposta que quem pergunta não gosta de ouvir, mas cada caso é realmente um caso.

Eu tendo a preferir usar o modelo simplificado em aplicações desktop monolíticas.[/quote]

Não gosto de relativar as aplicações. Cada caso é um caso. Normalmente em aplicações maiores é necessário usar. Um exemplo q tenho é de uma apliação que fazia o uso de diversos gráficos. A tela dos gráficos era a mesma embora o controle fosse outro. Nesse projeto a separação era necessária por esse e outros motivos. As variação nas telas era relativamente simples e não envolvia o controller de modo que usavamos o padrão decorator para aplicar essas variações. Isso facilitava muito a expansão do sistema.

Concordo com você que a maioria das views tem um comportamento especifico, mas não concordo que o controller seja sem função. Como disse anteriormente, para mim a view deve ser responsável apenas pela exibição, todas as outras tarefas devem estar no controller e no domain. Claro que para aplicações simples isso não faz sentido (muitas vezes não é necessário nem mesmo o domain). Mas se o controller for praticamente vazio, e sem sentido, isso é sinal que a lógica dele vazou para view. Um jeito bem simples de saber isso é se fazer a pergunta de quantos métodos terão que ser duplicados caso se queira utilizar o controller em outra aplicação.

Em alguns projetos para industria nos quais trabalhei, boa parte dos sistemas de controles das estações eram muito parecidos. O que mudava era basicamente o tipo de informação recebida e numero de passos a serem feitos para coleta das informações. Nessas aplicações muitas vezes eu tinha telas diferentes utilizando o mesmo controlador ou o contrário a mesma tela para controladores diferentes.

Uma das coisas que gosto na separação é que posso simular o funcionamento inteiro do sistema e a validação dos dados sem a view. Eu já uso o junit para testar o cotroller e o domain.
Como a maioria dos projetos que participo a a view quase não tem comportamento, o teste para ela é quase desnecesário, mas vou dar uma olhada Rational Functional Testerview para os casos onde ha necessidade

Nada impede tb que um projeto comece com a junção da view e do cotroller e que a medida que o sistema evolua seja feito uma refatoração para separação das tarefas aonde necessário (caso seja necessário). Eu não adotaria essa estratégia, mas ela não deixa de ser válida também.

Que bom, não estou tão sozinho, rs.

[quote=x@ndy]
Não gosto de relativar as aplicações. Cada caso é um caso. Normalmente em aplicações maiores é necessário usar. Um exemplo q tenho é de uma apliação que fazia o uso de diversos gráficos. A tela dos gráficos era a mesma embora o controle fosse outro. Nesse projeto a separação era necessária por esse e outros motivos. As variação nas telas era relativamente simples e não envolvia o controller de modo que usavamos o padrão decorator para aplicar essas variações. Isso facilitava muito a expansão do sistema.

Concordo com você que a maioria das views tem um comportamento especifico, mas não concordo que o controller seja sem função. Como disse anteriormente, para mim a view deve ser responsável apenas pela exibição, todas as outras tarefas devem estar no controller e no domain. Claro que para aplicações simples isso não faz sentido (muitas vezes não é necessário nem mesmo o domain). Mas se o controller for praticamente vazio, e sem sentido, isso é sinal que a lógica dele vazou para view. Um jeito bem simples de saber isso é se fazer a pergunta de quantos métodos terão que ser duplicados caso se queira utilizar o controller em outra aplicação.

Em alguns projetos para industria nos quais trabalhei, boa parte dos sistemas de controles das estações eram muito parecidos. O que mudava era basicamente o tipo de informação recebida e numero de passos a serem feitos para coleta das informações. Nessas aplicações muitas vezes eu tinha telas diferentes utilizando o mesmo controlador ou o contrário a mesma tela para controladores diferentes.

Uma das coisas que gosto na separação é que posso simular o funcionamento inteiro do sistema e a validação dos dados sem a view. Eu já uso o junit para testar o cotroller e o domain.
Como a maioria dos projetos que participo a a view quase não tem comportamento, o teste para ela é quase desnecesário, mas vou dar uma olhada Rational Functional Testerview para os casos onde ha necessidade

Nada impede tb que um projeto comece com a junção da view e do cotroller e que a medida que o sistema evolua seja feito uma refatoração para separação das tarefas aonde necessário (caso seja necessário). Eu não adotaria essa estratégia, mas ela não deixa de ser válida também.[/quote]

No caso nós faziamos o teste em cima do Model. Como as chamadas do model pela view ficam bem simples em desktop, não achavamos tão diferente assim. Realmente, cada caso é um caso e os seus parecem bem justificáveis.

Nossa aplicação era mais próxima de uma IDE, com alguns cadastros auxiliares. Era grande, mas as telas eram bastante independentes. Os poucos exemplos onde tinhamos compartilhamento de dados, usavamos ali uma classe mediadora. Atuava como um controlador simples.

Me parece que em desktop é possível abrir mão do controller, fica mais a gosto da equipe, analisando o sistema a ser desenvolvido. Numa aplicação web, eu consideraria completamente inviável. Como na view não podemos confiar na interface de entrada dos dados, seria insanidade não ter um controler tratando eventos, validando entradas e roteando corretamente os dados para o model.

Ah sim, é importante ressaltar que abrir mão do controller != abrir mão de estrutura. Você ainda deve ter um model bem configurado, ainda deve evitar duplicação de código com mediadores, herança visual, componentização e outros estratégias similares. É importante não confundir não usar o controller com fazer tudo na view!

Humm…

Como a maioria das minhas aplicações são para controle de equipamentos e isso exiger muitas vezes tem uma sequencia de passos a serem executadas o unico jeito de garantir a integridade nos testes era criar um Service que realiza-se a validação dos dados de entrada e e executasse a a respectiva sequencia de chamadas ao dominio. Esse service se torna o meu controller, na maioria das vezes.

Isso, no meu caso, facilita os testes e a expanção pois consigo fazer tudo indepentende da view.

Nos casos de cadastros, eu não faço isso, ai eu retiro o controller, pois fica mais fácil refatorar o código depois caso necessário. Isso torna o sistema mais simples.