sábado, 12 de dezembro de 2009

Considerações Históricas sobre o Padrão MVC

Este post é o primeiro de uma série de traduções de artigos do blog Design Codes, que falam um pouco sobre a evolução do padrão MVC desde o final dos anos 70, até chegar aos dias de hoje, momento em que uma de suas variações - o MVP - está se popularizando, tendo inclusive sido citado como uma best practice no Google I/O 2009 para o desenvolvimento de aplicações GWT

A História do Padrão MVC (Model View Controller)

Neste artigo, caminharemos nas duas primeiras fases da evolução do MVC. Iremos revisar o padrão MVC Clássico desenvolvido por Trygve Reenskaug para o Smalltalk no final dos anos 70, e ver como ele evoluiu para o Application Model MVC (a partir de agora referenciado, neste artigo, por AM-MVC; uma tradução conveniente seria MVC com Modelo de Aplicação).

Clique Aqui Clique Aqui Clique Aqui


O Conceito MVC

A idéia por trás do MVC é fazer uma clara separação entre os objetos do domínio (model) e os objetos da apresentação (view/controller). Ele introduz o mecanismo "Observer-Synchronization" para
  • suportar múltiplas apresentações (observadores) de um mesmo conjunto de objetos de domínio (observáveis); e
  • para manter os objetos de domínio completamente desacoplados dos seus respectivos objetos de apresentação.
Este conceito foi largamente experimentado nas últimas três décadas, e mesmo com algumas significativas melhorias que foram introduzidas com o MVP, no final das contas o conceito permanece inalterado.

MVC Clássico

View

Os componentes view são os widgets da tela, podem ser botões, labels, etc. Seu propósito é exibir dados do modelo (usualmente um de seus campos). No MVC Clássico, componentes view se comunicam diretamente com o modelo.
Tenha em mente que estamos falando de widgets dos anos 80, não importando se eles eram clicados por mouse ou pressionados através do teclado.

Controller

Um controller é a entidade lógica que sempre tem uma view (widget) como par. Ele processa a entrada vinda dos dispositivos como teclado e mouse, e comanda o modelo conforme apropriado. O controller também se comunica diretamente com o modelo.

Model

O modelo diz respeito aos objetos de negócio que representam o domínio do problema. Geralmente, estes objetos armazenam dados, interagem com bancos de dados e serviços, e lidam com a lógica do negócio. Eles são completamente ignorantes com relação à UI, portanto eles não sabem absolutamente nada sobre a view nem sobre o controller.

Colaboração

O diagrama abaixo mostra como os objetos MVC colaboram entre si. Os objetos no diagrama representam uma UI bem simples, que possui apenas dois widgets (representados pelos pares "view widget"/controller) e um objeto de negócio (representado pelo modelo).
  • O controller recebe as entradas do usuário,
  • Se a entrada for relevante para o seu par widget (view), ele comanda o modelo,
  • O modelo executa alguma operação, altera seu estado, e dispara um evento.
  • O widget (view) responde ao evento, pega os dados relevantes do modelo, e altera a sua exibição.
image_thumb9
O que não é mostrado na figura:
  • A view está acoplada a um método do modelo, de forma que ela possa obter os dados toda vez que houver alguma alteração.
  • O controller e a view podem se comunicar diretamente um com o outro.

    • Nota do tradutor: A view, portanto, está acoplada ao controller, e o controller à view.

Interação

A GUI controle de volume mostrada abaixo tem um único caso de uso.
  • Gatilho: O usuário clica no botão "Aumentar Volume"
  • Cenário Normal: O volume é aumentado em uma unidade e a caixa de texto é atualizada de modo a exibir o volume atual.
A modelagem para esta GUI terá um par view-controller para cada elemento visual (botão, caixa de texto, label) e um objeto modelo para memorizar o volume. O diagrama abaixo mostra como os objetos MVC interagem.

Application Model MVC (AM-MVC ou MVC com Modelo de Aplicação)

À medida que o Smalltalk evoluia, uma nova entidade denominada 'Application Model' (AM ou modelo da aplicação) foi adicionada de modo a proteger o modelo e a view das responsabilidades da lógica de apresentação. O AM age como uma classe intermediária entre o modelo e os objetos da apresentação (view/controller), que deixam de acessar diretamente o modelo (domínio). Ao invés disso, eles acessam o modelo da aplicação (AM), e se registram para os eventos do AM.

Colaboração

  • O controller recebe as entradas do usuário,
  • Se a entrada for relevante para o seu widget, ele comanda o AM,
  • O AM por sua vez, executa alguma operação relacionada à UI, alterando o estado interno da mesma,
  • O AM comanda o modelo, o qual executa alguma operação de negócio, altera seu estado e dispara algum evento
  • O AM responde ao evento do modelo, propagando-o para o widget.
  • O widget responde ao evento do AM, peg os dados relevantes no AM e alterando a sua vizualização

Pra que a mudança?

Vimos que o MVC clássico funciona bem com a GUI do "Controle de Volume". O problema é que na vida real, a UI provavelmete terá casos de uso mais complexos. Para ilustrar, adicionemos um caso de uso a esta GUI: se o volume exceder 12 unidades, então a cor da caixa de texto deve mudar para vermelho. A questão é: quem deve ser responsável por este pedaço da lógica de apresentação?
Podemos empurrar isto para o modelo, de modo que dele dispare algum evento especial quando o limite exceder 12 (mas isso parece inadequado). Podemos extender o widget da caixa de texto, de modo que ela verifique o seu valor e, quando aplicável, altere sua própria cor. Soa melhor, porém ainda é preferível manter os widgets genéricos e ignorantes de qualquer tipo de lógica.
Exatamente por este tipo de situações que o AM foi inventado.
O diagrama abaixo mostra como o AM lida com a nova regra.

  • O usuário clica no botão "Aumentar Volume",
  • O controller comanda o AM para aumentar o volume,
  • O AM delega o comando para o modelo,
  • O modelo comanda o auto-falante e dispara o evento "DataChanged",
  • AM respond and delegate the event to the widget,
  • O widget verifica com o AM qual o volume atual,
  • O AM checa o volume com o modelo, retornando o valor para o widget, que atualiza seu estado.
  • O AM checa se o valor é maior que 12, neste caso dispara um evento ColorChanged, ao qual o widget responde alterando sua cor.
Um benefício de usar o AM é que ele pode armazenar dados da view, como a cor atual do widget, qual item em uma lista está atualmente selecionado, quais widgets estão habilitados ou desabilitados, e assim por diante.

Qual o problema com o AM?

O AM possui uma limitação: ele não tem permissão para manipular sua view diretamente, NÃO pode simplesmente mudar a cor da caixa de texto, ao invés disso, precisa disparar o evento "ColorChanged", e deixar que o widget responda ao evento.
O próximo post, 'Do MVC para o MVP', será mostrado como o Padrão MVP soluciona este problema.

Nenhum comentário:

Postar um comentário