如何构建企业级MVC应用程序,业务逻辑放在哪里?

39

我是一个MVC的新手,据我所知:

  • Controller:负责路由请求处理。
  • View:负责数据呈现。
  • Model:看起来非常像一个数据访问层。

业务逻辑放在哪里?

如果有一个大型企业应用程序:

  • 多个不同数据源(WCF、WebServices和ADO)在数据访问层中绑定在一起(使用多个不同的DTO)。
  • 很多业务逻辑分段分布在几个dll中。

从代码和项目结构方面来说,MVC Web应用程序如何在这些上层运行?

我看到的所有示例都放在Model文件夹中,似乎不适用于非常大的应用程序。

感谢任何建议!


如果某种架构似乎不适合您的应用程序,也许您应该考虑不同的设计?MVC并不总是最好的选择。不过,我会很感兴趣看到这里的答案。 - DOK
8个回答

27

在我的应用中,通常会创建一个与Web项目分离的"核心(Core)"项目。

核心项目包含:

  1. 业务对象,例如实体等
  2. 数据访问
  3. 任何不专门为Web设计的内容

Web项目包含:

  1. 控制器(Controller):将UI请求路由到核心逻辑
  2. 视图(View):重点是以HTML形式呈现数据
  3. 视图模型(View Model):将核心业务对象展开/转换成更简单的结构,以支持特定的视图

关键点在于,基于Web的“Models”文件夹/命名空间仅用于记录给定视图所需的具体变量的以呈现为主的模型。尽可能多的“业务逻辑”应该放在核心项目中。


2
哇,8个答案,在40分钟内有多个评论 - 这一定是某种记录!感谢所有人的出色贡献。这个特定的答案(尤其是使用ViewModels)对我来说很有意义,所以我将其标记为答案。 - James
这不是MVVM而不是MVC吗? - Keith Pinson
这个架构的哪一部分负责创建ViewModels? - systempuntoout
@systempuntoout:ViewModel类存在于Web项目中,并在控制器中实例化。这有帮助还是我误解了你的问题? - Seth Petry-Johnson
@Seth Petry-Johnson,如果您能展示一下您示例项目的屏幕截图就更好了。 - Shaiju T

15
Model View Controller(MVC)听起来像是涉及您的3个层次,但实际上不是这样。它确实组织了UI的构建方式。控制器位于中间,并且通常(A)使用Business对象执行操作并(B)从Business对象获取Model对象以传递给View。系统的MVC部分(UI功能)不知道业务层另一侧正在发生什么。数据库?服务调用?磁盘IO?激光发射?因此,“MVC-B-?”将是一个描述MVC及其连接方式的缩写。
Controller想象为中心,向下延伸一条线到Business对象。 控制器通常会从Business对象获取Model并传递给View,但Model只是数据。 这很关键。在某种意义上,Controller现在是系统中最聪明的部分,但Business对象仍然是最强大的部分。
因此,Model对象是Controller和Business对象之间通信的重要组成部分。此外,每个视图都有一个VMView Model)对象,它可能是一个Model,但也可能是由Controller构建的传递更复杂信息集的对象。

因此,控制器(1)从客户端获取数据并对业务对象进行处理(如果必要),可能使用模型对象进行通信,然后(2)从业务对象中获取Model对象构造一个VM,并将其提供给一个或多个视图进行呈现。

起初,这似乎到处都是层和层,特别是因为进入MVC是增加接口使用的好时机(见最后3到4个Solid原则)和单元测试。你的项目中可能有比以前更多的文件。但很快你会发现这实际上是一种很好的组织方式。

作为系统的“顶部”部分,MVC部分,我们根本不关心Model对象是如何构建的或Business对象对它们做了什么。当然,如果您的Customer模型对象看起来非常像您的Customers数据库表,也不要感到惊讶!这是很正常和普遍的。但是,您的客户Model对象和客户Business对象将确实有不同的生命周期。现在是考虑仓储模式的好时机。

抵制懒惰的诱惑,不要在控制器中放置大量逻辑。努力将关注点放在正确的位置上。控制器只是用于连接事物的。如果需要很多代码来构建一个足够的视图模型供视图使用,那么将这些代码放在控制器中是可以的,因为这是控制器的工作。通常情况下,业务逻辑或渲染逻辑会出现在控制器中。将其放在正确的位置上!

6
回答很好,但是我发现在突出显示的缩写词之间有空格,读起来很困难,但我知道你这样做的原因是因为粗体标记的解析方式不好!那么加上粗体字的括号怎么样?比如[V]iew。 - Pauk
很好的答案!如果您不介意,我会将整个单词都加粗,而不仅仅是第一个字母 :) - Vivin Paliath
@Vivin 听起来有点疯狂,但试试吧! - Pauk
@Vivin Paliath 哎呀!我刚才是不是取消了所有的加粗?感谢您的编辑修复,但我也在用另一种策略来做这件事。与我刚才所做的相比,全加粗的关键字布局如何?我采用了Pauk的策略。 - Patrick Karcher
没关系 - 其实我更喜欢你这样的外观。当我把它全部加粗时,它看起来有点杂乱无章! - Vivin Paliath
1
感谢您花费时间阅读此内容 - 您的回复非常有帮助。 - James

9

MVC并不是满足你需求的完整架构,它只覆盖了展示层。你的控制器应该与业务层进行交互,并获取模型对象。业务层可以与其他层进行交互,如数据库访问、Web服务、文件系统等。


3

我倾向于将我的业务逻辑放在服务中,并从控制器调用它们,控制器整理数据并将其发送到相应的服务。

为了使MVC应用程序能够运行,我会使用外观模式或类似的东西来代理对现有业务逻辑的调用。因此,您的服务本质上是外观,只需将数据传递给现有的业务逻辑。

这样,现有的业务逻辑和您的新基于MVC的代码之间就有了一个干净的分界线。


1

"这要看情况" :)

请求被路由到控制器,由控制器适当地处理。控制器是将其他所有组件(模型、视图等)粘合在一起的“胶水”。因此,通过控制器直接处理“业务逻辑”或将其卸载到另一个组件中是很自然的。

实际上,您将逻辑放置在哪里取决于您的需求。如果逻辑仅由单个控制器使用,则将其直接放在其中就可以了。当然,如果需要数据一致性,则逻辑也可能进入单个模型中。

或者,您可以将逻辑放在帮助程序类/函数中,或者(如其他人所提到的),您可以为业务逻辑创建服务层。


1

http://jamesbroo.me/who-can-help-me-q-a/ 是一个关于“谁能帮我?”如何设计的好链接。不幸的是,S#arp Architecture的链接已经失效。 - Jacob

0

或许这个链接可以帮助你更好地理解模型。它们可以扮演数据传输对象的角色,也可以像链接描述的那样更深入。然而,在我看来,它们不应该成为你的DAL。我看到的许多示例都使用服务和存储库模式处理业务逻辑和DAL。

检查MVC Contrib Project和代码营样例以获取此类示例。

我还发现Rob Conery的eCommerce StorefrontNorthwind MVC starter kit很有帮助。


0

在我看来,这种情况更适合使用类似于 WPF 的东西。ViewModel 视图控制器。

您的控制器与执行域对象功能的业务服务进行通信。控制器将从业务服务返回的数据(如果需要,结合多个数据)转换为视图模型(MVC 中的“M”)。然后将视图模型传递给视图。

同样地,从视图中获取 VM 并将数据发送回业务服务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接