应该将排序逻辑放置在模型,视图还是控制器中?[关闭]


157

我有一个下拉列表,可显示从表到最终用户的值。我希望这些值按字母顺序排序。

根据适当的MVC设计,我应该在哪一层放置排序逻辑:模型,视图还是控制器?

编辑:针对LarsH的问题,“您是指确定所需排序顺序的代码还是执行排序的代码?”,我最初指的是确定所需排序顺序的代码。


6
为了解决意见分歧,如果您说“排序逻辑”是什么意思,将很有帮助。您是说确定所需排序顺序的代码吗?或执行排序的代码?
LarsH 2012年

9
MVC设计不是什么特别的东西或魔术,它只是一个起点。使它适合您的需求,并记住您可以随时重构。我注意到,不同的供应商将根据其工具箱的需求重新定义控制器或视图中的内容,因此很难达成任何协议。重要的是将模型与视图/控制器分开。您可能还会从MVP模式中获得更多收益,我相信在此领域它会更加具体。
Bill K

9
也许应该将其迁移到程序员。
Alfredo Osorio

57
绝对在控制器中。要么那个,要么那个模型。或视图。
暴民

2
绝对永远,永远,永远,永远在视野中。
contactmatt 2012年

Answers:


49

(注意:此引用和引文来自@dasblinkenlight的答案,但我们不同意对此的解释。请阅读他的文章,并下定决心)。

根据MVC的描述

控制器可以将命令发送到其关联的视图,以更改模型的视图表示(例如,通过滚动文档)。它可以向模型发送命令以更新模型的状态(例如,编辑文档)。

排序逻辑(例如,排序比较器/排序算法)属于模型,因为它包含业务规则和状态数据。由于更改模型数据的排序方式直接属于“更改模型的视图呈现”类别,因此控制器通过调用model.changeSortedState()方法负责“进行排序”。


8
如果相同的数据要在两个不同的视图中显示,并且排序方式不同,该怎么办?
2012年

还应该以相同的方式(model.SortAscending()和model.SortDescending())来完成,并由Controller调用。
Brij 2012年

1
@Brij在适当的MVC中,两个视图可以不共享同一模型吗?
KOVIKO 2012年

@Sidnicious如果有意义的是使用一种采用不同参数的排序方法。例如public void Sort(bool sortByDescending = false),如果为假,则按升序排序。或者,如果逻辑非常不同,则仅使用两种不同的排序方法。
MattMcGowan

@Sidnicious有两个不同的模型,它们将除了排序逻辑之外的所有东西都委派给单个第三个模型。docs.google.com/drawings/d/...
rightfold

62

谁控制排序顺序?

简单的MVC图(来自维基百科

1)数据本身内的自然顺序:

订单是模型的一部分,因此应该去那里。“所有数据”的原始提取将按排序顺序返回数据,并且没有接口可以选择排序顺序。

2)用户应控制他们如何查看数据:

视图将提供与Controller交互的界面(例如,上升/下降箭头),并且Model充分理解数据以对数据进行请求的排序。但是,与(1)不同,不必对数据的原始提取进行排序。

在任一情况下,

视图不了解正在进行排序,而是无法显示已选择的排序方向。不要把逻辑放在这里。

小警告

在一种情况下(我可以认为是顺手的;可能还有更多),排序功能可以完全在View中使用:

一种“哑”排序,其中所有数据都已经存在于视图中,并且无需使用任何领域知识即可进行排序。例如,非常简单的字符串或数字比较。例如,当结果可能会分布在多个页面上时,这在网页上的搜索结果中是不可能的。


58
该视图可以看到用户!?
Farzher 2012年

41
模型将更新视图!
deceze

13
维基百科的文章很烂:“组件交互”部分与右图(您刚刚在此处发布的图)相冲突。其次,该模型不会“更新”视图。状态发生更改时,它将通知视图。视图决定如何更新。啊。您想知道为什么当有这么多不清楚的信息在周围漂浮时,这个问题有1000个不同的答案。
KyleM 2012年

4
@cHao当然。我们可以同意Wikipedia图很奇怪,对吧?:)
deceze

6
@StephenSarcsamKamenar和其他所有人:不,该图像非常合理:它显​​示的是数据流,而不是代码连接。
Izkata 2012年

18

根据MVC的描述

控制器可以将命令发送到其关联的视图,以更改模型的视图表示(例如,通过滚动文档)。它可以向模型发送命令以更新模型的状态(例如,编辑文档)。

据此,排序逻辑属于控制器,因为更改模型数据的排序方式直接属于“更改模型的视图显示”类别。

编辑:为了澄清注释中表达的多种误解,“排序逻辑” 不是执行排序的代码;它是定义排序的代码。排序逻辑将各个项目进行相互比较以建立订单(例如通过的实例IComparator<T>),或者包含构建要用于外部系统订购的对象的逻辑(例如通过的实例IOrderedQueryable<T>)。该逻辑属于您的控制器,因为它需要与应用程序的“业务”方面相关的知识。执行排序就足够了,但与实际执行的代码是分开的它。排序的代码可能在您的视图,模型中,甚至在支持模型的持久层中(例如,SQL数据库)。


12
-1您如何根据该报价得出结论?是否有地方说控制器应该从模型中检索信息?控制器发送命令以更改状态。关于信息的提取或处理,没有什么可说的。
tereško

3
@tereško您如何从我的答案中得出结论,即控制器需要从模型中检索信息?“排序逻辑”是指仅一种建立顺序所必需的逻辑-以C#术语提供了的实现IComparer<T>。排序的其余“样板机制”(包括从模型中检索数据)取决于视图。
dasblinkenlight 2012年

3
“ ..排序逻辑属于控制器..”,这还意味着什么?
tereško

3
“响应于来自控制器的命令,“控制器可以向与其关联的视图发送命令以更改视图的表示形式”听起来确实像视图将进行排序。
塞缪尔·埃德温·沃德

1
@KyleM但是视图并不总是具有足够的知识来包含排序逻辑。例如,考虑一个具有对应于枚举之一的数字代码的字段{Unknown, Pass, Fail}。进一步假设Unknown,无论用户选择了升序还是降序,都必须始终排在最后。在视图中放置此逻辑会使您的视图过多了解code字段内部数据的业务性质。该视图不应该知道:只知道用户执行了“排序”手势(例如,单击标题)。其余的取决于控制器。
dasblinkenlight 2012年

10

以上都不是。排序是业务逻辑,而业务逻辑不属于这三种。并不是您的应用程序中的每一段代码都是模型,视图或控制器。

我在MVC应用程序中通常所做的是,我有一个执行所有业务逻辑的服务层。服务层中的方法应具有带有命名参数的干净,简单的API。然后,您可以从控制器中调用这些方法来处理模型中的数据。

从这种意义上说,排序是“在控制器中”,但是进行排序的代码本身不应该在控制器中实现,而只能从那里调用。


5
我最近得知,有人认为“服务层”(业务逻辑)是该模型的一部分。
Marvo 2012年

@Marvo我认为在某些情况下,某些逻辑部分与它们的数据类型紧密相关,以至于将它们封装在一个类中是有意义的。(例如,时间和日期功能)。但是,总的来说,我发现当模型对象除了保存数据之外什么都不做时,它效果最好。
2012年

那么,业务逻辑在MVC模式中何处“存在”?
Marvo 2012年

2
仅仅因为应用程序使用MVC模式,并不意味着应用程序中的每一段代码都将是模型,视图或控制器。这实际上是在采用设计模式。例如,您的应用程序可能具有某种配置文件。该配置文件既不建模用户数据,也不呈现视图,也不控制通过模型到视图的数据流。它是一个配置文件,这是它自己的东西。
2012年

可以很容易地将配置文件视为模型的一部分。该模型不必是数据库。我并不是说你是对还是错。我只是建议您,就像我最近所做的那样(因为我持有与您相同的观点),将这个主题放到Google上一点,看看别人在说什么。
Marvo 2012年

8

绝对不是控制器:它发送消息以进行视图和建模,但应做的工作尽可能少。如果用户可以更改排序,则控制器会通过通知模型或视图来处理请求。

如果是纯View,则可能是View。如果应用程序在不进行排序的情况下也能正常工作,那么排序只是表示形式的一部分,应该在视图中进行。

如果排序是域的固有部分,则应将其放入模型中。


“提供比较器或排序描述符”是否算作“正在工作”?因为排序逻辑封装在比较器或排序描述符中,所以即使“排序工作”是在排序方法或模型后端中完成的。
dasblinkenlight 2012年

取决于您所提供的含义:可以传入。但是比较器应该是模型或视图的一部分,而不是控制器的一部分。
延斯·肖德

6
  • 视图是MVC的一部分,应该包含表示逻辑。
  • 模型层是业务逻辑所在的地方。
  • 控制器仅根据用户输入更改两者的状态。

因此,选择-您是否认为这是域业务逻辑或表示逻辑的一部分。

如果要实现适当的MVC Model2或经典MVC模式,那么我想说,模型层提供的数据排序应该由视图对模型层的请求触发。视图要求排序的数据,模型层提供了它。

但是,由于您使用的是ASP.NET MVC对MVC模式的解释,因此与标准MVC有所不同-ViewModel实例应从模型层请求有序信息(出于某种原因,ASP.NET框架认为应调用模板“视图”和视图应称为“视图模型” ..这很奇怪。


12
您继续采用自己对“排序逻辑”的含义的假设,否决了多个答案。您的假设完全是错误的-排序逻辑不包含,也从未包含检索。
dasblinkenlight 2012年

1
@dasblinkenlight,是的,我否决了多个主题,因为它们都暗示控制器应该执行排序。这是错的。和..人们..请不要仅仅因为您不同意就标记我的评论。
tereško

请明确说明:我没有对您的回答投反对票,因为它是不正确的,并且我从未标记您的任何评论,因为我认为当时并没有以任何方式侮辱您。老实说,我不知道您的答案是如何获得如此之低的票数的:我认为他们的想法不正确。
dasblinkenlight 2012年

@dasblinkenlight naah ..我对我在此主题中碰到的评论happened之以鼻。
tereško

5

我通常会在控制器中执行此操作,以保持与其他答案一致的模式。参见下文进行推理。

我一直在仔细考虑,阅读答案和相关材料,实用地说,这取决于您的应用程序,例如:

它是中型/大型应用程序和/或具有与其关联的多个UI(即Windows App,Web界面和Phone界面)。

  • 在这种情况下,我可能会构造一个服务层并将其放入业务对象中,然后从控制器中调用适当的方法。

如果它是一个定义明确的单个UI网站,并且您使用的是EF Code First之类的东西,并且您没有或无意创建服务层,并计划使用一种简单的现成的Extension方法来实现它:

  • 在这种情况下,我很可能将其实际地放在时间/预算方面最合适的控制器中。

如果与上述BUT相同,则无法使用现成的扩展方法来实现。

  • 我可能会选择将其弹出到Model类中(如果确实定制给该单一类型),因为在这里比在控制器中更合适。如果排序可以应用于多个类,则可以在扩展方法中实现它,然后在控制器中调用它。

总结一下:

教条式回答:服务层

务实的答案:通常是控制器


哪个定义控制器负责“准备数据以供查看”?
tereško

1
@tereško:此处的msdn.microsoft.com/zh-cn/library/ff649643.aspx在“变体”部分中描述的模型是“被动”的。请参阅“ HTTP是此示例”。尽管纯粹主义者可能对此表示异议,但对于初学者来说,他们可能更容易从MVC入门,因为他们可能直接在控制器中使用EF或其他模型,而无需通过BAL进行这种思考,从而降低了进一步了解模式的障碍。
卢克·波恩

1
您所说的是“贫血模型”。
tereško

要点指出,我已按照您的建议删除了有问题的描述。为输入加油!
Luke Baughan

3

我建议对来自表数据的数据进行排序,该数据应足够小以在下拉列表中使用-应该来自已经通过查询排序的数据库。对我来说,这使模型成为应用排序的地方。

如果您确定要手工进行排序,那么我认为将模型或控制器用作逻辑的首选位置是有道理的。限制将是您的特定框架。我更喜欢仅在模型中管理数据。我已经学会了(自学)使用控制器将数据(模型)和演示文稿(视图)结合在一起。


2

尽管我原则上同意排序是业务逻辑的想法,因为将其分解为起源,您最终会得到诸如“客户希望产品页面显示按日期排序的图像”之类的东西,然后很明显数据的排序顺序通常不是任意的-即使没有排序,因为这仍然是遗漏的业务决策(空列表仍然是列表)。

但是...这些答案似乎没有考虑到ORM技术的进步,我只能就Microsoft的Entity Framework进行讨论(让我们避免争论这是否是真正的ORM,这不是重点)。这就是我使用的方式,但是我确定其他ORM都提供类似的功能。

如果我使用MS MVC和Entity Framework为Product类创建一个“强类型”视图,并且Product和Image表之间存在外键关系(例如FK_Product_Image_ProductId),那么我便可以立即进行排序在显示过程中使用以下视图中的图像进行显示:

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

提到了特定的业务逻辑层,我也用它来执行80%的业务逻辑,但是我不会在我的业务逻辑层中编写排序功能,以模仿现成的东西。来自实体框架。

除了这样说,我认为这个问题没有正确答案。您应该在可能的情况下抽象复杂的业务逻辑,但不要以重新发明轮子为代价。


我在想同样的事情,这里的答案似乎并没有考虑到ORM和扩展方法。在大多数情况下,排序逻辑将非常简单myList.OrderBy(x => x.CreationDate)-确实没有必要为此引入任何不必要的额外层。此外,如果需要分页和排序的数据,他们将怎么办?查询整个表,对其进行排序,然后保留所需的内容?一个人可以打电话myList.OrderBy(x => x.Date).Skip((page-1)*pageSize).Take(pageSize),没有不必要的数据被检索。
巴拉兹

1

假设您有MVC网站,WebForms网站和移动应用程序。

如果您希望排序在这些表示层之间保持一致,那么我会说在表示层之外进行排序。服务将是一个不错的选择。

否则,我会将这种逻辑存储在视图模型中。为什么?因为它可以重用并且易于测试。


0

在您列出的三个中,我想说它属于控制器。不过,我真的不喜欢在控制器中放置这种逻辑。我通常创建一个与控制器通信的服务层,该服务层将负责与数据存储进行通信并处理排序逻辑。不过,对于小型应用程序,可以坐在控制器中。


2
那会使逻辑更多地放在模型方面,对吗?
瑞安·科恩

是的,我对“服务层”的理解是它是模型的一部分。
Marvo 2012年

0

考虑到asp.net,这是一个问题,但是由于有人提到过Rails,所以我认为在这种情况下考虑这个问题会很有趣。在Rails中,将排序和检索作为控制器操作一起执行是很自然且很常见的事情,因为框架和ActiveRecord / ActiveQuery api为此提供了功能。另一方面,可以为静态项目定义某种自定义排序顺序,并将其放入控制器要使用的模型中,因此即使不执行该模型,该模型也可以在排序逻辑中发挥作用直接操作。无论是什么,可以肯定地说,将排序逻辑放在视图中通常是令人讨厌的。

我有些感到有些满足,绝对不赞成将排序放到控制器或模型中,这让我有些感到困惑,但是我觉得它们太过花哨了,但我想它取决于所用框架的性质以及与之相关的常规约定。它。我也同意Bill K的意见,即首先分离是更重要的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.