Padrão Model View Presenter [email protected] Model View Presenter (MVP) • Padrão utilizado para separar a lógica da apresentação da apresentação propriamente dita. • A idéia do MVP é que toda a lógica que normalmente iria ligar a IU com os dados seja movida para uma classe separada. • Isso significa que a IU (Forms, UserControls, etc) se torna bastante “fina". • No MVP, a IU é “burra” no sentido de que não há processamento embutido nela. Arquitetura MVP Componente Model • O componente Model corresponde aos objetos que contêm a lógica do negócio. • Esse componente não conhece nada acerca da apresentação. – Aspectos positivos: facilita o reuso da lógica do negócio em diferentes contextos (ambientes). – Web, Smart Client, Mobile, WEB Services • Idealmente esse componente, deve expor interfaces de forma abstrata, em vez de concreta. – Simplificação dos testes com objetos Mock – Isolamento da implementação do modelo Componente View • O componente View é uma estrutura composta de controles de interface com o usuário. • Esse componente não contém qualquer comportamento que descreve como os controles reagem à eventos de sistema (i.e., a ações do usuário). • A reação às ações do usuário é posicionada em um objeto separado, o componente Presenter. • Os manipuladores para as ações do usuário ainda existem nos controles da IU, mas eles meramente passam (delegam) o processamento para o Presenter. Componente Presenter • O Presenter então decide como reagir ao evento notificado pelo componente View. • Normalmente, essa reação corresponde ao envio de mensagens aos objetos componente Model. – Composto de classes do domínio e de classes de serviço. • Conforme o presenter atualiza o modelo, o componente view é atualizado. MVP versus MVC • O MVP é uma variante do padrão MVC. • Qual a diferença? – No MVC, o View “conversa” (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 & contras no MVP • Há duas razões principais para usar o MVP: – Evitar a baixa coesão de uma Autonomous View. – Melhorar a testabilidade (essa é a mais convincente). • Se testabilidade automática deve ser usada, isso conta positivamente para retirar o máximo de comportamento permanece do view. • A vantagem da separação é que toda a complexidade comportamental é removida da interface gráfica, tornando esta última mais fácil de entender. • Essa vantagem é “descompensada” pelo fato de que o controlador deve ainda ser fortemente acoplado à tela. – Nesse caso, há um “ponto de interrogação” grande acerca de se vale à pena criar um objeto separado. Prós & contras no MVP (cont) • Aspectos positivos – Já que a lógica não está atrelada à IU, o MVP facilita a utilização de um framework de testes. – Posiciona código de em seu lugar apropriado. – Aumenta o reuso do modelo de domínio. • Aspectos negativos – Mais código para implementar. – Curva de aprendizado é acentuada. Passive View x Supervising Controller • O padrão MVP corresponde na verdade a dois outros padrões: Passive View e Supervising Controller. • A diferença entre os dois está em quanto o componente View tem conhecimento acerca do componente Model. • Quando o View não conhece nada acerca do Model e o Presenter realiza toda a lógica da apresentação, temos o padrão Passive View. • Quando uma parte pequena dessa manipulação é feita pelo View, temos o padrão Supervising Controller. Exemplo Exemplo de View • Esse é o componente View (CadastroDepartamentoView) para a funcionalidade de cadastro de departamentos. CadastroDepartamentoView • public class CadastroDepartamentoView extends JFrame implements ICadastroDepartamentoView • O View aqui é uma subclasse de JFrame (formulário em Swing). • O View deve implementar uma interface com a qual o Presenter irá interagir (o Presenter não interage com o View diretamente, apenas por intermédio dessa interface). ICadastroDepartamentoView public interface ICadastroDepartamentoView { void desabilitarEntrada(); void habilitarEdicao(); void informarErro(String mensagem); void modoAlteracao(); void modoInclusao(); void modoInicial(); void modoVisualizacao(); continua... ICadastroDepartamentoView (cont.) void limparCampos(); void setNome(String nome); void setSigla(String sigla); void setLocalizacao(String localizacao); void setVerbaAnual(Float verbaAnual); String getNome(); String getSigla(); String getLocalizacao(); Float getVerbaAnual(); } ICadastroDepartamentoView (cont.) • Note que ICadastroDepartamentoView não possui detalhe algum acerca da apresentação específica (e.g. Swing ou JSP). • Isso aumenta a portabilidade do Presenter. • O View não conhece o Presenter diretamente, mas notifica este último sobre a ocorrência de eventos de sistema; Instanciação do Presenter • Na sua instanciação, o objeto Presenter recebe o View e os DAO´s de que precisa como parâmetros. • O Presenter é um ouvinte (listener) do View. ... CadastroDepartamentoView form = new CadastroDepartamentoView(); CadastroDepartamentoController presenter = new CadastroDepartamentoController(form, DepartamentoDAO.getInstance()); form.inscrever(presenter); ... Modos do View • O View pode passar por diversos modos (ou estados). • Em cada estado, a aparência e o comportamento do View são diferentes. • Esses estados se refletem em operações: – – – – void modoAlteracao(); void modoInclusao(); void modoInicial(); void modoVisualizacao(); • É responsabilidade do Presenter controlar o modo no qual o View deve se encontrar, em função das ações do usuário. Eventos de Sistema • Eventos de sistema ocorrem no View, mas são imediatamente repassados por ele ao Presenter. public void inscrever(ActionListener listener) { btnIncluir.addActionListener(listener); btnConfirmar.addActionListener(listener); btnCancelar.addActionListener(listener); btnAlterar.addActionListener(listener); btnExcluir.addActionListener(listener); btnPesquisar.addActionListener(listener); } Eventos de Sistema • É responsabilidade do Presenter decidir o que fazer como reação ao evento. – Ou seja, o Presenter implementa a lógica da apresentação. – Para ser um ouvinte do View, o Presenter implementa ActionListener. public void actionPerformed(ActionEvent e) { String comando = e.getActionCommand(); if (comando.equals("Confirmar")) { confirmarOperacao(); } else if (... } Uso de um Adapter • Quando a lógica de IU é complexa, uma alternativa é criar adaptatores • Adaptadores são objetos intermediários entre o view e o presenter. • Servem para ajudar o presenter na execução da lógica da apresentação. • Vejamos o próximo slide... Uso de um Adapter (cont) View Adapter Notificações Presenter Apresentação Model Domínio Conclusões • Resumo da arquitetura MVP: – View: exibe os dados e notifica eventos de sistema para o Presenter. – Presenter: coordena a comunicação entre o view e a camada de serviços (ou camada de negócio) e é responsável pela lógica de IU. – Model: os dados que devem ser exibidos ou editados na tela. • Aspectos Positivos – Facilita a modificação da IU por designers gráficos. – Facilita o uso de TDD (Test Driven Design). – Separa adequadamente os aspectos da lógica da aplicação. • Aspectos Negativos – Requer uma mudança na forma de pensar do desenvolvedor – Código é mais abstrato do que no estilo “Forms & Controls” de programação visual. Referências • GUI Architectures – http://martinfowler.com/eaaDev/uiArchs.html • Channel9 – http://channel9.msdn.com/ShowPost.aspx?PostID=313257 • Microsoft sobre MVP – http://msdn.microsoft.com/msdnmag/issues/06/08/DesignPat terns/default.aspx • MVC – http://en.wikipedia.org/wiki/Model-view-controller Referências • Passive View – http://www.martinfowler.com/eaaDev/PassiveScreen.html • Supervising Controller (Supervising Presenter?) http://www.martinfowler.com/eaaDev/SupervisingPresenter.html • GUI Architectures – http://martinfowler.com/eaaDev/uiArchs.html • Podcasts – http://polymorphicpodcast.com/shows/mv-patterns/ • Stub Generator (mais curiosidade do que realidade...) – http://www.polymorphicpodcast.com/tools/mvp-stub/ Material complementar Modo Inicial Modo Inclusão Modo Visualização Modo Alteração Outros Padrões para Apresentação • Forms and Controls • MVC (Model View Presenter) Forms & Controls • Os desenvolvedores escrevem os formulários específicos da aplicação que usam controles genéricos. • O formulário descreve a disposição dos controles nele. • O formulário observa os controles e tem os métodos manipuladores para reagir aos eventos interessantes originados nos controles. • A edição simples de dados é realizada com a estratégia “Data Binding”. • Alterações complexas são feitas pelos métodos manipuladores de eventos do formulário. Code Behind • ASP.NET traz uma forma de separar o comportamento da apresentação de seu layout: code-behind. • No entanto, ainda há alguns aspectos negativos: – O code-behind ainda pode fazer as vezes do manipulador de eventos em um ambiente orientados a eventos. • Forms & Controls – É praticamente proibitivo realizar testes de unidades no código localizado nos code-behind. • “TDD is difficult to use in some situations, such as graphical user interfaces” – Wikipédia para “Test Driven Development” MVC • • • • MVC: Model-View-Controller “modelo”; encapsula os dados “view”- conceito de apresentação “controller”- controla a apresentação – comunicação com o usuário – gerenciamento de eventos MVC • Uso na plataforma JavaEE Outro exemplo de MVP • Suponha que haja a necessidade de apresentar dados sobre um objeto de negócio. • Variance é um campo calculado • Cálculos fazem parte da lógica do negócio • Dica: não faça cálculos no código da IU Interação entre Presenter e View • O presenter solicita à view a exibição de algo sem assumir nada acerca de como essa exibição é feita – “O que” apresentar, e não “Como” ‘ Em vez disso IView.TextBoxName.Text = Cust.Name ‘ Temos isso IView.DisplayCustomer(Cust) Interação entre Presenter e View • A view fornece notificações para o presenter acerca de ações relevantes do usuário. – O presenter é o responsável por iniciar a view. Public Sub New(ByVal view As IView) _view = view AddHandler _view.FileNameChanged, AddressOf FileNameChangedHandler End Sub