.NET

9 nov, 2010

MVP & ASP.NET – Introdução ao Passive View

Publicidade

O padrão inicialmente chamado de Thing-Model-View-Editor foi criado pelo norueguês Trygve Reenskaug. Pode até soar meio estranho, mas esse foi o primeiro nome dado ao super popularizado MVC. Ele foi concebido para atender ao Smalltalk, que é uma linguagem de orientação a objetos criada na década de 70 pela empresa Xerox.

Desde a sua concepção até hoje, surgiram várias variações, como o AM-MVC, Model2 e o próprio Microsoft MVC, que nada mais são do que herdeiros (variações) do MVC clássico.

Nos anos 90, a Smalltalk entra em cena novamente e, através de uma pesquisa para obter a melhor arquitetura para sua nova geração de frameworks (denominada Dolphin Smalltalk), chega até uma publicação feita por Mike Potel. Tratava-se de um novo padrão criado para a IBM, chamado MVP. Logo após realizar algumas adaptações no MVP, a Smalltalk chega à outra variação, o agora então MVP simplificado.

No ano de 2006, Martin Fowler apresentou duas novas variações do “Dolphin MVP”, que estavam categorizadas como MVP Passive View e o Supervising Controller.

Em especial neste artigo, abordaremos o MVP Passive VIEW, a variação que atualmente tenho utilizado. Esse padrão é dividido em três entidades Model-View-Presenter:

  • View é a responsável pela interação com o usuário (GUI), onde ocorre a requisição de entrada e saída de dados. No caso de uma aplicação ASP.NET, é onde estará o HTML, o TextBox, o CheckBox, o GridView… Se implementado da forma correta, você pode perfeitamente reutilizar o mesmo projeto para outras tecnologias de apresentação, assim como Windows Forms, Silverlight e WPF.
  • Presenter é a entidade intermediária, ou seja, ela se responsabiliza pelo meio campo entre a VIEW e a MODEL (na variação do MVP Passive View, a view não se comunica com a model e ao menos sabe existência da mesma). Além de intermediar as entidades VIEW e MODEL, a Presenter é também responsável pela lógica de apresentação, por exemplo, manipular uma propriedade booleana que determina se um campo estará habilitado ou desabilitado.
  • Model se preocupa com a manipulação das entidades responsáveis pelo domínio e pelas regras de negócio da aplicação, onde devemos efetuar a persistência de dados, serviços e lógica de negócio. Como por exemplo, a validação de um CPF, a inserção de um novo registro no banco de dados, a comunicação com WCF.

Observe no diagrama abaixo como ocorre a comunicação entre as entidades:

Implementação

Para obter um melhor entendimento sobre a implementação do pattern, iremos criar uma aplicação ASP.NET simples, ela será composta por uma única tela onde o usuário poderá consultar clientes e manipular registros de um cadastro de clientes. Acompanhe na imagem abaixo a estrutura da aplicação:

Note que, além do MVP, nós implantamos outros padrões de projeto de software. Padrões que estão armazenados no modelo da aplicação e que fortificam ainda mais o conceito de separação de responsabilidade.

  • DAO: a idéia é que a lógica de negócio deva permanecer ignorante quanto à tecnologia utilizada para acessar o banco de dados. Permite que você mude facilmente de tecnologia, nesse exemplo estamos utilizando Entity Framework, mas com pouco esforço poderíamos mudar para LINQ to SQL.
  • Factory: através desse padrão nós podemos centralizar a criação de objetos da DAO, facilitando o acesso a esses objetos, trazendo mais dinâmica a nossa aplicação e abstraindo ainda mais a DAO, sendo que os objetos não precisarão ser explicitamente instanciados toda vez que requisitados.

Não vou me prender muito a esses conceitos, o foco do artigo é o padrão MVP Passive View. A primeira etapa que deve ser realizada é criar uma abstração para User Interface do projeto. Todo WebForm terá sua própria interface que será a responsável pela comunicação com o apresentador. Ao abstrair os detalhes do modo de exibição para essa interface, o MVP torna o Presenter altamente reutilizável e testável.

O diagrama acima exibe o mapeamento gerado pelo Entity Framework, com base nele podemos vislumbrar as estruturas da Web.UI e a interface responsável pela abstração da ViEW.

Não quero ser repetitivo, mas gostaria de deixar ainda mais claro o conceito, de que é fundamental que a interação entre a Presenter e a UI seja estabelecida através de contratos. Cada botão clicado e cada campo preenchido devem ser encaminhados à Presenter, que é a responsável pela lógica de apresentação.

Ex.: A sua Presenter precisa popular uma DropDownList ou então obter uma lista de itens selecionados nessa mesmaDropDownList. Para isso, devemos implementar um método na interface que será o responsável por fornecer essa transação.

Abaixo, a tela criada para atender ao cadastro de clientes. Como mencionado anteriormente, utilizaremos ASP.NETWebForms como UI, a mesma Presenter funcionaria perfeitamente com WindowsForms, WPF ou Silverlight.

Em alguns casos, as propriedades da interface são implementados como wrappers de propriedades de controle. Por exemplo, a propriedade Nome da interface é um wrapper para a propriedade Text do TextBox txtNome. Acompanhe na imagem abaixo:

Os controles têm como objetivo capturar as requisições feitas pelo usuário através de eventos, assim como um click em um botão, ou então a seleção de um novo item no DropDownList. Através desses eventos devemos efetuar chamadas aos métodos responsáveis pelo tratamento adequado da UI. Para isso, implementaremos um objeto privado da presenter, que será instanciado no método Page_Load do WebForm.

O apresentador possui uma série de métodos que são executados em resposta às solicitações feitas pelo usuário através da UI disponibilizada. Qualquer ação que usuário executar deve estar acoplada a um método da classe do apresentador. Nesse caso, essa classe chama-se ClientePresenterDetails.

O construtor do apresentador receberá e armazenará em cache a referência para a abstração do Web.UI. Esse construtor também é responsável por instanciar os objetos contidos em nosso modelo. Sabemos que a nossa VIEW não consegue enxergar o modelo, então o construtor deve ser sobrecarregado. Se você observar o code-behind do WebForm, perceberá que a aplicação está de fato utilizando sobrecarga.

O apresentador é quem fará a comunicação com o modelo, como por exemplo a consulta de um cliente cadastrado. Um bom exemplo é o evento OnSearch, ele é responsável por ir até a DAO e fazer a pesquisa de clientes pelo nome informado. Acompanhe no código abaixo.

Caso a pesquisa de clientes obtenha êxito, o evento OnSearch deve invocar o método PopulateForm, que é o responsável por popular o formulário com as informações obtidas sobre o cliente.

Conclusão

O MVP irá lhe exigir algumas linhas de código a mais e certo nível de conhecimento para implementá-lo da forma correta. Em contrapartida, as entidades possuem suas responsabilidades muito bem esclarecidas, além do fato de o apresentador ser independente e isolado da UI, o que lhe permite obter um nível satisfatório de testes em sua aplicação mesmo utilizando WebForms.

Como profissional, me considero ainda imaturo no âmbito da arquitetura de software, e espero que o material tenha ficado no mínimo esclarecedor.  Para entender ainda mais sobre o padrão, você pode baixar o código fonte da aplicação e acompanhar o funcionamento.

Referências:

Requisitos:

  • Visual Studio 2008 SP1
  • Framework 3.5 SP1

Segue o código-fonte para download.