La logique de tri doit-elle être placée dans le modèle, la vue ou le contrôleur? [fermé]

157

J'ai une liste déroulante qui affiche les valeurs d'une table à l'utilisateur final. J'aimerais que ces valeurs soient triées par ordre alphabétique.

Selon la conception MVC appropriée, à quelle couche dois-je placer ma logique de tri: le modèle, la vue ou le contrôleur?

EDIT : En réponse à la question de LarsH, "Voulez-vous dire du code qui détermine quel ordre de tri est souhaité? Ou du code qui effectue le tri?", Je faisais à l'origine référence au code qui détermine quel ordre de tri est souhaité.

Ryan Kohn
la source
6
Afin de résoudre le désaccord dans les commentaires, il serait utile que vous disiez ce que vous entendez par «logique de tri». Voulez-vous dire un code qui détermine l'ordre de tri souhaité? ou code qui effectue le tri?
LarsH
9
Le design MVC n'a rien de spécial ou de magique - ce n'est vraiment qu'un point de départ. adaptez-le à vos besoins et n'oubliez pas que vous pouvez le refactoriser à tout moment. J'ai remarqué que différents fournisseurs redéfiniront ce qui entre dans le contrôleur ou la vue en fonction des besoins de leur boîte à outils, il est donc difficile de trouver un accord. L'important est de séparer votre modèle de votre vue / contrôleur. Vous pourriez également obtenir plus de kilométrage grâce au modèle MVP, je pense que c'est un peu plus spécifique dans ce domaine.
Bill K
9
Peut-être que cela devrait être migré vers les programmeurs.
Alfredo Osorio
57
Certainement dans le contrôleur. Soit ça, soit le modèle. Ou la vue.
mob
2
Certainement jamais, jamais, jamais, jamais dans la vue.
contactmatt

Réponses:

49

(Remarque: cette citation et cette citation sont tirées de la réponse de @ dasblinkenlight , mais nous ne sommes pas d'accord sur notre interprétation de celle-ci. Lisez son message et décidez-vous ).

Selon la description MVC ,

Un contrôleur peut envoyer des commandes à sa vue associée pour modifier la présentation de la vue du modèle (par exemple, en faisant défiler un document). Il peut envoyer des commandes au modèle pour mettre à jour l'état du modèle (par exemple, éditer un document).

La logique de tri (par exemple, le comparateur de tri / algorithme de tri) appartient au modèle car elle contient des règles métier et des données d'état. Puisque la modification de la façon dont les données du modèle sont triées tombe carrément dans la catégorie «modifier la présentation de la vue du modèle», le contrôleur est responsable de «faire le tri» en appelant la méthode model.changeSortedState ().

KyleM
la source
8
Que faire si les mêmes données doivent être affichées dans deux vues différentes, triées différemment?
s4y
Cela devrait également être fait de la même manière, model.SortAscending () et model.SortDescending () et appelé par Controller.
Brij
1
@Brij Dans MVC proprement dit, deux vues ne peuvent-elles pas partager le même modèle?
KOVIKO
@Sidnicious S'il est judicieux d'avoir une méthode de tri qui prend un paramètre différent. Par exemple public void Sort(bool sortByDescending = false), si faux, il trie par ordre croissant. Ou ayez simplement deux méthodes de tri différentes si la logique est très différente.
MattMcGowan
@Sidnicious a deux modèles différents qui délèguent tout sauf la logique de tri à un seul troisième modèle. docs.google.com/drawings/d/…
droite du
62

Qui contrôle l'ordre de tri?

Diagramme MVC simple(De Wikipedia )

1) Ordre naturel dans les données elles-mêmes:

La commande fait partie du modèle, elle devrait donc y aller. Une extraction brute de «toutes les données» renverrait les données dans l'ordre trié, et il n'y a pas d'interface pour choisir l'ordre de tri.

2) L'utilisateur doit contrôler la façon dont il voit les données:

La vue fournirait une interface (telle que des flèches ascendantes / descendantes) qui interagissent avec le contrôleur, et le modèle comprend suffisamment bien les données pour effectuer le tri demandé sur les données. Cependant, une extraction brute des données ne doit pas nécessairement être triée, contrairement à (1).

Dans tous les cas,

La vue ne comprend pas qu'un tri est en cours, à part la possibilité de montrer quelle direction de tri a été choisie. N'y mettez pas la logique.

Petite mise en garde

La fonctionnalité de tri pourrait aller purement dans la vue, dans une circonstance (que je peux penser désinvolte; il peut y en avoir plus):

Un tri "stupide" où toutes les données sont déjà dans la vue et il n'est pas nécessaire d'utiliser des connaissances de domaine pour effectuer le tri. Comparaison de chaînes ou de nombres très simple, par exemple. Cela n'est pas possible, par exemple, dans les résultats de recherche sur une page Web lorsque les résultats sont susceptibles d'être répartis sur plusieurs pages.

Izkata
la source
59
La vue peut voir l'utilisateur !?
Farzher
41
Le modèle met à jour la vue !?
deceze
13
Cet article de wikipedia est nul: la section "Interaction des composants" est en conflit avec le diagramme présenté à droite (que vous venez de publier ici). Deuxièmement, le modèle ne «met pas à jour» la vue. Il NOTIFIE la vue lorsqu'il y a eu un changement d'état. La vue décide comment mettre à jour. Pouah. Vous vous demandez pourquoi il y a 1000 réponses différentes à cette question alors qu'il y a tellement d'informations peu claires qui circulent.
KyleM
4
@cHao Bien sûr. Nous pouvons convenir que le graphique de Wikipédia est assez étrange, non? :)
deceze
6
@StephenSarcsamKamenar et tout le monde: Non, l'image est parfaitement logique: elle montre le flux de données , pas les connexions de code.
Izkata
18

Selon la description MVC ,

Un contrôleur peut envoyer des commandes à sa vue associée pour modifier la présentation de la vue du modèle (par exemple, en faisant défiler un document). Il peut envoyer des commandes au modèle pour mettre à jour l'état du modèle (par exemple, éditer un document).

Selon cela, la logique de tri appartient au contrôleur, car la modification de la manière dont les données du modèle sont triées relève carrément de la catégorie «modifier la présentation de la vue du modèle».

EDIT: Pour clarifier les multiples malentendus exprimés dans les commentaires, la "logique de tri" n'est pas le code qui effectue le tri; c'est le code qui définit le tri. La logique de tri compare des éléments individuels les uns aux autres pour établir un ordre (par exemple via une instance de IComparator<T>) ou contient une logique qui construit un objet à utiliser pour la commande par un système externe (par exemple via une instance de IOrderedQueryable<T>). Cette logique appartient à votre contrôleur, car elle nécessite des connaissances liées au côté «métier» de votre application. Il est tout à fait suffisant d'effectuer le tri, mais il est séparé du code qui effectue réellementil. Le code qui trie peut être dans votre vue, dans votre modèle ou même dans la couche de persistance qui soutient votre modèle (par exemple votre base de données SQL).

dasblinkenlight
la source
12
-1 Comment avez-vous réussi à conclure cela à partir de cette citation? A-t-on dit quelque part que le contrôleur est censé récupérer les informations du modèle? Le contrôleur envoie des commandes pour changer l'état. Il n'y a rien de dit sur l'extraction ou la manipulation des informations.
tereško
3
@ tereško Comment avez-vous réussi à conclure de ma réponse que le contrôleur doit récupérer des informations du modèle? Par «logique de tri», j'entends uniquement la logique nécessaire pour établir un ordre - en termes C #, qui fournit une implémentation de IComparer<T>. La «mécanique passe-partout» restante du tri, y compris la récupération des données du modèle, dépend de la vue.
dasblinkenlight
3
".. la logique de tri appartient au contrôleur .." , qu'est-ce que cela signifie d'autre?
tereško
3
«Un contrôleur peut envoyer des commandes à sa vue associée pour changer la présentation de la vue» ressemble vraiment à ce que la vue ferait le tri, en réponse à la commande du contrôleur.
Samuel Edwin Ward
1
@KyleM Mais la vue n'a pas toujours assez de connaissances pour contenir la logique de tri. Par exemple, considérons un champ qui a un code numérique correspondant à l'une des énumérations {Unknown, Pass, Fail}. Supposons également que le Unknowntri doit toujours être effectué en dernier, quel que soit l'ordre croissant ou décroissant choisi par l'utilisateur. Placer cette logique dans la vue en dirait trop sur la nature commerciale des données à l'intérieur du codechamp. La vue ne doit pas le savoir: tout ce qu'elle sait, c'est que l'utilisateur a effectué un geste de "tri" (par exemple, a cliqué sur un en-tête); le reste appartient au contrôleur.
dasblinkenlight
10

Aucune de ces réponses. Le tri est une logique métier, et la logique métier n'appartient à aucun des trois. Tous les morceaux de code de votre application ne seront pas un modèle, une vue ou un contrôleur.

Ce que je fais généralement dans mes applications MVC, c'est que j'ai une couche de service qui exécute toute la logique métier. Les méthodes de la couche de service doivent avoir une API propre et simple avec des paramètres bien nommés. Vous pouvez ensuite appeler ces méthodes à partir de votre contrôleur pour manipuler les données dans les modèles.

En ce sens, le tri est "dans le contrôleur", mais le code lui-même qui effectue le tri ne doit pas être implémenté dans le contrôleur, mais uniquement appelé à partir de là.

non
la source
5
J'ai récemment été informé que certaines personnes considèrent qu'une «couche de service» (logique métier) fait partie du modèle.
Marvo
@Marvo Je pense qu'il y a des cas où certains éléments de logique sont si intimement liés à leur type de données qu'il est logique de les encapsuler ensemble dans une classe. (fonctions heure et date par exemple). En général, cependant, je trouve que cela fonctionne mieux lorsque les objets du modèle ne font que contenir des données.
nont
Alors, où la logique métier «vit» dans le modèle MVC?
Marvo
2
Ce n'est pas parce qu'une application utilise un modèle MVC que chaque morceau de code de l'application sera un modèle, une vue ou un contrôleur. Cela prend trop littéralement les modèles de conception. Par exemple, votre application a probablement un fichier de configuration quelconque. Ce fichier de configuration ne modélise ni les données utilisateur, ni ne présente des vues, ni ne contrôle le flux de données des modèles vers les vues. C'est un fichier de configuration, qui est son propre genre de chose.
nont
On pourrait tout aussi facilement considérer un fichier de configuration comme faisant partie du modèle. Le modèle n'a pas besoin d'être une base de données. Je ne dis pas que vous avez raison ou tort. Je suggère simplement que vous, comme je l'ai fait récemment (parce que j'ai le même point de vue que vous avez), recherchez un peu sur le sujet et voyez ce que les autres disent.
Marvo
8

Certainement pas le contrôleur: il envoie des messages à visualiser et à modéliser, mais devrait faire le moins de travail possible. Si l'utilisateur peut modifier le tri, cette demande est gérée par le contrôleur en informant le modèle ou la vue à ce sujet.

Peut-être la vue si c'est une chose pure vue. Si l'application fonctionne aussi bien sans trier, alors le tri fait simplement partie de la représentation et doit aller dans la vue.

Si la commande fait partie intégrante du domaine, elle doit aller dans le modèle.

Jens Schauder
la source
Est-ce que «fournir un comparateur ou un descripteur de tri» compte comme «faire du travail»? Parce qu'une logique de tri est encapsulée dans un comparateur ou un descripteur de tri, même si le "travail de tri" est effectué dans la méthode de tri ou le back-end du modèle.
dasblinkenlight
Cela dépend de ce que vous entendez par fournir: transmettre, c'est ok. Mais le comparateur doit faire partie du modèle ou de la vue, pas du contrôleur.
Jens Schauder
6
  • Les vues font partie de MVC qui est censée contenir une logique de présentation.
  • La couche modèle est l'endroit où la logique métier est contenue.
  • Les contrôleurs modifient uniquement l'état des deux, en fonction de l'entrée utilisateur.

Le choix est donc le suivant: pensez-vous que cela fait partie de la logique métier du domaine ou de la logique de présentation.

Si vous implémentiez un modèle MVC Model2 approprié ou un modèle MVC classique, je dirais que l'ordre des données fournies par la couche de modèle doit être déclenché par la demande de la vue à la couche de modèle. La vue demande des données ordonnées, la couche de modèle les fournit.

Mais, puisque vous utilisez l'interprétation du modèle MVC par ASP.NET MVC, qui est un peu différente de votre MVC standard, l'instance ViewModel doit demander des informations ordonnées à la couche de modèle (pour une raison quelconque, le framework ASP.NET pense que les modèles doivent être appelés les "vues" et les vues devraient être appelées "viewmodels" ... c'est étrange).

tereško
la source
12
Vous avez continué à voter contre plusieurs réponses en appliquant votre propre hypothèse sur ce qu'elles entendent par «logique de tri». Votre hypothèse est totalement incorrecte - la logique de tri n'inclut pas et n'a jamais inclus la récupération.
dasblinkenlight
1
@dasblinkenlight, oui, je déconseille plusieurs sujets car ils impliquent tous que le contrôleur doit effectuer le tri. Ce qui est faux. Et… les gens… arrêtez de signaler mes commentaires simplement parce que vous n'êtes pas d'accord.
tereško
Juste pour être clair: je n'ai pas voté contre votre réponse parce qu'elle n'est pas incorrecte, et je n'ai jamais signalé aucun de vos commentaires, parce que je ne trouve alors en aucune manière abusif. Honnêtement, je ne sais pas comment votre réponse a réussi à obtenir autant de votes négatifs: je pense qu'ils sont mal conçus.
dasblinkenlight
@dasblinkenlight naah .. je faisais rage à propos de mes commentaires qui, dans ce sujet, ont disparu.
tereško
5

Je le ferais généralement dans le contrôleur pour rester en ligne avec le modèle selon les autres réponses. Voir ci-dessous pour le raisonnement.

J'ai réfléchi à cela et lu les réponses et les documents connexes et, de manière pragmatique, je dirais que cela dépendrait de votre application, par exemple:

S'agit-il d'une application moyenne / grande et / ou a plusieurs interfaces utilisateur associées (c'est-à-dire une application Windows, une interface Web et une interface téléphonique).

  • Dans ce cas, je construirais probablement une couche de service et la placerais dans l'objet métier, puis j'appellerais la méthode appropriée à partir du contrôleur.

S'il s'agit d'un site Web d'interface utilisateur unique bien défini et que vous utilisez quelque chose comme EF Code First et que vous n'avez pas ou n'avez pas l'intention de créer une couche de service et prévoyez d'utiliser une méthode d'extension simple prête à l'emploi pour l'atteindre:

  • Dans ce cas, je le mettrais probablement dans le contrôleur comme pragmatiquement, c'est le meilleur ajustement en termes de temps / budget.

Si c'est le même que celui ci-dessus, MAIS ne peut pas être implémenté avec une méthode d'extension prête à l'emploi.

  • Je pourrais bien choisir de le faire apparaître dans la classe Model (si c'est vraiment sur mesure pour ce type unique) car il serait plus approprié ici que dans un contrôleur. Si le tri pouvait être appliqué à plus d'une classe, je l'implémenterais dans une méthode d'extension, puis je l'appellerais dans le contrôleur.

Pour résumer:

Réponse dogmatique: couche de service

Réponse pragmatique: généralement le contrôleur

Luke Baughan
la source
Dans quelle définition le responsable du traitement est-il chargé de «préparer les données pour consultation»?
tereško
1
@ tereško: Où le modèle est "passif" comme décrit ici msdn.microsoft.com/en-us/library/ff649643.aspx dans la section variations. Voir le "HTTP en est un exemple". Bien qu'un puriste puisse contester cela, il peut être plus facile pour les débutants débutant dans MVC où ils peuvent utiliser EF ou d'autres modèles directement dans le contrôleur et non via un BAL de penser à cela de cette façon, ce qui réduit la barrière pour mieux comprendre le modèle.
Luke Baughan
1
ce dont vous parlez est "modèle anémique".
tereško
Point noté, j'ai supprimé les descriptions offensantes comme vous l'avez suggéré. Vive la contribution!
Luke Baughan
3

Je suggérerais de trier les données à partir d'une table, les données suffisamment petites pour être utiles dans une liste déroulante devraient provenir de la base de données déjà triée via la requête. Pour moi, cela fait du modèle l'endroit où le tri est appliqué.

Si vous êtes déterminé à faire le tri à la main, je pense qu'il y a de bons arguments pour utiliser le modèle ou le contrôleur comme votre endroit préféré pour la logique. La limitation serait votre cadre particulier. Je préfère gérer les données uniquement dans le modèle. J'utilise le contrôleur pour marier les données (modèle) et la présentation (vue) comme je l'ai été (autodidacte).

B0nk3r
la source
2

Bien que je sois d'accord en principe avec l'idée que le tri relève de la logique métier, car en le décomposant selon son origine, vous obtiendrez quelque chose comme "Le client souhaite que la page du produit s'affiche avec les images triées par date", alors il devient clair que l'ordre de tri des données n'est généralement pas arbitraire - même s'il n'y a pas de tri car c'est toujours une décision commerciale par omission (une liste vide est toujours une liste).

MAIS ... Ces réponses ne semblent pas prendre en compte les progrès de la technologie ORM, je ne peux parler que par rapport à l'Entity Framework (évitons une dispute pour savoir si c'est vrai ORM, ce n'est pas le point) de Microsoft comme c'est ce que j'utilise, mais je suis sûr que d'autres ORM offrent des fonctionnalités similaires.

Si je crée une vue fortement typée pour une classe Product à l'aide de MS MVC et Entity Framework et qu'il existe une relation de clé étrangère entre la table Product et Image (par exemple FK_Product_Image_ProductId), alors je serais en mesure de trier rapidement les images pendant leur affichage en utilisant quelque chose comme ceci dans la vue:

@foreach(Image i in Model.Image.OrderBy(e => e.DisplayOrder)){ //etc etc... }

Il a été mentionné une couche de logique métier spécifique, que j'utilise également pour exécuter 80% de ma logique métier, mais je ne vais pas écrire une fonctionnalité de tri dans ma couche de logique métier qui imite quelque chose qui sort de la boîte. à partir de Entity Framework.

Je ne pense pas qu'il y ait une réponse correcte à cette question, à part cela; vous devez abstraire la logique métier complexe lorsque cela est possible, mais pas au prix de réinventer la roue.

Rob
la source
Je pensais la même chose, les réponses ici ne semblent pas prendre en compte les ORM et les méthodes d'extension. Dans la plupart des cas, la logique de tri sera aussi simple que myList.OrderBy(x => x.CreationDate)- il n'est vraiment pas nécessaire d'introduire une couche supplémentaire inutile juste pour ce faire. Pour ajouter à cela, que feraient-ils s'ils avaient besoin de données paginées et triées? Interrogez toute la table, triez-la puis conservez ce dont ils ont besoin? On pourrait simplement appeler myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize)et aucune donnée inutile n'est récupérée.
Balázs
1

Supposons que vous disposez d'un site Web MVC, d'un site Web WebForms et d'une application mobile.

Si vous voulez que le tri soit cohérent entre ces couches de présentation, je dirais alors de trier en dehors de la couche de présentation. Le service serait un bon candidat.

Sinon, je stockerais cette logique dans un modèle de vue. Pourquoi? Parce qu'il sera réutilisable et facilement testable.


la source
0

Sur les trois que vous avez énumérés, je dirais qu'il appartient au contrôleur. Je n'aime pas vraiment placer ce type de logique dans le contrôleur, cependant. Je crée généralement une couche de service avec laquelle le contrôleur communique, qui sera chargée de communiquer avec le magasin de données et de gérer la logique de tri. Pour les petites applications, il est cependant très bien de rester assis dans le contrôleur.

Dismissile
la source
2
Cela mettrait davantage la logique du côté du modèle, n'est-ce pas?
Ryan Kohn
Oui, ma compréhension d'une «couche de service» est qu'elle fait partie du modèle.
Marvo
0

C'est une question posée avec asp.net à l'esprit, mais puisque quelqu'un a mentionné Rails, j'ai pensé qu'il serait intéressant de considérer le problème dans ce contexte. Dans Rails, il est naturel et assez courant d'effectuer le tri avec la récupération en tant qu'action de contrôleur, car le framework et l'API ActiveRecord / ActiveQuery le prévoient. D'autre part, il est possible de définir une sorte d'ordre de tri personnalisé pour les éléments statiques et de le placer dans le modèle à utiliser par le contrôleur, de sorte que le modèle puisse jouer un rôle dans la logique de tri même s'il n'effectue pas l'opération directement. Quoi qu'il en soit, il peut être sûr de dire que mettre la logique de tri dans la vue est généralement mal vu.

Je suis un peu amusé que certaines réponses soient absolument contre le fait de mettre le tri dans le contrôleur ou dans le modèle, et je les trouve trop pédantes à mon goût, mais je suppose que cela dépend de la nature du framework utilisé et des conventions habituelles associées à il. Je suis également d'accord avec le commentaire de Bill K selon lequel la séparation est en premier lieu plus importante.

Prusswan
la source