Peço desculpas pela longa pergunta, ela parece um pouco como um discurso retórico, mas prometo que não! Resumi minhas perguntas abaixo
No mundo MVC, as coisas são simples. O Modelo tem estado, a Visualização mostra o Modelo, e o Controlador faz coisas para / com o Modelo (basicamente), um controlador não tem estado. Para fazer coisas, o Controlador tem algumas dependências em serviços da Web, repositório e muito. Ao instanciar um controlador, você se preocupa em fornecer essas dependências, nada mais. Ao executar uma ação (método no Controller), você usa essas dependências para recuperar ou atualizar o Modelo ou chamar outro serviço de domínio. Se houver algum contexto, digamos que, como um usuário deseja ver os detalhes de um item específico, você passa o ID desse item como parâmetro para a Ação. Em nenhum lugar do Controlador há alguma referência a qualquer estado. Por enquanto, tudo bem.
Digite MVVM. Eu amo o WPF, amo a ligação de dados. Eu amo estruturas que tornam a ligação de dados ao ViewModels ainda mais fácil (usando o Caliburn Micro atm). Eu sinto que as coisas são menos simples neste mundo. Vamos fazer o exercício novamente: o modelo tem estado, a exibição mostra o ViewModel eo ViewModel faz coisas para / com o modelo (basicamente), um ViewModel faz tem estado! (para esclarecer, talvez ele delega todas as propriedades para um ou mais modelos, mas isso significa que ele deve ter uma referência ao modelo de uma forma ou de outra, que é o estado em si) Para fazercoisas que o ViewModel tem algumas dependências em serviços da web, repositório e muito. Ao instanciar um ViewModel, você se preocupa em fornecer essas dependências, mas também o estado. E isso, senhoras e senhores, me irrita sem fim.
Sempre que você precisar instanciar a ProductDetailsViewModel
partir de ProductSearchViewModel
(do qual você chamou o ProductSearchWebService
que por sua vez retornou IEnumerable<ProductDTO>
, todo mundo ainda está comigo?), Você pode fazer uma destas coisas:
- chamada
new ProductDetailsViewModel(productDTO, _shoppingCartWebService /* dependcy */);
, isso é ruim, imagine mais 3 dependências, isso significa que também éProductSearchViewModel
necessário assumir essas dependências. Mudar o construtor também é doloroso. - Por exemplo
_myInjectedProductDetailsViewModelFactory.Create().Initialize(productDTO);
, a fábrica é apenas um Func, eles são facilmente gerados pela maioria das estruturas de IoC. Eu acho que isso é ruim porque os métodos Init são uma abstração com vazamento. Você também não pode usar a palavra-chave readonly para campos definidos no método Init. Tenho certeza de que existem mais algumas razões. - call
_myInjectedProductDetailsViewModelAbstractFactory.Create(productDTO);
Então ... esse é o padrão (fábrica abstrata) geralmente recomendado para esse tipo de problema. Eu pensei que era genial, pois satisfaz meu desejo de digitar estática, até que comecei a usá-lo. A quantidade de código clichê é, eu acho demais (você sabe, além dos nomes de variáveis ridículos que eu uso). Para cada ViewModel que precisa de parâmetros de tempo de execução, você obtém dois arquivos extras (interface e implementação de fábrica) e precisa digitar as dependências que não são de tempo de execução, como 4 vezes extras. E toda vez que as dependências mudam, você também muda na fábrica. Parece que eu nem uso mais um contêiner de DI. (Eu acho que o Castelo Windsor tem algum tipo de solução para isso [com suas próprias desvantagens, me corrija se eu estiver errado]). - faça algo com tipos ou dicionário anônimos. Eu gosto da minha digitação estática.
Então sim. A mistura de estado e comportamento dessa maneira cria um problema que não existe no MVC. E sinto que atualmente não há uma solução realmente adequada para esse problema. Agora eu gostaria de observar algumas coisas:
- As pessoas realmente usam MVVM. Portanto, eles não se preocupam com tudo isso, ou têm alguma outra solução brilhante.
- Não encontrei um exemplo detalhado de MVVM com WPF. Por exemplo, o projeto de amostra NDDD me ajudou imensamente a entender alguns conceitos de DDD. Eu realmente gostaria que alguém pudesse me apontar na direção de algo semelhante para o MVVM / WPF.
- Talvez eu esteja fazendo MVVM errado e eu deva virar meu design de cabeça para baixo. Talvez eu não devesse ter esse problema. Bem, eu sei que outras pessoas fizeram a mesma pergunta, então acho que não sou a única.
Resumir
- Estou correto ao concluir que ter o ViewModel sendo um ponto de integração para o estado e o comportamento é o motivo de algumas dificuldades com o padrão MVVM como um todo?
- O uso do padrão abstrato de fábrica é a única / melhor maneira de instanciar um ViewModel de maneira estaticamente tipada?
- Existe algo como uma implementação de referência detalhada disponível?
- Ter um monte de ViewModels com estado / comportamento é um cheiro de design?