Neste post especial da série de padrões de projeto, vamos analisar o tão conhecido padrão Model-View-Controller (MVC).
Este post será um pouco diferente dos outros da série, pois não vamos construir um exemplo real de utilização do padrão MVC, mas vamos analisá-lo sob o ponto de vista de vários frameworks em várias linguagens.
Problema:
Imagine que você trabalha em um projeto de uma loja online, nele é necessário que os clientes possam acessar o site da loja utilizando um desktop ou um dispositivo móvel. Também é necessário que a equipe que controla a parte operacional da loja acesse informações de estoque, para isso utilizando um aplicativo desktop para controle de estoque entre outras atividades. Além disso, também será necessário que o serviço da loja seja integrado com outros sistemas da empresa, precisando assim de comunicação através de XML ou JSON.
Ao analisar o problema, é fácil perceber o alto nível da questão. Não basta apenas analisar um conjunto de classes e resolver o problema. Este é um exemplo de um problema arquitetural, pois as decisões vão implicar em alterações em vários outros locais do projeto. Por isso é que o padrão MVC é tido como um padrão arquitetural e não de design, como são os outros padrões da série Mão na Massa.
Voltando ao problema, analisando melhor é possível perceber que o banco de informações é praticamente o mesmo para as várias aplicações, no entanto a lógica do negócio e como os dados serão exibidos é bem diferente entre os aplicativos. O site do cliente precisa gerenciar carrinhos de compra, o site mobile precisa de algumas pequenas alterações no seu visual para se adaptar ao dispositivo e, da mesma forma, os outros aplicativos precisam sofrer alterações para o seu ambiente.
Quem acompanhou a série de posts sobre padrões de projeto deve ter visto o padrão de projeto Observer, se você não o conhece, dê uma olhada no post depois. Poderíamos utilizar o padrão Observer para centralizar o conjunto de dados e oferecer várias visões diferentes, de acordo com os aplicativos. No entanto o Observer não possui uma abrangência que possa ser estendida ao domínio do nosso problema, por isso vamos ver agora o padrão MVC.
Model View Controller (MVC)
A estrutura básica do MVC é também semelhante a do Observer:
O MVC busca organizar o projeto de uma maneira que facilite a reusabilidade e manutenção, e bons frameworks que utilizam o padrão MVC irão melhorar ainda mais esta capacidade.
Na camada de Model, ficam as classes que fazem a comunicação com o Banco de Dados, representando estas informações. A camada de Controller é responsável por gerenciar eventos e acionar as classes de modelo para realizar alterações nas informações. A camada View então vai exibir os novos dados do Model ao usuário.
Ao utilizar o padrão, alterações ficam contidas nas suas camadas, ou afetam o mínimo possível outras camadas. No exemplo do problema citado acima, as classes de modelo e controle seriam as mesmas para o site desktop e o site mobile, a única diferença seria na camada de visualização. Já o controle de estoque dos produtos aproveitaria a camada de modelo para extrair as informações necessárias ao seu setor.
O fluxo MVC vária de acordo com a implementação de cada framework, no entanto geralmente ele segue o esquema [1]:
- O usuário interage com a interface
- O controlador gerencia os eventos da interface, invocando uma ação apropriada
- O modelo é notificado da ação, alterando o estado do modelo
- A visão é notificada da alteração e é atualizada
Apesar do fluxo ser bem parecido com o do padrão Observer, as implementações do padrão MVC oferecem uma série de recursos a mais, tornando o MVC mais geral. Vamos ver então como alguns frameworks implementam o padrão MVC.
MVC e os Frameworks
O framework Rails, como falado neste post, utiliza Helpers, que são classes com métodos auxiliares, e Partials, que são “pequenas views” que podem ser renderizadas em vários lugares para permitir reaproveitamento de código.
Já o Spring Web MVC (framework Java) segue uma abordagem um pouco diferente [2]:
Pela imagem podemos ver que o Front Controller centraliza as chamadas e delega as responsabilidades de requisições, renderização, etc.
A implementação do Django (framework Python) possui nomenclaturas diferentes e um fluxo um pouco diferenciado [3]:
O Django utiliza o Model-Template-View, pois no framework uma View contém as regras de negócios, quais modelos serão utilizados, etc. A view do Django define apenas quais dados serão mostrados, e não como estes dados serão exibidos. Esta é a responsabilidade dos Templates, que apresentam os dados da View em vários formatos, como HTML, Javascript, XML, etc. Dai a diferença entre View e Templates.
Já o CodeIgniter possui uma implementação mais “pura” do padrão MVC [4]:
O esforço do framework é separar os códigos PHP e organizá-los de uma maneira que facilite a reusabilidade e a manutenção do sistema, evitando assim aquelas páginas que contém regras de negócio, acesso ao banco e código Javascript no mesmo arquivo.
Se gostou do post compartilhe com seus amigos e colegas, senão, comente o que pode ser melhorado. Encontrou algum erro no código? Comente também. Possui alguma outra opinião ou alguma informação adicional? Comenta ai! 😀
Referências:
[1] http://en.wikipedia.org/wiki/Model–view–controller
[2] http://static.springsource.org/spring/docs/2.0.x/reference/mvc.html
[3] http://www.profissionaisti.com.br/2009/04/entendendo-o-django/
[4] http://codeigniterbrasil.com/passos-iniciais/mvc-model-view-controller/
Primeiro comentário: MVC não tem a ver com camadas, são responsabilidades de entidades que vivem em diversas camadas ou em uma mesma camada, mais sobre o assunto http://www.milfont.org/tech/2008/09/08/mvc-model-3-e-camadas/
Segundo comentário:
Não existe implementação “pura” de MVC quando se trata de WEB, o MVC original era ligado a propria arquitetura do desktop, na web chamamos de MVC Model 2 que é uma frágil implementação sobre – principalmente – HTTP ou protocolos de comunicação.