Introdução
Nesse artigo iremos abordar um padrão de projeto muito interessante, o MVC (Model, View, Controller). Quem nunca criou um "sistema-linguiça", aquele que tem meia duzia de arquivos e cada arquivo faz tudo, processa, acessa banco, mostra resultados na tela e estoura pipoca, que atire a primeira pedra! É muito comum fazermos esse tipo de programação quando estamos começando a desenvolver, geralmente são classes “Bom-Bril”, mil e uma utilidades, todas amarradas com scripts SQL misturados com tomadas de decisões e apresentações gráficas, um caos na hora de dar manutenção, parece um castelo de cartas. Tudo bem, e o que o MVC tem a ver com isso? O quê? Eu te explico!
Segundo Erich Gamma, "A abordagem MVC separa Visão e Modelos pelo estabelecimento de um protocolo do tipo inserção/notificação (subscribe/notify) entre eles. Uma visão deve garantir que a sua aparência reflita o estado do modelo"
O padrão MVC coloca ordem nisso tudo, estipulando regras de separação do código de acordo com as funcionalidades, distribuindo a aplicação em camadas e fazendo com que elas sejam o mais independente possível umas das outras.
Exemplo modular
Por exemplo, você pode fazer uma aplicação que se baseia em: receber um valor, processar e retornar uma resposta, sem salvar nada em banco de dados nem exibir graficamente. Agora imagine que você resolva acoplar a esse sistema um modulo que salve no banco de dados o resultado do processo e depois outro módulo para exibir o resultado com interface gráfica. Se isso não for bem estruturado, pode lhe dar uma tremenda dor de cabeça para implementar e outra maior ainda para dar manutenção.
Analogia com o mundo real
Uma analogia do MVC com o mundo real poderia ser o funcionamento de um carro. No carro temos o motor que faz o processo principal, gerar força mecanica. Temos também os pedais e câmbio de marchas. Além disso, temos o painel de controle do carro que exibe informações de como está o seu funcionamento, como temperatura, pressão do óleo e medidor de rotação do motor.
Colocando o exemplo do carro no padrão MVC temos a seguinte estrutura:
O motor do carro é certamente a camada model, pois se trata do núcleo da aplicação (carro), exercendo o maior trabalho.
Os pedais, cambio e painel fazem parte da camada view, embora o painel seja diferente dos pedais e câmbio já que é responsável em exibir dados e os outros em colher dados (interação com o usuário).
Agora imagine, já temos o motor e os elementos de interação com o usuário mas está faltando algo. Se não houvesse nada entre esses elementos e o motor, nada aconteceria, você poderia pisar o quanto quisesse no acelerador, trocar qualquer marcha que nada aconteceria, o painel seria apenas um monte de ponteiros e luzes que não funcionariam para nada. É nesse ponto que entra a camada de controller. Essa camada corresponderia aos sensores de temperatura, de rotação do motor e de pressão do óleo do motor, responsaveis em fazer a interação entre a camada model e a view, fazendo com que a pressão exercida nos pedais interfira no funcionamento do motor e que o painel mostre o estado do motor.
Estrutura MVC
A estrutura básica do MVC é a seguinte:
- Model
- Value Object
- Business Object
- Data Access Object
- View
- Controller
Esquema MVC
Se você encontrar outras estrutura MVC's diferentes mundo a fora, não se assuste, afinal de contas futebol, religião e MVC são difíceis de se encontrar o melhor e o pior.
Na próxima parte do artigo iremos por a mão na massa e desenvolver um "pequeno" sistema que irá usar todas as camadas faladas aqui, além de explicar a fundo a camada model e suas integrantes.
Camada model
Explicado todos esses conceitos, vamos agora falar da principal camada da aplicacação, a camada model. Como vimos anteriormente, ela é dividida em três tipos de classes, As Value Objects, Business Object e Data Access Object. Sua função é prover todas as funcionalidades do software independente de interação com o usuário ou parte gráfica.
Value Objects (VO)
Os objetos de valores (Values Objects) são classes que contém variáveis e metodos de acessos, além de construtores. Um exemplo desse tipo de classe seria assim:
01 | package br.com.gqferreira; |
02 | public class Pessoa { |
03 | //Variaveis |
04 | private String cpf; |
05 | private String nome; |
06 |
07 | //Construtor |
08 | public Pessoa(String cpf, String nome) { |
09 | this .cpf = cpf; |
10 | this .nome = nome; |
11 | } |
12 |
13 | //Get and Set |
14 | public String getCpf() { |
15 | return cpf; |
16 | } |
17 |
18 | public void setCpf(String cpf) { |
19 | this .cpf = cpf; |
20 | } |
21 |
22 | public String getNome() { |
23 | return nome; |
24 | } |
25 |
26 | public void setNome(String nome) { |
27 | this .nome = nome; |
28 | } |
29 | } |
Objetos de valor tem a função de modelar uma entidade, uma abstração do mundo real. Por exemplo a classe pessoa, precisa conter todos os atributos que lhe interessar a respeito de uma pessoa. Esse tipo de classe é muito utilizado para representar uma tabela do banco de dados, por exemplo, se você tiver uma tabela de cliente, precisará de uma classe desse tipo com os mesmos atributos que contém na tabela do banco de dados. É muito mais organizado e reutilizável trafegar todos os atributos encapsulados dentro de um objeto do que passar uma "enchorrada" de variáveis de um canto ao outro.
Os metodos de acesso (Get and Set) servem para garantir uma flexibilidade na hora de impor alguma regra no acesso aos atributos, embora você talvêz nunca utilize-os. Por exemplo, digamos que hoje o método getNome() apenas retorne o valor da variável nome e é exibido na tela. Derrepente você decidiu que todo mundo terá o título de Sr. e quer implementar essa regra, basta ir ao método getNome() e mudar o retorno assim:
1 | public String getNome() { |
2 | return "Sr. " +nome; |
3 | } |
Pronto, você acaba de impor uma regra no acesso ao atributo nome e poderá fazer isso em qualquer outro método.
Você pode dar o nome que quiser para seus métodos de acesso à atributos, poderia ser obtemNome() e defineNome() que iria funcionar do mesmo jeito, porém existe uma padronização em utilizar os prefixos get e set.
Com o uso do construtor fica mais "elegante" criar um objeto, por exemplo, em qualquer lugar que precisar de uma instância de Pessoa, basta fazer assim:
1 | Pessoa p = new Pessoa( "430.376.565-14" , "Joaquim da silva" ); |
Dessa forma você terá um objeto da classe Pessoa com todos os atributos já com valores definidos e poderá acessá-los a qualquer momento a partir dos metodos de acesso.
1 | Pessoa p = new Pessoa( "430.376.565-14" , "Joaquim da silva" ); |
2 | System.out.println(p.getNome()); |
Isso imprimiria no console o nome da pessoa.
Data Access Object (DAO)
As classes do tipo DAO são encarregadas de fazer o acesso à dados, seja eles em um fluxo de rede, arquivo ou banco de dados. Por exemplo, métodos responsáveis em fazer acesso ao banco de dados devem estar nesse tipo de classe, assim como métodos que manipulam arquivos ou que enviam e recebem dados pela rede. Lembre-se, entrada e saída de dados!
Business Object (BO)
Esse tipo de classe também compõem a model da aplicação, assim como os dois tipos de classe ditos anteriormente. A especialidade das classes BO's é resolver operações complexas, são os processos principais da aplicação, digamos que o "miolo" do software. Nessas classes são processadas regras de negócio e tomadas de decisão.
MVC com Java e desktop de Gustavo Ferreira é licenciado sob uma Licença Creative Commons Atribuição-CompartilhaIgual 3.0 Não Adaptada.
Esse artigo é dividido nas seguintes partes:
Comentarios (26) para MVC com Java e desktop
Prezado Gustavo,
Parabéns pelo artigo! Você conseguiu explicar de forma simples, clara e objetiva o que eu vinha procurando entender a muito tempo e com a exemplificação ficou 100% !!!
Abraços,
Augusto
Obrigado, fico feliz que tenha gostado. Sinta-se a vontade para continuar navegando pelos artigos.
Agraços,
Gustavo Ferreira.
Bom Dia, Gustavo. Tenho a seguinte dúvida, e gostaria da sua opinião/visão sobre a mesma:
- Estou desenvolvendo um sistema onde as classes envolvidas não são "Pessoas", "Pedidos", "Itens_Pedido", etc., mas sim "Editor de Textos", "Player de Vídeo", "Player de Áudio" e "Área de Exibição de Imagens". Este sistema deve permitir aos atores gerar seus próprios textos, simultaneamente gravar / reproduzir áudio / vídeo, etc...
Como seria a organização dessas classes em na arquitetura MVC? Quem seriam as classes BO, VO e Controller?
Desculpe-me pela falta de conhecimento, mas deveria eu pensar que este é o desenvolvimento de um "Framework" ???
Agradecendo qualquer esclarecimento,
atenciosamente
Augusto Cesar Nunes
Nesse caso eu imagino que "Player de Vídeo", "Editor de Texto" entre outros possam ser módulos independente, cada um com sua estrutura MVC. Se os módulos precisarem trabalhar em conjunto uns com os outros, você precisará que todos tenham uma ligação com a mesma controller para que as ações de um módulo interfira no outro.
Ou (melhor)...
Não precisam ser módulos independentes. Você pode ter uma DAO para audio (grava e lê), outra para video (grava e lê), uma para texto (grava e lê) e outra para imagens (grava e lê). Uma BO que centraliza os acessos à DAO e que resolva algum processo (conversao de formatos de audio e/ou video, redimensionamento de imagens, efeitos, restrição de acessos, login, logs, etc). Você poderá ter uma view para cada parte do sistema e uma que centralize. Olhe nessa imagem o que imaginei.
As VOs podem ser classes separadas para cada tipo de arquivo a ser salvo, como por exemplo: Audio.java contendo nome, duração, titulo, bytes[], formato, etc...
Muito bom mesmo, agora ficou muito mais claro.
Valew Gustavo.
Boa tarde Gustavo,
Parabéns pelo artigo. Só estou com uma dúvida do projeto todo, e se puder sanar agradeço.
Sabe-se que na camada model se insere as classes do modelo, e que no caso as classes tipo VO apenas tratam de valores. Ate aqui blz, a questão é se na nas classes de BO contém as regras de negócio então o trecho:
public String getNome() {
return "Sr. "+nome;
}
A regra de prefixar o valor "Sr. " antes do nome não deveria ser posta dentro de uma BO ?
Eu entendi o por que tu colocou este exemplo, obviamente para explicar o conceito get e set, mas num cenário real o mais correto seria ter essa regra em uma classe do tipo BO, correto ?
Fico no aguardo.
Misael
Gustavo,
Tenho mais 3 questão relevantes:
1) Em um sistema em que se aplique o MVC, onde (qual o nome da pasta) ficariam arquivos de recurso da aplicação tais como ícones, figuras, imagens, sons, etc ?
OBS: em uma app que tenho aqui de modelo eu criei uma pasta chamada resource para comportar tais arquivos!
2) Na web e até em alguns livros, os arquivos do tipo .jar oriundos de classes de conexão por exemplo MySql em geral são postos em uma pasta chamada lib para serem referenciados pela aplicção no caso inclusos como jar, utilizando o MVC isto estaria correto ou se deveria por em uma pasta com nomeação diferente?
3) Poderia alterar o teu modelo incluindo estas questões ?
Respondendo a primeira dúvida...
A VO é uma classe que também está no pacote model, portanto também possui alguns comportamentos de negócio. E como é uma classe que visa encapsular os atributos, deixar essa regra do "Sr" fora pode por abaixo o encapsulamento. Imagine que a classe Pessoa possa ser instanciada em várias métodos de uma BO, você vai precisar fazer o tratamento do "Sr" idêntico em todos os pontos. Isso acabaria aniquilando também o objetivo dos métodos controladores de acesso (get e set).
As classes do tipo BO devem se preocupar mais com o "algoritmo" da coisa, a engine. Mas você pode criar dois get's, um com tratamento e outro sem, assim, quando precisar alterar o tratamento, todo mundo que utilize esse get será afetado, deixando de afetar aos métodos que optarem por utilizar o get 'puro'
1) Por entender que tais recursos fazem parte da view, eu crio uma pasta de resources dentro do pacote view:
br.com.gqferreira.projectname.view.resources.[images|sounds|videos|icons]
2) Não precisa se preocupar em colocar as bibliotecas na estrutura MVC do teu projeto, até porque internamente cada biblioteca deve possuir a sua própria estrutura, o que dificultaria na hora de julgar se é model, se é controller... se é a DAO da model ou se... enfim, a biblioteca provavelmente é mista. Coloque em uma pasta chamada lib mesmo.
3) O que você sugere que possa ser alterado no modelo?
Obrigado pela atenção,
Gustavo Ferreira.
Boa tarde Gustavo,
Gostei muito desse artigo ,
muito bem explicado e consegui entender de primeira rs ..
sou iniciante e ajudou muito para poder projetar meus projetos
vlw cara ..
Aqui ainda é bom dia Diego rsrs..
Que bom que você tenha achado útil o artigo, fico contente.
Abraços!
Parabéns pelo o artigo tirou varias duvidas porem surgiu outras rsrsrs
no padrao de desenvolvimento web notei em varios tutorias e artigos que muda bastante esses padroes onde entrar como exemplo:
Util
Filter
E o controller precisa conhecer as duas interfaces!? e se uma terceira, quarta , quinta forem adicionadas?
Olá Gustavo, gostei bastante do seu artigo.
Olhá só, estou com um problema, criei 2 classes controller, 1 para controlar um login e outra pra controlar a tela de configuração de conexão com o Banco de Dados.
Quando executo o sistema, a tela de login se abre, aí eu clico no botão para abrir a tela de configuração.
Ao abrir a tela de configuração, quando vou sair dela, dou um dispose() e instancio uma nova classe da controller do login.
O problema é, quando clico em fechar ou pra sair da nova tela de login, a tela somente some, mas o sistema continua em execução.
Como posso resolver isso? Tem alguma ideia?
Obrigado
Parabéns muito bom.
Para quem se interessar, aqui tem outra aplição desktop com netbeans: http://www.memoriacache.com.br/aplicacoes-desktop-com-netbeans-swing/
Olá Gustavo.
Parabéns pelo artigo, esclareceu várias duvidas, mas ainda ficaram algumas.
Por um acaso não teria um exemplo de sistema que grave em banco e valide campos da tela para ter uma ideia não né?
Hoje eu tenho um sistema com uma tela padrão que valida de forma automática os campos, e as minhas telas de cadastro eu herdo ela.
Queria saber como fazer isso usando MVC.
Acredito que eu tendo um exemplo de um sistema que faça algumas validações e grave em banco eu consigo fazer o meu.
Obrigado.
Att,
Sidnei
Muito boa a didática, direta ao ponto e demonstra de forma muito clara. parabéns.
Artigo excelente!! Já pesquisei bastante para obter um exemplo de MVC. De todos que venho pesquisando, considerei esse, o melhor!! Obrigado!! Um abraço!
Me ajudou muito. Ótimo artigo, parabéns!
Otima explicação. Clareou muito para mim.
Olá Gustavo.
Muito obrigado por este artigo, estou começando agora com o MVC, e com esta primeira parte do seu artigo estou apreciando a utilidade deste padrão de projeto.
Muito bom e agradeço pela explicação, procurei bastante como fazer MVC e final achei e bem explícito
Parabéns. Me ajudou muito, o assunto abordado foi muito bem explicado e sanou muitas dúvidas que tinha. Muito obrigado, um grande abraço e sucesso.
Parabéns pelo artigo, depois de pesquisar muito finalmente encontrei um artigo que me fez entender claramente sobre o assunto, ótima didática. Muito obrigada!
Boa tarde Gustavo Ferreira, gostaria de poder utilizar esse artigo em um documento em PDF totalmente didático, sem fins lucrativos que estou desenvolvendo, para ajudar iniciantes assim como eu na programação em Java, utilizando o modelo MVC. Não consegui encontrar em pesquisas explicações tão boas, assim como as suas, se poderei utilizar, deixarei respectivamente a fonte do seu site e uma parte dizendo que o Artigo é de sua autoria e dos demais autores com suas respectivas fontes. Obrigado pela atenção!
Gostou do artigo? Acha que poderia ser melhor em algum ponto? Dê o seu feedback!