O padrão MVP : Model-View-Presenter


 MVC - Model-View-Controlle é um padrão antigo que prega a separação de responsabilidades do modelo, apresentação e do controle.

Este padrão consagrado é usado em muitas frameworks como Struts e Ruby-On-Rails, WPF, ASP .NET MVC, etc. para citar os atuais.

Se você procurar na web vai encontrar toneladas de exemplos com um detalhe, a grande maior para aplicações web.

Isso quer dizer que não podemos aplicar o padrão para outros tipos de aplicações ? Claro que podemos.

Procurando preencher esta lacuna este artigo vai apresentar os fundamentos do padrão MVP - Model-View-Presenter.

Não eu não me enganei, estava falando do padrão MVC e terminei dizendo que iria usar o padrão MVP - Model-View-Presenter.

E porque MVP e não MVC ?

A idéia do MVP é que toda a lógica que normalmente iria ligar a interface do usuário com os dados seja movida para uma classe separada. No padrão MVP, a interface do usuário não possui processamento algum.

"Imagine uma janela que sirva para cadastrar clientes no sistema. É agrupado um conjunto de diversos tipos de controles visuais (View) que representam uma lista de objetos Cliente no sistema (Model). O resultado da interação do usuário com a janela é traduzido em eventos (Controller), que controlam o fluxo da aplicação e modificam o estado dos controles da janela, atualizando também os objetos de negócio.

Na maioria dos casos, o código responsável pelo tratamento dos eventos e controle de fluxo da Janela fica dentro de uma mesma classe. Temos então uma quebra de camadas: a View não deve conhecer nem o modelo que representa e nem a lógica de apresentação, já que temos alguns tipos de ação na lógica de apresentação que são regidas pelo domínio do problema em questão. Outro problema de manter tanto o código de montagem da tela quanto o tratamento de eventos é uma classe extremamente grande, difícil de manter, difícil de expandir e com código de impossível reutilização.

A diferença entre o MVC e o MVP fica basicamente no conceito, já que as funções do Controller do MVC são semelhantes ao Presenter do MVP.

Imagine novamente o exemplo do cadastro de clientes. O Model é a coleção de objetos Cliente que são manipulados pela janela. A View é a janela propriamente dita. O Presenter é responsável por interceptar os eventos gerados na View, com a finalidade de controlar a lógica de apresentação.

Portanto, foco principal do MVP é separar a lógica de apresentação da apresentação em si."  (Apresentando Model-View-Presenter, o MVC focado na visualização - JavaFree.org)

Portanto o padrão MVP - Model-View-Presenter é um padrão de projeto 'derivado' do padrão MVC criado para separar a lógica da apresentação da apresentação propriamente dita e a realização dos testes unitários, onde:

O componente Model corresponde aos objetos que contêm a lógica do negócio sendo que esse componente não conhece nada acerca da apresentação e deve expor interfaces de forma abstrata e não de forma concreta. Com isso temos a simplificação dos testes com objetos Mock  e o isolamento da implementação do modelo.

Mock objects são objetos que simulam o comportamento de objetos reais de forma controlada. São normalmente criados para testar o comportamento de outro objeto.

Em testes unitários, mock objects podem simular o comportamento de objetos reais complexos e são, portanto, muito úteis quando os objetos reais são difíceis de criar ou impossíveis de serem incorporados no teste de unidade.

Por exemplo, em um teste para um objeto que faz uma chamada remota é necessário que do outro lado exista um previsão para a chamada. Neste caso, em vez de usar o objeto real que faz a chamada, usa-se um mock object que simula o comportamento do objeto real.

O componente View é uma estrutura composta de controles de interface com o usuário e não contém nenhum comportamento que descreve como os controles reagem à eventos de sistema (ações do usuário). A reação às ações do usuário é posicionada em um objeto separado, o componente Presenter.

O Presenter decide como reagir ao evento notificado pelo componente View e essa reação, de forma geral, corresponde ao envio de mensagens aos objetos do Model. Conforme o Presenter atualiza o modelo, o componente View é atualizado.

Obs: Os manipuladores para as ações do usuário ainda existem nos controles da interface do usuário eles apenas passam o processamento para o Presenter.

Esquema do MVP

Na figura acima podemos observar que o View e o Model estão claramente separados (não conhecem nada um sobre o outro) e o View expõe uma interface para comunicação do Presenter com o View fazendo com isso que o Presenter não saiba nada sobre a camada de interface usada. Da mesma maneira o Presenter atua sobre o Model e pode invocar suas operações.

Observe que cada objeto Presenter possui exatamente uma referência para um objeto View e cada objeto View possui exatamente uma referência para um objeto Presenter e que existe um objeto Model para toda a aplicação. Com base nisso, é necessário definir uma interface e um Presenter para cada objeto View da aplicação.

Dessa forma no MVP, o Presenter contém a lógica do negócio da view e todas as chamadas da view são delegadas diretamente para o Presenter.

O Presenter também é desacoplado diretamente da View e a comunicação entre View e Presenter é feita através de uma interface. (Com isso podemos ter o mocking da view em um teste unitário.)

Martin Fowler catalogou o padrão MVP na forma de dois padrões distintos:

Diferenças entre MVC e MVP

Fonte: http://www.mvcsharp.org/Overview/Default.aspx

- No MVC, o controller é o responsável por determinar qual View será exibida em resposta a qualquer ação incluindo quando a aplicação é carregada.

- No MVP as ações são roteadas através da View para o Presenter.

- No MVC, o View se comunica (no sentido de poder enviar mensagens) com o Model.

- No MVP, o View pode conhecer o Model, mas não envia mensagens para ele.

Prós e Contras
Prós :
 -  Já que a lógica não está atrelada à interface do usuário, o MVP facilita a utilização de um framework de testes;
-   Posiciona o código em seu lugar apropriado;
-   Aumenta o reuso do modelo de domínio;

Contras:
- Mais código para implementar;
- A Curva de aprendizado é mais acentuada;
Conclusão:
Vou concluir com a seguinte frase : "Bom senso e canja de galinha não fazem mal a ninguém..." 

Você nunca deve adotar uma tecnologia por que esta na moda ou por que todo mundo esta usando, use o bom senso e verifique se realmente tal tecnologia irá tornar o seu projeto um sucesso. Tenha paciência e faça uma análise detalhada levando em conta todos os aspectos envolvidos no seu projeto, afinal o que é bom para a maioria pode não ser bom para você.

Simples, simples assim...
Referências:

José Carlos Macoratti