MVC体系结构—我需要多少个控制器?


54

我已经编码了一段时间,但主要是脚本和简单的应用程序。我已经升任新职位,其职责是开发Web应用程序并使用适当的MVC架构,因此我拼命尝试快速了解所有内容。

我希望这个问题与“ MVC体系结构的最佳实践 ”不太相似,但是当我浏览一些不同的教程时,我注意到其中有些具有针对不同事物的多个控制器。

一个Web应用程序需要多少个控制器?

我意识到如果没有示例,这将很难回答,因此我将提供一个示例:

应用:

  1. 用户登录。
  2. 用户可以做以下三件事之一:
    a) 上传一个文件(与元数据一起存储在mongodb数据库中)。
    b) 搜索文件。
    c) 注销。

我的问题很笼统,但我举了一个例子来帮助任何想回答的人。


8
一个非常好的问题。
Daniel Hollinrake 2013年

Answers:


34

对于您的示例,我将创建两个控制器:

  • 用于登录和注销的会话控制器(为REST之类的布局创建和销毁会话)
  • 用于文件上所有内容的文件控制器(索引=搜索和创建=上传)

通常,RESTful方法将所有内容都视为可以显示,创建,编辑和销毁的资源,这为您提供了一个很好的构想方法。如您从我的示例中看到的那样,我并不太贴近REST中的每个动词。

您很可能需要更多的控制器才能获得更多功能。例如,用户控制器,用户可以在其中创建新帐户。除此之外,您还需要一个管理界面,您可以在其中以更高的权限编辑资源。在这种情况下,几乎每个控制器都重复很常见。

一个很初步的想法很粗略的估计可能是用户可以访问的数据库中每个表的一个控制器。但这实际上只是非常粗略的度量。


3
以您的管理员为例:管理员将扩展普通用户,还是完全重新定义所有方法?例如,也许所有用户都可以上传和搜索,但只有管理员可以删除。管理控制器类是否会继承所有常规用户方法?
杰夫,

4
这实际上很大程度上取决于实际功能,但是总的来说,我简单地编写了一个完全没有继承的第二个控制器。遵循“瘦控制器”原则,控制器中应该没有太多代码。而且管理员控制器可以特别简单。所有重要功能都包含在模型中。(例如,如果删除用户意味着还应删除其所有文件,则模型将处理此问题,控制器
中将

6

这实际上取决于Web应用程序。在您的示例中,一个可能就足够了。如果您要使用运输,税收,库存管理,分层定价等来实现功能全面的电子商务应用程序,那么您可能只想再多一些。

如果您的控制器遭受一种或多种代码气味(尤其是大类或God Object)的困扰,那么您知道您可能已经过了只有一种会起作用的地步了。


5

这实际上取决于您的应用程序需求和业务模块的体系结构。

一般的经验法则是,所需控制器的数量取决于Web应用程序中的模块和子模块的数量。

作为补充,将控制器组织到Areas中将很有帮助。Areas的概念内置于ASP.NET MVC框架中,它简化了为一个模块提供服务的控制器的组织。

有许多相关的讨论:


1
很好的参考!我一定会检查出来的!
杰夫,

好没问题。
EL Yusubov

4

我喜欢苹果的做法。

每个视图仅由一个视图控制器控制。〜适用于iOS的View Controller编程指南

这个想法是,您应该能够轻松地交换视图。海事组织,Controller每项只有1 个View,因此更容易实现。但是我确信您可以拥有一个具有多个视图的Controller并仍然对其进行设计,以便您可以在不更改程序逻辑的情况下切换视图。


那是一个好点,但是您是否需要为每个视图都配备一个控制器,并需要额外的控制器来处理诸如用户之类的事情?我还猜想如果我的项目更大,那么拥有更多控制器将更有意义。
杰夫

模型应跟踪用户。因此,如有必要,多个控制器都可以使用同一模型对象。
Korey Hinton 2013年

2
因此,控制器具有模型对象和视图对象。控制器向模型对象询问信息(例如用户信息),然后相应地设置视图。模型应具有大多数程序逻辑,而控制器仅具有能够在视图与模型之间来回通信的逻辑。
Korey Hinton 2013年

2
每个视图一个控制器的设计非常有限,因为对于模型的不同状态,您的控制器将无法显示不同的视图模型。
EL Yusubov

1
@ElYusubov我可以看到它在哪里令人困惑。在iOS中,每个视图只有一个视图控制器,每个视图控制器只有一个活动视图(该视图可以具有子视图),但是该视图控制器还可以包含对任意数量的视图的引用。
Korey Hinton

2

我喜欢的一个例子是考虑恒温器。恒温器是查看MVC模式的绝佳视觉效果。


在较旧的模拟恒温器上,您可以看到以下内容:

视图 -温度读取器,显示当前温度。

控制器 -用来更改温度的刻度盘

模型 -控制器调用的内部零件导致温度变化。


您应始终遵守允许松散耦合的设计,并将模型及其关联的控制器限制为一个任务,并且应根据需要使用任意数量的模块/控制器。根据应用程序的大小,视图的数量可能远少于模型和控制器的视图。任何大型应用程序都可以预期到这一点。好的面向对象程序设计的特征在于松散的耦合,封装,继承和多态性。并非所有语言都在同一程度上支持多态(功能,方法,运算符重载/重载)。

如果您想更好地理解正确使用MVC架构,请查阅GoF“设计模式:可重用...软件的元素”,该示例使用C ++和SmallTalk作为示例代码。这本书不是Alpha和Omega,但肯定是一个开始!

祝好运!


1

我认为您的示例将发展成为一个复杂的系统。

应用:

用户登录:

  • LoginController

它的唯一责任是处理登录,重定向或将结果通知用户。

上传一个文件

  • UploadController

我在这里假设您要上传任何类型的文件。如果以后决定上传MP3和PDF,那么我将有一个基本的UploadController,MP3UploadController和PDFUploadController。

搜索文件。

  • SearchFileController

这足以满足基本要求。以后可以有多个搜索控制器,具体取决于搜索逻辑变得多么复杂。您要拥有的最后一件事是单个SearchController,它具有20个执行不同搜索的操作方法。

登出。

-LogoutController

可能有人认为这是一个过大的杀手,但我认为不是。我认为它很干净而且分开得很好。

如果我看一下这个项目的结构,我会立即知道它的作用以及它的结构。要采取这一步,我会把LoginControllerLogoutController成独立的区域。

我以前已经开发过类似的东西,并且效果很好。


感谢您的输入!有任何工作代码吗?卡在几件事上。
杰夫(Jeff)

您遇到什么问题?
CodeART

我可以上传主题和日期(字符串格式),但不能上传文件本身(请参见stackoverflow.com/questions/18344614/…)。
杰夫,

我是.NET开发人员。对不起,我帮不了你。
CodeART

1

您的大多数代码都将在业务层中发生,对吗?如果是这种情况,那么您在控制器中真正要做的就是将数据返回到视图。

不太确定我是否喜欢将控制器分为子类型。虽然您应该保持关注点的分离,但我认为子类型有些过分了。另外,在构造函数或控制器中初始化重对象的情况下,您也需要小心。例如:在您的示例中,您想要一个重的对象,仅当用户位于登录页面时才用于搜索/上传文件。

最好每个逻辑单元都有一个控制器,例如AccountController(登录,注册,注销),FileController(搜索,上载)等等。


0

通常,您可以说每个模型都有其自己的控制器和专用视图。概括地说,我的意思是这是最佳做法。

应用程序方面(如用户管理)应转换为应用程序服务,并需要由控制器自身调用,或包装控制器(例如使用根据请求的用户角色使控制器功能“可见”的属性)。

请记住,所有控制器基本上都应该处理模型上的CRUD操作,并对不同的过滤器使用不同的视图。

在我看来,MVC作为模式的主要优点之一是,它提供了联系模型和视图的最佳方法。

关于您添加的示例:我将创建2个控制器:一个用于所有用户登录操作(注册,登录,注销等),第二个用于文件操作(上传和搜索)。请注意,第一个还应该备份一些与登录功能相关的方面,第二个是普通控制器


如果没有任何解释,那么如果有人发表相反的意见,此答案可能会毫无用处。例如,如果有人发布诸如“管理用户角色和授权不应位于控制器之上”之类的声明,那么此答案将如何帮助读者选择两种相反的意见?考虑编辑将其投入一个更好的状态
蚊蚋

1
@gnat我接受您的评论,请参阅编辑后的答案
Saturn Technologies
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.