Dans MVC, est-il considéré comme une bonne pratique d'avoir des fonctions privées sans action dans une classe de contrôleur?

10

Parfois, les fonctions d'action dans la classe de contrôleur peuvent devenir énormes et désagréables, avec de nombreuses lignes de code pour contrôler simplement le flux de données du modèle vers la vue. À un moment donné, ces énormes fonctions perdent complètement la trace des principes de base d'un bon code, c'est-à-dire ne font qu'une chose, sont petites, lisibles et gérables, etc.

Serait-il considéré comme une bonne pratique de diviser ces énormes fonctions d'action en fonctions privées plus petites dans la classe de contrôleur ou le besoin d'une telle optimisation signifie-t-il que nous devrions plutôt les ajouter dans le modèle?

Je voterais pour que les petites fonctions soient privées dans le contrôleur afin qu'elles soient relatives à l'action, mais j'ai entendu des arguments selon lesquels le contrôleur devrait de préférence être simple tandis que le modèle peut devenir énorme et grumeleux; et se demandait simplement laquelle serait la méthode la plus préférée.

David 'le gingembre chauve'
la source

Réponses:

16

Ce n'est peut-être pas la meilleure analogie, mais pensez au contrôleur de la même manière que vous penseriez à une toile d'araignée. Son seul travail consiste à attraper les mouches (demandes) pour que l'araignée (couches sous-jacentes) digère. La toile peut attraper et contenir des mouches plus ou moins grandes (modèles). Le rôle d'une toile d'araignée n'est pas de digérer la proie, bien qu'elle puisse être utilisée à cette fin. Plus la toile est fine et propre, plus l'araignée gagne facilement sa vie.

Vous pouvez appliquer un peu la même logique à votre application MVC. Les fonctions énormes et désagréables que vous décrivez sont le comportement le plus probable du modèle et elles devraient appartenir au modèle (notez que le modèle n'est pas seulement l'objet affiché dans la vue). Si le comportement du modèle change, c'est le modèle qui doit être modifié et non le contrôleur qui le gère.

De plus, les conserver en tant que méthodes privées dans le contrôleur ne ferait que l'encombrer et le rendre difficile à maintenir. Cela fait également place à une mauvaise habitude, car d'autres personnes impliquées dans le développement seraient tentées de faire de même, car elles l'ont déjà vu dans le projet.

devnull
la source
+1 pour l'analogie créative. :) Votre remarque est intéressante. Surtout sur la formation de mauvaises habitudes. Je vous remercie.
David 'le chauve gingembre'
8

La meilleure réponse que je puisse donner est de citer le grand livre de Robert Martin, "Clean Code" que je recommande fortement à toute personne intéressée par le sujet:

La première règle des fonctions est qu'elles doivent être petites. La deuxième règle est qu'ils doivent être plus petits que cela.

Je ne peux pas le dire mieux. Une autre grande citation du même livre s'applique:

Les fonctions devraient faire une chose. Ils devraient bien le faire. Ils devraient le faire seulement.

Lorsque vous divisez votre code en plusieurs fonctions, vous êtes obligé de donner à ces fonctions des noms significatifs qui peuvent améliorer considérablement la lisibilité de votre code. Inutile de dire que toutes les fonctions qui ne sont pas destinées à être utilisées en dehors de la classe doivent être privées, vous pouvez donc facilement réutiliser votre code via l'héritage.

Si votre contrôleur a maintenant trop de fonctions, c'est un signe qu'il en fait probablement trop. Ensuite, vous pouvez le diviser en plusieurs morceaux indépendants ou essayer de déplacer certaines fonctions vers des modèles comme mentionné dans l'autre réponse. De plus, si vous suivez la saveur MVC non classique, où les vues sont autorisées à avoir une certaine logique, vous pouvez y placer certaines de vos fonctions chaque fois que cela vous convient.

Dmitri Zaitsev
la source
1
Je ne pense pas que mettre la logique métier dans les vues soit "MVC non classique", c'est juste "mauvais MVC". De toute évidence, vous avez besoin de structures de contrôle de base dans les vues, mais elles doivent être alignées sur les préoccupations de l'utilisateur / de l'interface utilisateur, et non sur les préoccupations du domaine / de l'entreprise. Une fonction réelle dans une vue est assez horrible.
Aaronaught
1
@Aaronaught J'étais vague avec "un peu de logique", ce que j'avais en tête était par exemple la bibliothèque Backbone.js, où vous mettiez des événements et des fonctions utilisateur pour les gérer dans votre vue. Dans le MVC classique, c'est le travail du contrôleur. Cependant, cela peut être impossible car vous devrez ajuster à la fois la vue et le contrôleur à chaque fois que votre interface utilisateur change. En plaçant vos fonctions de gestionnaire d'interface utilisateur dans la vue, vous n'avez qu'à ajuster la vue. C'est juste mon point de vue subjectif - manque-t-il quelque chose?
Dmitri Zaitsev
1
Ce n'est pas parce qu'un élément est livré côté client qu'il fait logiquement partie de la vue. Les liaisons de données dans les vues, bien sûr, mais Backbone est lui-même un framework MV * (type de MVC, type de MVP, pas tout à fait non plus) et vos scripts côté client doivent être organisés en conséquence; sinon, vous piratez juste.
Aaronaught
0

Dans MVC, j'essaie de m'assurer que mon contrôleur est aussi "mince" que possible et que mes modèles sont aussi stupides que possible.

Les fonctions logiques et d'assistance nécessaires sont placées dans des classes d'assistance autonomes distinctes. Cela facilite également mes tests (vous testez .. n'est-ce pas ??: D) Le test des contrôleurs est notoirement difficile, chaque fois que vous essayez de créer une instance d'un contrôleur pour tester, vous devez penser au contexte HTTP et simuler http ceci et cela, et c'est une douleur, mais c'est une douleur exprès. Vous avez besoin de tout cela parce qu'un contrôleur est si étroitement lié à HTTP et au Web. C'est le point d'entrée de votre application Web.

Les fonctions logiques et d'assistance n'ont rien à voir avec le Web. Ils sont entièrement indépendants de l'environnement (ou ils devraient l'être). Cela seul devrait vous dire qu'ils n'appartiennent pas ensemble au même endroit. De plus, si vous liez si étroitement la logique de toutes vos applications au Web ou à une implémentation Web particulière, vous ne pourrez jamais l'emporter avec vous.

Nous avons développé notre site MVC avec toutes nos entités de base de données (pas nos modèles mvc, nos entités db réelles), notre stockage, nos classes d'assistance et notre logique en dll autonomes autonomes. Nous n'avons eu qu'un seul site Web, mais nous l'avons quand même fait comme ça.

Il y a quelques mois, on nous a demandé de créer quelques applications de bureau liées à quelques-uns de nos systèmes marginaux. Cela a été facilement fait car tout notre code testé pouvait facilement être réutilisé. Si nous avions inséré notre code dans notre projet Web ou inséré dans nos contrôleurs, nous n'aurions jamais pu le faire.

astronaute
la source
2
Le modèle dans MVC est la seule couche qui n'est pas censée être stupide. Si les smarts ne sont pas dans le modèle, et ils ne sont pas dans le contrôleur, alors où sont-ils ... dans la vue? Les contrôleurs ne devraient pas non plus être difficiles à tester; la possibilité d'utiliser DI et les faux / simulateurs pour faciliter les tests unitaires est l'un des avantages de MVC par rapport aux autres cadres. La plupart de mes tests de contrôleur sont sous 5 lignes.
Aaronaught
j'utiliserais une classe "d'aide" avec la logique plutôt que de pénétrer un modèle avec la logique. quel type de logique mettriez-vous à l'intérieur d'un modèle? sait-il se charger et se sauver? Je suis d'accord pour simuler / tronçonner est facile, mais ce n'est pas une excuse pour commencer à engraisser vos contrôleurs.
spaceman
J'ai le sentiment que cette réponse signifie bien mais elle est mal formulée .. ou peut-être une terminologie différente.
Simon Whitehead
3
Les classes "auxiliaires" ne sont pas un élément architectural. Ils font partie du M, du V ou du C. Si vous ne savez pas lequel, alors ces aides manquent de cohésion . Le mot "helper" se classe également là-haut avec "handle", "do", "perform" et le gestionnaire redouté .
Aaronaught
@SimonWhitehead: La plupart des réponses signifient bien mais beaucoup ne sont pas correctes. Celui-ci, malheureusement, favorise soit une incompréhension du sens de «modèle», soit recommande de mettre la logique métier critique en dehors de celui-ci. J'ai eu le plaisir douteux de maintenir des sites MVC avec un zillion d '"aides" - ils sont affreux.
Aaronaught
-2

À côté de Dmitri Zaitsev et de grandes réponses spateman, je ne sais pas si ce qui suit est également valable pour PHP: Vous devriez essayer d'éviter les méthodes privées en raison du manque de possibilités de test automatisé.

Oui, vous pouvez également utiliser la métaprogrammation ou l'injection de dépendance pour tester des méthodes privées, mais vous ne devriez pas le faire car cela a un impact énorme sur la lisibilité de votre code.

Rappelez-vous toujours le principe KISS: restez simple, stupide.

cHaOs667
la source
5
Ce n'est pas une bonne raison pour éviter les méthodes privées et cela n'a rien à voir avec l'architecture MVC. Vous n'essayez pas de tester des méthodes privées, elles devraient être couvertes par des tests sur les méthodes publiques . Si vous ne pouvez pas les couvrir, c'est un signe que votre classe est trop complexe et doit être refactorisée; cela ne signifie pas que vous ne devriez pas avoir de méthodes privées ou (j'espère sincèrement que ce n'est pas vraiment ce que vous vouliez dire) qu'elles devraient être publiques à la place.
Aaronaught