Estou tentando entender bem como implementar uma boa dissociação entre uma interface do usuário e o modelo, mas estou tendo problemas para descobrir exatamente onde dividir as linhas.
Eu estive analisando o Model-View-Presenter, mas não sei exatamente como proceder para implementá-lo. Por exemplo, minha Visualização possui várias caixas de diálogo.
- Deve haver uma classe View com instâncias de cada uma das caixas de diálogo? Nesse caso, como os diálogos devem interagir com o Apresentador? ie se um diálogo individual precisar solicitar dados do modelo por meio do apresentador, como o diálogo deve obter uma referência ao apresentador? Através de uma referência à vista que lhe foi dada durante a construção?
- Eu estava pensando que talvez a visão devesse ser uma classe estática? Em seguida, as caixas de diálogo GetView e o Presenter de lá ...
- Eu estava pensando em configurá-lo para o Presenter com propriedade do View and Model (em oposição ao View com o Presenter e o Presenter com Model) e o Presenter registrando retornos de chamada para eventos no View, mas isso faz parecer muito mais acoplados (ou pelo menos o idioma dependia).
Eu estou tentando:
- faça isso o mais dissociado possível
- idealmente, é possível associar o Presenter / Model às exibições de outros idiomas (eu não fiz muitas coisas inter-idiomas, mas sei que é possível, principalmente quanto mais
void(void)
posso me apegar, pelo menos um aplicativo C # com um Biblioteca C ++ ... - mantenha o código limpo e simples
Então .. alguma sugestão de como as interações devem ser tratadas?
design-patterns
ui
interfaces
trycatch
fonte
fonte
Respostas:
Bem-vindo a uma ladeira escorregadia. Você já percebeu que existe uma variação infinita de todas as interações de visualização de modelo. MVC, MVP (Taligent, Dolphin, Passive View), MVVM apenas para citar alguns.
O padrão do Model View Presenter, como a maioria dos padrões de arquitetura, está aberto a muita variedade e experimentação. A única coisa que todas as variações têm em comum é o papel do apresentador como um "intermediário" entre a visualização e o modelo. Os dois mais comuns são a visão passiva e o apresentador / controlador de supervisão - [ Fowler ]. O Passive View trata a interface do usuário como uma interface muito superficial entre o usuário e o apresentador. Ele contém muito pouca ou nenhuma lógica, delegando tanta responsabilidade a um apresentador. Apresentador / Controlador Supervisortenta tirar proveito da ligação de dados incorporada em muitas estruturas de interface do usuário. A interface do usuário lida com a sincronização de dados, mas o apresentador / controlador adota uma lógica mais complexa. Nos dois casos, o modelo, a visualização e o apresentador formam uma tríade
Há muitas maneiras de fazer isso. É muito comum ver isso tratado, tratando cada caixa de diálogo / formulário como uma visão diferente. Muitas vezes, existe uma relação 1: 1 entre visualizações e apresentadores. Esta não é uma regra difícil e rápida. É bastante comum que um apresentador lide com várias visualizações relacionadas ou vice-versa. Tudo depende da complexidade da visualização e da complexidade da lógica de negócios.
Quanto à maneira como as visualizações e os apresentadores obtêm uma referência um para o outro, isso às vezes é chamado de fiação . Você tem três opções:
A exibição contém uma referência ao apresentador.
Um formulário ou caixa de diálogo implementa uma exibição. O formulário possui manipuladores de eventos que delgate para um apresentador usando chamadas de função diretas:
Como o apresentador não tem uma referência à visualização, ela deve enviar dados como argumentos. O apresentador pode se comunicar de volta à exibição usando funções de eventos / retorno de chamada que a exibição deve escutar.
O Presenter mantém uma referência para exibição.
No cenário, a exibição expõe propriedades para os dados exibidos para o usuário. O apresentador escuta eventos e manipula as propriedades na exibição:
Ambos mantêm uma referência um ao outro, formando uma dependência circular.
Este cenário é realmente mais fácil de trabalhar do que os outros. A exibição responde aos eventos chamando métodos no apresentador. O apresentador lê / modifica dados da exibição por meio de propriedades expostas.
Há outros problemas a serem considerados nos padrões do MVP. Ordem de criação, vida útil do objeto, onde a fiação ocorre, comunicação entre as tríades MVP, mas essa resposta já foi longa o suficiente.
fonte
Como todos disseram, existem dezenas de opiniões e nenhuma delas está certa ou errada. Sem entrar na miríade de padrões e focando apenas no MVP, aqui estão algumas sugestões sobre implementação.
Mantenha-os separados. A visão deve implementar uma interface que forma o vínculo entre a visão e o apresentador. A exibição cria um apresentador e se injeta no apresentador e expõe os métodos oferecidos para o apresentador interagir com a exibição. A visualização é responsável por implementar esses métodos ou propriedades da maneira que desejar. Geralmente, você tem uma visualização: um apresentador, mas em alguns casos você pode ter muitas visualizações: um apresentador (web, wpf, etc.). A chave aqui é que o apresentador não sabe nada sobre implementações da interface do usuário e apenas interage com a exibição pela interface.
Aqui está um exemplo. Primeiro, temos uma classe de exibição com um método simples para exibir uma mensagem para o usuário:
Agora aqui está o apresentador. Observe que o apresentador recebe uma IView em seu construtor.
Agora, aqui está a interface do usuário real. Pode ser uma janela, uma caixa de diálogo, uma página da web etc. Não importa. Observe que o construtor da exibição criará o apresentador injetando-se nele.
O apresentador não se importa com a maneira como a exibição implementa o método que ele faz. Pelo que o apresentador sabe, ele pode estar gravando em um arquivo de log e nem mesmo mostrá-lo ao usuário.
De qualquer forma, o apresentador trabalha com o modelo no back-end e, em algum momento, deseja informar o usuário sobre o que está acontecendo. Portanto, agora temos um método em algum lugar no apresentador que chama para a mensagem InformUser dos modos de exibição.
É aqui que você obtém sua dissociação. O apresentador mantém apenas uma referência a uma implementação do IView e realmente não se importa como ele é implementado.
Essa também é uma implementação pobre, pois você tem uma referência ao Presenter na visualização e os objetos são definidos por meio de construtores. Em uma solução mais robusta, você provavelmente desejaria examinar contêineres de inversão de controle (IoC), como Windsor, Ninject etc., que resolveriam a implementação do IView para você em tempo de execução sob demanda e, assim, tornando-o ainda mais dissociado.
fonte
Eu acho que é importante lembrar que o Controller / Presenter é onde a ação realmente ocorre. O acoplamento no controlador é inevitável por causa da necessidade.
O ponto principal do Controller é que, se você fizer uma alteração na View, o Model não precisará mudar e vice-versa (se o Model alterar a View também não precisa) porque o Controller é o que traduz o Modele na Vista e volte novamente. Mas o Controlador mudará quando as alterações de Modelo ou de Visão o fizerem, porque você precisa traduzir efetivamente dentro do Controlador como o Modelo é Visto como obter as alterações feitas na Visualização de volta ao Modo.
O melhor exemplo que posso dar é que, ao escrever um aplicativo MVC, sou capaz de não apenas ter dados na visualização da GUI, mas também de escrever uma rotina que empurra os dados extraídos do Modelo para um
string
a ser mostrado no depurador (e por extensão em um arquivo de texto sem formatação). Se eu puder pegar os dados do Modelo e traduzi-los livremente em texto sem alterar a Visualização ou o Modelo e apenas o Controlador, estou no caminho certo.Dito isto, você precisará ter referências entre os diferentes componentes para que tudo funcione. O Controller precisa conhecer o View para enviar dados, o View precisa saber sobre o Controller para avisar quando uma alteração foi feita (como quando o Usuário clica em "Salvar" ou "Novo ..."). O Controller precisa saber sobre o Modelo para extrair os dados, mas eu argumentaria que o Modelo não deveria saber de mais nada.
Advertência: Eu venho de uma experiência totalmente Mac, Objective-C, Cocoa, que realmente leva você ao paradigma MVC, quer você queira ou não.
fonte
Em geral, você deseja que seu modelo encapsule todas as interações com esse modelo. Por exemplo, suas ações de CRUD (Criar, Ler, Atualizar, Excluir) fazem parte do modelo. O mesmo vale para cálculos especiais. Há algumas boas razões para isso:
No seu controlador (aplicativo MVC), tudo o que você está fazendo é coletar os modelos que você precisa usar na sua visualização e chamar as funções apropriadas no modelo. Quaisquer alterações no estado do modelo acontecem nesta camada.
Sua visualização simplesmente exibe os modelos que você preparou. Essencialmente, a visualização lê apenas o modelo e ajusta sua saída de acordo.
Mapeando o princípio geral para classes reais
Lembre-se de que suas caixas de diálogo são visualizações. Se você já possui uma classe de diálogo, não há motivo para criar outra classe "Visualizar". A camada Presenter vincula essencialmente o modelo aos controles na Visualização. A lógica de negócios e todos os dados importantes são armazenados no modelo.
fonte