No MVC, é considerado uma boa prática ter funções privadas, sem ação, em uma classe de controlador?

10

Às vezes, as funções de ação na classe do controlador podem se tornar enormes e desagradáveis, com muitas linhas de código para simplesmente controlar o fluxo de dados do Model para o View. Em algum momento, essas enormes funções perdem completamente os princípios básicos de um bom código, ou seja, apenas fazem uma coisa, sendo pequenas, legíveis e gerenciáveis ​​etc.

Seria uma boa prática dividir essas enormes funções de ação em funções privadas menores na classe do controlador ou a necessidade dessa otimização significa que devemos adicioná-las ao modelo?

Eu votaria por ter as funções menores como privadas no controlador para que elas sejam relativas à ação, mas ouvi argumentos de que o controlador deve preferencialmente ser simples enquanto o modelo pode ficar enorme e desajeitado; e estava imaginando qual seria o método mais preferido.

David 'o gengibre careca'
fonte

Respostas:

16

Pode não ser a melhor analogia, mas pense no controlador da mesma maneira que você pensaria na teia de uma aranha. Seu único trabalho é pegar moscas (solicitações) para a aranha (camadas subjacentes) digerir. A web pode pegar e segurar moscas menores ou maiores (modelos). O papel da teia de uma aranha não é digerir a presa, embora possa ser usada para esse fim. Quanto mais fina e limpa a teia, mais fácil para a aranha ganhar a vida.

Você pode aplicar a mesma lógica ao seu aplicativo MVC. As funções enormes e desagradáveis ​​que você descreve são o comportamento mais provável do modelo e devem pertencer ao modelo (observe que o modelo não é apenas o objeto que está sendo exibido na exibição). Se o comportamento do modelo mudar, é o modelo que deve ser alterado e não o controlador que lida com isso.

Além disso, mantê-los como métodos particulares no controlador apenas o desorganizaria e dificultaria a manutenção. Também abre caminho para um mau hábito, já que outras pessoas envolvidas no desenvolvimento seriam tentadas a fazer o mesmo, uma vez que já viram isso antes no projeto.

devnull
fonte
+1 para a analogia do criativo. :) Você faz um ponto interessante. Especialmente na formação de maus hábitos. Obrigado.
David 'o careca'
8

A melhor resposta que posso dar é citar o grande livro de Robert Martin, "Código Limpo", que eu recomendo para qualquer pessoa interessada no assunto:

A primeira regra das funções é que elas devem ser pequenas. A segunda regra é que eles devem ser menores que isso.

Não posso dizer melhor. Outra grande citação do mesmo livro se aplica:

Funções devem fazer uma coisa. Eles deveriam fazê-lo bem. Eles deveriam fazer isso apenas.

Ao dividir seu código em mais funções, você é forçado a atribuir nomes significativos a essas funções que podem melhorar muito a legibilidade do seu código. Desnecessário dizer que todas as funções não destinadas a serem usadas fora da classe devem ser privadas, para que você possa reutilizar facilmente seu código por herança.

Se o seu controlador agora possui muitas funções, é um sinal de que provavelmente faz muito. Em seguida, você pode dividi-lo em várias partes independentes ou tentar mover algumas funções para os modelos, conforme mencionado na outra resposta. Além disso, se você seguir o estilo MVC não clássico, em que o Views tem lógica, você poderá colocar algumas de suas funções sempre que caber.

Dmitri Zaitsev
fonte
11
Não acho que colocar a lógica de negócios em visualizações seja "MVC não clássico", é apenas "MVC ruim". Obviamente, você precisa de estruturas básicas de controle nas visualizações, mas elas devem estar alinhadas às preocupações do usuário / interface do usuário, não do domínio / negócios. Uma função real em uma exibição é bastante horrível.
Aaronaught 5/09/13
11
@Aaronaught Eu era vago com "alguma lógica", o que eu tinha em mente é, por exemplo, a biblioteca Backbone.js, onde você coloca eventos e funções do usuário para lidar com eles na sua opinião. No MVC clássico, este é o trabalho do controlador. No entanto, isso pode ser impraticável, pois você precisará ajustar o View e o Controller sempre que sua interface do usuário for alterada. Ao colocar as funções de tratamento da interface do usuário na Visualização, você só precisa ajustar a Visualização. Essa é apenas a minha visão subjetiva - estou perdendo alguma coisa?
Dmitri Záitsev
11
Só porque algo é entregue no lado do cliente não significa que isso faz parte da visão. Ligações de dados em visualizações, com certeza, mas o Backbone é ele próprio uma estrutura MV * (tipo de MVC, tipo de MVP, também não) e os scripts do lado do cliente devem ser organizados de acordo; caso contrário, você está apenas invadindo.
Aaronaught
0

No MVC, tento garantir que meu controlador seja o mais "fino" possível e também que meus modelos sejam o mais burros possível.

As funções lógicas e auxiliares necessárias são colocadas em classes auxiliares separadas e independentes. Isso torna meus testes muito mais fáceis também (você está testando ... certo?: D) Testar controladores é notoriamente difícil, sempre que você tenta criar uma instância de um controlador para testar, você precisa pensar no contexto HTTP e na falsificação http isto e aquilo, e é uma dor, mas é uma dor de propósito. Você precisa de tudo isso porque um controlador está intimamente ligado ao HTTP e à Web. É o ponto de entrada para o seu aplicativo da web.

As funções de lógica e auxiliar não têm nada a ver com a web. Eles são totalmente independentes do ambiente (ou deveriam ser). Só isso deve lhe dizer que eles não pertencem um ao outro no mesmo lugar. Além disso, se você vincular todas as lógicas de seus aplicativos tão intimamente à Web ou a uma implementação específica da Web, nunca poderá levá-la consigo.

Desenvolvemos nosso site MVC com todas as nossas entidades de banco de dados (não nossos modelos mvc, nossas entidades db reais), nosso armazenamento, nossas classes auxiliares e nossa lógica em dlls independentes e independentes. Todos nós possuímos apenas um site, mas fizemos assim de qualquer maneira.

Alguns meses atrás, fomos solicitados a criar alguns aplicativos de desktop relacionados a alguns de nossos sistemas adicionais. Isso foi feito facilmente, pois todo o nosso código testado poderia ser facilmente reutilizado. Se tivéssemos introduzido nosso código em nosso projeto da Web ou colocado em nossos controladores, nunca conseguiríamos fazer isso.

astronauta
fonte
2
O modelo no MVC é a única camada que não deve ser burra. Se os espertos não estão no modelo e não estão no controlador, onde estão ... na exibição? Os controladores também não devem ser difíceis de testar; a capacidade de usar DI e falsificações / zombarias para facilitar o teste de unidade é um dos atrativos do MVC em relação a outras estruturas. A maioria dos meus testes de controlador tem menos de 5 linhas.
Aaronaught 5/09/13
eu usaria uma classe "auxiliar" com lógica em vez de permear um modelo com lógica. que tipo de lógica você colocaria dentro de um modelo? sabe como se carregar e se salvar? Concordo que fingir / arrancar é fácil, mas não é uma desculpa para começar a engordar seus controladores.
spaceman #
Tenho a sensação de que essa resposta significa bem, mas está redigida incorretamente .. ou, talvez, com terminologia diferente.
Simon Whitehead
3
As classes "auxiliares" não são um elemento arquitetural. Eles fazem parte do M, do V ou do C. Se você não tem certeza de qual, esses auxiliares não têm coesão . A palavra "auxiliar" também aparece na lista com "manipular", "fazer", "executar" e o temido gerente .
Aaronaught 5/09/13
@SimonWhitehead: A maioria das respostas significa bem, mas muitas não estão corretas. Infelizmente, este está promovendo um mal-entendido sobre o significado de "Modelo" ou recomendando colocar a lógica crítica de negócios fora dele. Tive o duvidoso prazer de manter sites de MVC com um zilhão de "ajudantes" - eles são terríveis.
Aaronaught 5/09/13
-2

Ao lado de Dmitri Zaitsev e ótimas respostas do astronauta, não sei se o seguinte também é válido para o PHP: Você deve tentar evitar métodos privados devido à falta de possibilidades de teste automatizado.

Sim, você pode usar a metaprogramação ou injeção de dependência para testar métodos privados, mas não deve fazê-lo, pois isso tem um enorme impacto na legibilidade do seu código.

Lembre-se sempre do princípio do KISS: Seja simples, estúpido.

cHaOs667
fonte
5
Essa não é uma boa razão para evitar métodos privados e também não tem nada a ver com a arquitetura MVC. Você não tenta testar métodos privados, eles devem ser cobertos por testes nos métodos públicos . Se você não pode cobri-los, é um sinal de que sua turma é muito complexa e precisa ser refatorada; isso não significa que você não deve ter métodos particulares ou (sinceramente espero que não seja isso que você realmente quis dizer) que eles deveriam ser públicos.
Aaronaught 5/09/2013