Modelos gordos e controladores magros soam como criar modelos de Deus [fechado]

91

Tenho lido muitos blogs que defendem a abordagem de modelos gordos e controladores magros , esp. o acampamento Rails. Como resultado, os roteadores estão basicamente descobrindo qual método chamar em qual controlador e tudo o que o método do controlador faz é chamar o método correspondente no modelo e, em seguida, exibir a visualização. Portanto, tenho duas preocupações aqui que não entendo:

  1. O controlador e o roteador realmente não estão fazendo tarefas muito diferentes além de apenas chamar um método no modelo divino com base na rota.
  2. Os modelos estão fazendo muito. Enviando e-mails, criando relacionamentos, excluindo e modificando outros modelos, enfileirando tarefas, etc. Basicamente agora você tem objetos semelhantes a Deus que devem fazer tudo que pode ou não ter a ver com modelar e lidar com dados.

Onde você desenha a linha? Isso não é apenas cair no padrão de Deus?

Jungle Hunter
fonte

Respostas:

136

Pode não ser a melhor ideia olhar para Rails como um grampo do padrão de design MVC. Essa estrutura foi feita com algumas deficiências inerentes (eu meio que elaborei isso em um post diferente ) e a comunidade apenas agora começou a abordar as consequências. Você pode considerar o desenvolvimento do DataMapper2 como a primeira etapa principal.

Alguma teoria

As pessoas que dão esse conselho parecem ser afetadas por um equívoco bastante comum. Então, deixe-me começar esclarecendo isso: Model, no padrão de design MVC moderno, NÃO é uma classe ou objeto. O modelo é uma camada.

A ideia central por trás do padrão MVC é Separation of Concerns e a primeira etapa é a divisão entre a camada de apresentação e as camadas do modelo. Assim como a camada de apresentação se divide em controladores (instâncias, responsáveis ​​por lidar com a entrada do usuário), visualizações (instâncias, responsáveis ​​pela lógica da IU) e modelos / layouts, o mesmo ocorre com a camada de modelo.

As principais partes em que consiste a camada do modelo são:

  • Objetos de Domínio

    Também conhecidos como entidades de domínio, objetos de negócios ou objetos de modelo (não gosto desse último nome porque só aumenta a confusão). Essas estruturas são o que as pessoas costumam chamar erroneamente de "modelos". Eles são responsáveis ​​por conter as regras de negócio (toda a matemática e validação para unidade específica de lógica de domínio).

  • Abstrações de armazenamento:

    Normalmente implementado usando o padrão de mapeador de dados (não confunda com ORMs , que abusaram desse nome). Essas instâncias geralmente têm a tarefa de armazenar e recuperar informações nos objetos do domínio. Cada objeto de domínio pode ter vários mapeadores, assim como existem várias formas de armazenamento (banco de dados, cache, sessão, cookies, / dev / null).

  • Serviços:

    Estruturas responsáveis ​​pela lógica da aplicação (ou seja, interação entre objetos de domínio e interação entre objetos de domínio e abstrações de armazenamento). Eles devem agir como a "interface" por meio da qual a camada de apresentação interage com a camada do modelo. Isso geralmente é o que no código do tipo Rails termina nos controladores.

Existem também várias estruturas que podem estar nos espaços entre esses grupos: DAOs , unidades de trabalho e repositórios .

Ah ... e quando falamos (no contexto da web) de um usuário que interage com a aplicação MVC, não é um ser humano. O "usuário" é, na verdade, seu navegador da web.

E quanto às divindades?

Em vez de ter algum modelo assustador e monolítico para trabalhar, os controladores devem interagir com os serviços. Você passa dados da entrada do usuário para um serviço específico (por exemplo MailServiceou RecognitionService). Desta forma, o controlador muda o estado da camada do modelo, mas é feito usando uma API clara e sem mexer com as estruturas internas (o que causaria uma abstração com vazamento).

Essas mudanças podem causar alguma reação imediata ou afetar apenas os dados que a instância de visualização solicita da camada de modelo, ou ambos.

Cada serviço pode interagir com qualquer número (embora, geralmente, seja apenas um punhado) de objetos de domínio e abstrações de armazenamento. Por exemplo, o RecogitionServicenão poderia se importar menos com abstrações de armazenamento para os artigos.

Notas de encerramento

Dessa forma, você obtém um aplicativo que pode ser testado por unidade em qualquer nível, tem baixo acoplamento (se implementado corretamente) e tem uma arquitetura claramente compreensível.

Porém, tenha em mente: MVC não se destina a aplicativos pequenos. Se você está escrevendo uma página de livro de visitas usando o padrão MVC, está fazendo isso errado. Esse padrão se destina a fazer cumprir a lei e a ordem em aplicações de grande escala.

Para pessoas que estão usando PHP como linguagem primária, esta postagem pode ser relevante. É uma descrição um pouco mais longa da camada do modelo com alguns trechos de código.

Tereško
fonte
Resposta muito útil e completa! Você conhece algum livro que explique um pouco mais o padrão arquitetônico MVC? Especialmente na parte dos modelos que todos pensam erroneamente "O modelo representa os dados e não faz mais nada." e isso soa mais como a ideia de objeto de domínio, não o 'Modelo' -> tomdalling.com/blog/software-design/…
thermz
1
@thermz, afaik , realmente não há livros que tratem exclusivamente do padrão MVC. Normalmente, apenas digo às pessoas para lerem o PoEAA e depois irem cavar. Talvez esta lista de links possa ser útil. Acho que, quando as pessoas têm uma compreensão sólida dos princípios e conceitos OOP, o padrão se torna muito fácil de entender.
tereško
@tereško bela resposta. O Hibernate consegue isso? Não estou convencido pelas respostas aqui -> stackoverflow.com/questions/1308096/…
Ankan-Zerob
@ Ankan-Zerob como você pode notar, não sou um desenvolvedor java, mas pelo que sei sobre o Hibernate, ele fornece um conjunto de ferramentas completo para camada de persistência. Ele lhe dará parte do que está descrito lá, mas não uma camada de modelo completa.
tereško de
3
@johnny não tanto quanto eu sei. A maioria dos chamados "frameworks mvc" do php são variações do Rails. E, como parte do curso, a maioria deles vem com algumas soluções ORM baseadas em registro ativo (essas coisas são notoriamente frágeis para mudanças no banco de dados). Você pode implementar algo assim com SF2.x ou ZF2.x, mas o objetivo de uma estrutura não é implementar / impor uma arquitetura específica, mas fornecer ferramentas. Além disso, quando se trata de MVC, ele é implementado pelo código do aplicativo e não pela estrutura.
tereško
5

Se as classes "modelo" forem mal implementadas, sim, sua preocupação é relevante. Uma classe de modelo não deve fazer e-mail (tarefas de infraestrutura).

A verdadeira questão é o que implica o modelo em MVC. Não está restrito a classes POCO com alguns métodos. Modelo em MVC significa dados e lógica de negócios. Trate-o como um superconjunto dos modelos básicos de POCO clássicos.

Exibir ==== Controlador ==== Modelo ---> Camada de processo de negócios -> Modelos principais

Adicione conjuntos de infraestrutura e camadas de acesso a dados e use injeção para entregá-los ao BPL, então seu processo está usando MVC conforme pretendido.

O BPL pode invocar padrões de UoW / Respository e executar regras de negócios e chamar recursos de infraestrutura por meio de objetos injetados ou padrões de interface.

Portanto, a recomendação de manter um controlador magro não significa que a classe "pessoa" em um modelo Core clássico deva ter 50 métodos e chamar Email diretamente. Você está certo em pensar que isso está errado.

O controlador ainda pode ser necessário para instanciar e injetar classes de infraestrutura no BPL ou camada central, se chamado diretamente. Deve haver uma camada de negócios ou pelo menos classes orquestrando chamadas entre classes de modelo de objeto clássico. Bem, essa é minha "visão" de qualquer maneira ;-)

Para uma abordagem genérica do MVC, a descrição do wiki http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Um pequeno blog que fala sobre o "M" em MVC. http://www.thedeveloperday.com/skinny-controllers/

phil soady
fonte
1
Se você discordar, pelo menos seja cortês o suficiente para justificar sua opinião
phil soady
-1

Acho que você pode fazer uma distinção entre um único modelo de gordura (possivelmente denominado App ou Aplicativo) e vários modelos de gordura divididos em grupos lógicos (Negócios, Cliente, Pedido, Mensagem). O último é como eu estruturo meus aplicativos, e cada modelo corresponde aproximadamente a uma tabela de banco de dados em um banco de dados relacional ou coleção em um banco de dados de documentos. Esses modelos lidam com todos os aspectos de criação, atualização e manipulação dos dados que compõem o modelo, seja conversando com o banco de dados ou chamando uma API. O controlador é muito pouco responsável por pouco mais que chamar o modelo apropriado e selecionar um modelo.

Bryan Young
fonte