Eu tenho um aplicativo que usa MVC, mas estou lutando um pouco sobre como o controlador deve ser arquitetado. Por exemplo, o modo de exibição está exibindo apenas um subconjunto dos dados do modelo de uma só vez. No entanto, não sei exatamente como isso deve ser organizado. É normal que a View ou o modelo chame diretamente funções no controlador, por exemplo? Através de algum tipo de interface? Ou eles são totalmente encapsulados e nunca sabem sobre o Controlador ou um ao outro?
Apenas como uma edição; este é um aplicativo personalizado que não está escrito em nenhuma estrutura da web, portanto, não estou procurando detalhes específicos da estrutura aqui e tenho a liberdade de fazer minha própria escolha.
Respostas:
O controlador controla o fluxo de atividade. O usuário executa esta ação, o controlador passa os dados da visualização para o domínio, o que faz o que for necessário, com base nas respostas, o controlador informa à estrutura qual visualização exibir a seguir (e fornece dados suficientes para fazer assim).
O controlador deve, portanto, ser acoplado ao modelo de domínio, até certo ponto. ie Você pode colocar uma camada de serviço no meio, mas, por definição estrita, isso se torna parte do domínio.
Também é acoplado aos dados da exibição, mas não à exibição em si. ie simplesmente diz "mostre a visão do cliente usando esses detalhes do cliente". A estrutura então decide onde deve encontrar essa visão.
Agora, isso deve permitir que você desacople o modelo de domínio da visualização, usando um modelo de visualização dos mesmos dados. Alguns desenvolvedores fazem isso, outros não, e acho que é em grande parte uma questão de preferência pessoal.
No Rails, você é incentivado a enviar os objetos de domínio (ActiveRecord) para a visualização e confiar que a visualização não tira proveito desse acesso (por exemplo, você não deve chamar customer.save da visualização, mesmo que estaria disponível).
No mundo .NET, tendemos a reduzir o risco, não permitindo coisas que não deveriam acontecer e, possivelmente por esse motivo, parece-me que o modelo de exibição desanexada é mais popular.
fonte
Nota: Robert C. Martin (tio Bob) explica isso de uma maneira muito melhor e bem-humorada em sua palestra: Architecture the Lost Years . Um pouco longo, mas ensina muitos bons conceitos.
tl; dr: não pense e planeje seu aplicativo em termos de MVC. A estrutura MVC é apenas um detalhe de implementação.
A coisa mais confusa sobre o MVC é que os desenvolvedores tentam usar todos os componentes colados.
Tente pensar nos termos de um programa, não nos termos da estrutura.
Seu programa tem um propósito. Ele pega alguns dados, faz coisas com dados e retorna alguns dados.
Dessa forma, o
controller
é o mecanismo de entrega do seu programa.$user->addToCart($product)
addToCart
função douser
objeto neste caso) faz o trabalho que ele pretende fazer e retorna uma resposta (digamossuccess
)view
: por exemplo. no objeto do controlador$this->render($cartView('success')
Dessa forma, os controladores são dissociados do programa e usados como mecanismo de entrega. Eles não sabem como o seu programa funciona, apenas sabem qual parte do programa precisa ser chamada para as solicitações.
Se você quiser usar outra estrutura, seu aplicativo não precisará de alterações, basta escrever controladores relevantes para chamar seu programa para solicitações.
Ou, se você quiser criar uma versão para desktop, seu aplicativo permanecerá o mesmo, você só precisará preparar um mecanismo de entrega.
E o
Model
. Pense nisso como um mecanismo de persistência.No modo OO, existem objetos no seu programa que mantêm os dados.
Ao adicionar um produto ao carrinho de compras, você pode adicionar o
product::id
aouser::shoppingCart
.E quando você deseja persistir os dados, pode usar a
model
parte da estrutura, que geralmente consiste em usar um ORM, para mapear as classes para as tabelas do banco de dados.Se você deseja alterar o ORM usado, seu programa permanecerá o mesmo, apenas as informações de mapeamento serão alteradas. Ou, se você quiser evitar os bancos de dados todos juntos, basta gravar os dados em arquivos de texto sem formatação e seu aplicativo permanecerá o mesmo.
Então, escreva seu programa primeiro. Se você programar com o modo 'OO', use objetos antigos simples da linguagem. Não pense em termos de MVC no início.
fonte
MVC
é. Por isso escreviMVC Framework
.Martin Fowler faz um bom trabalho ao descrever o paradigma MVC. Aqui está um link para o artigo dele http://martinfowler.com/eaaDev/uiArchs.html
Observe sua citação sobre a apresentação separada "A idéia por trás da apresentação separada é fazer uma divisão clara entre objetos de domínio que modelam nossa percepção do mundo real e objetos de apresentação que são os elementos da GUI que vemos na tela".
fonte
Aqui está um exemplo simples de como o MVC pode ser usado em um aplicativo Java Swing típico ...
Digamos que você tenha um painel contendo um botão e um campo de texto. Quando o botão é pressionado, um evento é disparado, levando a alguma alteração de estado no aplicativo. Depois que a alteração de estado é registrada, o TextField fica desativado.
Essa seria a abordagem típica adotada por um aplicativo MVC simples ...
O Controlador se registra como ouvinte dos eventos do View. Quando o botão é clicado, a própria exibição não lida com o evento; o controlador faz. O Controller é específico do Swing, pois deve lidar com eventos relacionados ao Swing.
O Controlador recebe essa notificação e deve decidir quem deve tratá-la (a Vista ou o Modelo). Como esse evento alterará o estado do aplicativo, ele decide encaminhar as informações ao Modelo, responsável pelos dados e pela lógica do programa. Alguns cometem o erro de colocar a lógica do programa no controlador, mas no OOP, os modelos representam dados e comportamento. Leia Martin Fowler em sua opinião sobre isso.
A mensagem é recebida pelo modelo no contexto apropriado. Ou seja, é completamente nula qualquer referência ao Swing ou quaisquer outras referências específicas da GUI. Esta mensagem fala com o modelo e SOMENTE o modelo. Se você estiver importando instruções javax.swing no Modelo, não está codificando o Modelo corretamente.
O Modelo define seu estado como 'desativado' e passa a notificar todas as partes interessadas sobre essa alteração do modelo. A View, interessada neste evento, já se registrou como Observadora de qualquer alteração de modelo. Depois que o evento de alteração de estado do Modelo é capturado pela Visualização, ele desativa o TextField. Também é legal que o View obtenha informações somente leitura diretamente de seu modelo sem precisar passar pelo controlador (geralmente por uma interface específica exposta pelo modelo para essa atividade)
Ao promover esse acoplamento frouxo entre a apresentação e a lógica de negócios e as camadas de dados, você descobrirá que seu código é muito mais sustentável. À medida que os sistemas crescem, também aumentará sua abordagem ao MVC. Por exemplo, o MVC hierárquico é uma extensão usada frequentemente para vincular tríades MVC para formar grandes sistemas corporativos sem acoplamento de subsistemas
fonte
O acoplamento (do tipo que você deseja evitar) envolve uma dependência mútua entre duas classes. Ou seja, um Foo depende de uma barra e uma barra depende de um Foo, para que você não possa realmente modificar uma sem modificar a outra. Isso é uma coisa ruim.
Você não pode realmente evitar ter algumas dependências, no entanto. As turmas precisam conhecer um pouco da outra, caso contrário nunca se comunicariam.
No padrão MVC, o Controlador controla a comunicação entre o Modelo de domínio e a Visualização da apresentação. Como tal, o Controlador deve conhecer o suficiente sobre o Modelo para solicitar que ele faça o que deve fazer. O Controlador também deve conhecer o suficiente sobre a Visualização para poder apresentá-la ao cliente ou usuários. Portanto, o
ModelController possui dependências em ambos. No entanto, o View pode existir perfeitamente bem sem o Controller - não há dependência lá. Da mesma forma, o modelo não possui representações no controlador - é simplesmente o que é. Finalmente, o Model e o View são completamente separados um do outro.Essencialmente, o Controlador é o nível de indireção que separa a Visão do Modelo, para que eles não precisem se conhecer.
fonte
Na minha experiência, geralmente o modelo depende apenas de uma visão, não de uma visão específica, geralmente como observadora ... se ela tem algum acoplamento.
A visão geralmente se encaixa no que quer que esteja olhando, o que faz sentido. Difícil de ter uma visão que possa ser dissociada do que está visualizando ... mas às vezes você pode ter um acoplamento parcial ou algo assim.
O controlador geralmente tende a acoplar a ambos. Isso também faz algum sentido, pois seu trabalho é transformar eventos de exibição em alterações de modelo.
Obviamente, essa é apenas uma tendência que observei e realmente não diz nada sobre nenhum exemplo específico.
Para entender o que é o MVC e qual é a relação de acoplamento, você deve examinar como o MVC surgiu. O ambiente em que o MVC foi criado era aquele em que "widgets" como elementos de formulário com os quais você pode construir diálogos não existiam. Uma "visão" era uma caixa e atraía coisas. Uma exibição de texto seria uma caixa que desenharia texto. Uma exibição de lista era uma caixa que desenharia uma lista. O "controlador" recebeu todos os eventos de mouse e teclado do sistema de interface do usuário que ocorreram nessa exibição; não houve eventos "textChanged" ou "selectionChanged". O controlador pegaria todos esses eventos de baixo nível e geraria interação com o modelo. O modelo, ao ser alterado, notificaria suas visões; desde então, passamos a ver esse relacionamento como "observador" e é '
Essa é a essência do padrão MVC. Como esse tipo de programação de interface do usuário de baixo nível geralmente não é mais realizada, o MVC evoluiu em várias direções diferentes. Algumas coisas que hoje têm esse nome quase não se parecem com o MVC e devem realmente ser chamadas de outra coisa. Ainda pode ser usado no sentido de um diálogo como um todo interagindo com um objeto maior. Existem muitas alternativas melhores.
Basicamente, tudo o que o MVC deveria resolver acontece agora dentro dos widgets e é algo que não precisamos mais usar.
Para aqueles que pensam que sabem melhor:
http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod
http://msdn.microsoft.com/en-us/library/ff649643.aspx
Tenho certeza de que existem mais, mas esses são apenas o topo da lista no google. Como você pode ver, o modelo depende muito de uma interface de visualização em MUITAS implementações. Geralmente, um modelo é observável e a visão é um observador.
Mas por que deixar os fatos atrapalharem ...
Um artigo já publicado em outra resposta também suporta minhas declarações:
http://martinfowler.com/eaaDev/uiArchs.html
Se as pessoas querem continuar dizendo que TODOS na indústria do design estão errados, tudo bem.
fonte
Se o controlador estiver fortemente acoplado a uma visualização, estaremos em um mundo de formulários da web. Você teria um código por trás do qual seria vinculado a um arquivo de modelo (aplicável aos formulários da Web do ASP.NET)
Por esse motivo, o controlador não está acoplado a um modelo ou uma vista. É apenas um mecanismo para processar solicitações e enviar respostas.
A vista está fortemente acoplada a um modelo. Faça alterações no seu modelo (por exemplo, altere sua propriedade) e você terá que fazer alterações na sua visualização.
O modelo não está firmemente acoplado a uma vista. Faça alterações em uma vista e isso não afetará o modelo.
O modelo não sabe nada sobre o controlador ou as visualizações onde ele pode ser usado. Portanto, o modelo não está firmemente acoplado a uma vista ou controlador.
Outra maneira de pensar sobre isso:
Faça alterações em um controlador - a visualização e o modelo não serão afetados
Fazer alterações em um modelo - a exibição será interrompida quando depender de um modelo
Faça alterações em uma vista - o modelo e o controlador não serão afetados
Esse acoplamento frouxo nos projetos MVC é o que os torna fáceis para o teste de unidade.
fonte