Em uma arquitetura MVC, quão intimamente acoplados estão o Model e o View ao Controller?


16

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.


1
Não responderei porque minha experiência é limitada em arquiteturas MVC, mas, pelo que ouvi e conversei com outras pessoas, os M&V estão fortemente acoplados entre si, mas não o C. O M geralmente chama funções no C e no V muitas vezes apenas databinds para um subconjunto do M.
Steven Evers

8
@ SNOrfus: Isso é exatamente o oposto do que eu pensava - o M&V está acoplado ao C, mas não um ao outro.
DeadMG

1
Como tantas respostas podem estar tão erradas. Aqui, leia a versão da MS msdn.microsoft.com/en-us/library/ff649643.aspx
Reactgular

Respostas:


15

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.


1
O modelo de visualização é uma prática muito comum quando se trata de teste de unidade. Você normalmente mapeia automaticamente o modelo de domínio ou um objeto DTO para um modelo de exibição. Você usaria seu modelo de vista em uma vista. O modelo de visualização é facilmente testável e não está vinculado a uma camada abaixo.
CodeART

7

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.

  1. Um usuário envia uma solicitação ao seu programa (digamos, adicione um produto ao carrinho de compras).
  2. O controlador aceita essa solicitação (informações do produto e informações do usuário), chama a parte necessária do seu programa que tratará dessa solicitação $user->addToCart($product)
  3. Seu programa ( addToCartfunção do userobjeto neste caso) faz o trabalho que ele pretende fazer e retorna uma resposta (digamos success)
  4. O controlador prepara a resposta usando o relevante 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.

class User {
    //...
    private $id;
    private $shoppingCart;
    //...
}

class Product {
    //...
    private $id;
    //...
}

Ao adicionar um produto ao carrinho de compras, você pode adicionar o product::idao user::shoppingCart.

E quando você deseja persistir os dados, pode usar a modelparte 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.


Ótimo vídeo. Obrigado. Eu discordaria de sua interpretação disso. MVC não é um detalhe no significado que o tio Bob tem lá. Você observará que o MVC é um padrão arquitetural muito parecido com o padrão "Interator / Entity / Boundary" que ele está estabelecendo. Por outro lado, qualquer sistema MVC específico, como o Spring ou o que seja, é de fato algo que ele está recomendando adiar. Como ele explica, essas estruturas, chamadas de "MVC", são uma espécie de bastardização do termo.
Edward Strange

Sim, eu escrevi isso da maneira que as pessoas pensam o que MVCé. Por isso escrevi MVC Framework.
Hakan Deryal

2

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".


1

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


0

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 Model Controller 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.


Ah - é por isso que os votos negativos - eu escrevi errado. Eu quis dizer que o Controller tem dependências em ambos. D'oh!
Matthew Flynn

-5

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.


4
Isto está claramente errado. Um modelo nunca deve depender de uma visualização! Mesmo se essa visão for abstrata ou uma interface. Um modelo deve ser totalmente dissociado da apresentação!
Falcon

3
A resposta está errada. O modelo não depende de uma vista ou controlador.
CodeART

2
@Crazy Eddie Você disse: "Na minha experiência, geralmente o modelo depende apenas de uma visão, não uma específica, muitas vezes como observador" Sua referência citada diz: "No entanto, o modelo não depende da visão nem do controlador". Você já leu o artigo citado? Não parece.
CodeART

2
@Crazy Eddie: Eu não ligo para o que alguém escreve sobre um projeto de código ruim. Este é um design horrível. Usar um observador para escutar as alterações é bom, mas colocar uma interface de apresentação em um modelo de domínio é muito errado. O código citado do artigo tem falhas de algumas maneiras fundamentais em relação ao MVC. Ele ainda permite que o modelo dependa implicitamente do controlador. Mas que porcaria.
Falcon

3
@ Louco Eddie: lol @ tumulto downvote. Eu te enfureci?
Falcon

-7
  • O controlador envia o modelo para uma vista e processa o modelo enviado a partir das vistas, no entanto, não está fortemente acoplado a uma vista ou modelo.

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.


1
Isso é tão errado que não é engraçado. Nem vale a pena explicar. Apenas ignore esta resposta completamente.
Reactgular

1
@ MathewFoscarini Pare de chorar e deixe uma "resposta correta"
CodeART 13/12/12

2
lol, toda a teoria do design por trás do MVC é que eles não são dependentes um do outro.
Reactgular

Deixei mais informações para você, espero que isso faça sentido #
CodeART
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.