Esclarecimento MVVM

15

Estamos prestes a escrever nosso primeiro aplicativo WPF e estamos nos familiarizando com o padrão MVVM. Criamos muitos aplicativos Winform e temos uma arquitetura que foi muito bem-sucedida para nós. Estamos com problemas para traduzir essa arquitetura ou determinar onde determinadas partes da nossa arquitetura se encaixam no modelo MVVM.

Historicamente, temos um Gui (o principal exe) que se comunica com uma dll BusinessLogic. O BusinessLogic se comunica com uma DLL DAL através de um serviço da Web e o DAL interage com o DB. O DAL, BusinessLogic e GUI referenciam a mesma DLL BusinessObjects.

Arquitetura AsIs

Parte da transição para o MVVM é bastante direta. Nosso Gui ainda conterá as visualizações, nossos BusinessOjbects ainda conterão o modelo e nosso DAL ainda interagirá com o DB (embora a tecnologia para implementá-los possa mudar).

O que não temos certeza é do nosso componente BusinessLogic. Historicamente, isso forneceria funções para que a GUI chamasse para preencher controles nas exibições (por exemplo, GetCustomerList, que retornaria uma lista de objetos Customer ou as funções CRUD típicas).

O principal problema que temos é se o padrão MVVM exigiria um componente adicional para abrigar os ViewModels ou se apenas mudamos de ideia e migramos o que usamos como componente BusinessLogic para os ViewModels?

Nosso componente BusinessLogic representa os ViewModels?

user7676
fonte
Isso soa um pouco como uma solução procurando um problema. Existe uma razão convincente para você estar migrando para o MVVM? Sou fã do padrão, mas sua solução anterior não estava funcionando? O modelo de visualização é como um apresentador supervisor. Ele contém lógica de apresentação e apresenta dados através da ligação de dados. Ele deve conhecer sua lógica de negócios e poder chegar a essa camada, mas eu não recolheria a lógica de negócios no próprio modelo de exibição.
Jeremy Likness

Respostas:

19

Em geral, eu não colocaria lógica de negócios na camada do modelo de exibição. Mas o termo "lógica de negócios" é enganoso.

Eric Evans usa um modelo em que a lógica de negócios é dividida em duas categorias

  • Lógica do domínio - lógica relacionada ao domínio do problema real que você está resolvendo
  • Lógica do aplicativo - Lógica relacionada ao fato de você estar construindo um aplicativo

Ele menciona o exemplo de um aplicativo de contabilidade. Regras sobre contas, postagens, contas fiscais etc. são regras de domínio, regras pertencentes ao domínio da contabilidade. A lógica sobre importação / exportação de CSV não tem nada a ver com o domínio da contabilidade. Essas regras existem apenas porque estamos construindo um aplicativo de software. Estes são exemplos de lógica de aplicativo.

As regras de domínio NUNCA devem entrar na camada do modelo de visualização. Se você estiver seguindo o padrão MVVM, as regras de domínio entrarão, sem dúvida, na camada de modelo.

Regras de aplicativo, como importação / exportação de CSV, podem ser inseridas na camada do modelo de exibição. Mas, pessoalmente, eu preferiria separar isso em uma camada lógica de aplicativo separada.

O modelo de exibição deve ser muito simples. Procurando os dados necessários para a visualização no modelo correspondente, atualizando o modelo quando a visualização muda, ouvindo eventos no modelo e propagando esses eventos para a visualização, permitindo que a visualização seja atualizada quando o modelo for atualizado nos bastidores (se aplicável).

Pessoalmente, eu garantiria que a camada do modelo de exibição contenha apenas um tipo de lógica, a lógica de apresentação.

Pete
fonte
1
Excelente resposta. Gosto de garantir que o ViewModel contenha apenas a lógica de apresentação. Você pode adicionar algum link relacionado ao seu ponto de Eric Evans?
user7676
Duvido que consiga encontrar um link, porque acredito que o recebi do livro dele, Domain-Driven Design. Enfim, acho que é um excelente exemplo da diferença entre domínio e lógica de aplicativo. Mais sobre o livro aqui books.google.dk/books/about/…
Pete
5

Sim.

A camada da lógica de negócios é representada pela camada da VM. Então, basta migrar seu modelo mental.

Para ajudar na migração do seu modelo mental, uma leve nuance é que os objetos da GUI (Visualização) devem ser vinculados aos objetos na camada da VM. Essa ligação se traduz em | implica que o View não seja mais a camada que "faz a chamada" para recuperar outra coisa. A chamada para recuperação de dados virá da VM.

Para explicar melhor: Sim, um objeto na Visualização precisará ser alterado para acionar a sequência de itens que farão a chamada. Mas o View não faz a chamada propriamente dita. E, nesse caso, considero que um clique no botão é equivalente a algo dentro da exibição que está sendo alterado, mas ainda não estou fazendo a ligação.

No primeiro caso, esse objeto View será vinculado a um objeto VM. A VM deve estar ouvindo um evento alterado de propriedade no objeto vinculado. O evento de mudança de objeto pode ser conectado a uma função de VM para fazer a chamada de modelo.

No segundo caso (evento de clique no botão), o evento de alteração (clique) pode ser conectado a uma chamada de função exposta pela VM.

De qualquer forma, é sempre um evento que sequencia a VM que chama o Modelo, que por sua vez chama o DAL / DB.

Apresento-o porque algum código do WinForm é usado para fazer uma chamada para a camada DB diretamente do code-behind da GUI do WinForm. Essa abordagem quebra a separação que o MVVM está fornecendo.


fonte
Obrigado pela confirmação. Entendemos as nuances de como o View interage com o ViewModel e mantemos o modelo de ligação e eliminamos a "chamada".
user7676
Percebi que essa resposta perdeu um voto positivo. Eu ficaria curioso para saber se o downvoter comentaria por quê? Ou talvez adicione sua própria resposta se eles não compartilharem esse ponto de vista.
user7676
1
Concordo que a camada de lógica de negócios é representada pela camada VM, no entanto, acho que partes da sua resposta podem ser confusas. A Viewcamada deve ser uma representação visual do ViewModel ou Model. Portanto, em vez de dizer que o evento click é conectado a uma chamada de função na VM, uma definição melhor seria dizer que o Comando na VM é renderizado como um Botão no a camada Exibir. Além disso, eu normalmente não faço como a minha camada Model ser capaz de acessar o DAL directamente, para que o meu fluxo de aplicação seria normalmente ir VM -> DAL -> DB, onde os VMe DALambos usam o simples Modelobjetos de dados.
Rachel
4
Eu discordo desta resposta. ViewModel é o modelo da visualização, contém lógica de visualização e não lógica de negócios. ViewModels fazem parte da camada de apresentação
simoraman
1
@simoraman - O padrão MVPVM está alinhado com o que você está sugerindo. Eu acho que o MVPVM é um bom padrão, mas um pouco pesado para aplicativos menores. Eu realmente encorajo você a colocar seus pensamentos em uma resposta e contribuir para esta pergunta.
5

Você está certo de que essencialmente substituirá sua dll BusinessLogic pela camada ViewModel, no entanto, acho que a maior diferença que você enfrentará é como a camada View / UI interage com a camada ViewModel / BusinessLogic.

No WinForms, a GUI é seu aplicativo e é responsável pelo fluxo do aplicativo. No WPF / MVVM, seu ViewModels é seu aplicativo, e a GUI se torna apenas uma interface amigável para interagir com os ViewModels.

Por exemplo, com o WinForms, você pode ter um DataGrid e um Button e, ao clicar nesse botão, chama BusinessLogicLayer.GetProducts()e carrega os objetos Product resultantes no DataGrid.

Com o WPF, você teria um ViewModel que contém an ObservableCollection<Products>e an ICommand GetProducts, e a execução do comando chama o DAL e carrega a coleção de produtos. Mas, para fornecer uma interface amigável, você criaria uma View que renderiza seu ViewModel usando um DataGrid para a coleção Products e um Button para o comando GetProducts.

Na verdade, escrevi um post bastante recente no meu blog sobre a mudança de mentalidade ao passar do Winforms para o WPF no meu blog , e acho que a melhor maneira de resumir a diferença é com essas fotos:

Rachel
fonte
1
Concordo com o GlenH7, esta é uma boa resposta para alguém iniciando com o WPF. Temos a mudança de paradigma da interação entre o View e o ViewModel, de modo que isso não estava realmente no tópico da pergunta que eu fiz.
user7676