MVC:在哪里放置业务逻辑?

And*_*ius 68 c# model-view-controller asp.net-mvc business-logic

首先,我已经看到了很多这方面的问题,但背后还没有足够的推理.如果我的问题不够好而应该删除,我会理解.

我已经看了一下,例如,这个和45多个投票的答案说他建议你把业务逻辑放在模型中,听起来很合乎逻辑.

然而,我的第一个大型项目我完全在控制器中完成了所有BL,因为我没有质疑这些事情,看看它是如何完成的AccountController,如果您选择MVC进行表单身份验证,则会自动添加.所有方法看起来都非常充满BL.或者也许它是可以添加的最少量的代码,我忽略了一些东西?

youtube上的一个人通过将所有逻辑放入他的模型中问我是否正确,起初我不是!然后我开始想,也许他是对的!?

那么,毕竟,我在哪里放置我的业务逻辑?如果它在模型类中,那么,在控制器中的方法中应该将多少代码视为健康数量?一行最多从控制器中的模型调用一些方法,然后返回视图?

Fer*_*cio 49

我更喜欢将域逻辑放在模型中,原因有两个.

  1. 该模型应该没有UI代码,因此更容易测试.在编写任何UI代码之前,我希望尽可能地使用完全正常(意味着完整的测试覆盖)模型.控制器可以相信模型正在做正确的事情并且只处理UI问题.

  2. 如果将域逻辑放在控制器中,则在不同应用程序之间或甚至不同控制器之间共享并不容易.

  • 是的,我真的很喜欢`#2`,因为我发现很难在控制器之间共享(必须使用静态的方法)! (2认同)
  • @Ferrucio 这是一个糟糕的解决方案。您最终会陷入“依赖地狱”,您创建的对象依赖于要创建的其他对象。这是一个糟糕的解决方案,因为不必要/未使用的数据会无缘无故地传递。您希望函数只接受完成工作所需的内容 - 否则代码很快就会变得不清楚。更好的解决方案是创建只需最少的构建时间的业务逻辑类(或者更好的是,使用依赖注入来构建)。这样,您就永远不必获取多个不相关的对象来执行业务逻辑。 (2认同)

Mar*_*lsh 37

我喜欢保持我的模型干净即只是属性和没有业务逻辑.我总是认为将依赖项注入控制器很好,这些依赖项包含我在模型上执行的逻辑.我希望在可能的情况下坚持单一责任原则,我发现有很多方法的模型很快就会膨胀.两者都有利有弊,注入大量依赖有一个开销,但允许单独测试并保持类简单,你最终会有更精简的控制器.尽管我的逻辑实际上并不存在于我的模型中作为类的成员,但它仍然是业务逻辑.我倾向于没有在控制器中定义业务逻辑,因为像Httpcontext这样的模拟事物有点像噩梦并且是不必要的.

  • +1完全同意.我以为我是唯一一个喜欢将模特的责任降到最低的人! (4认同)

The*_*kis 23

业务逻辑属于问题域,一切都属于问题域进入到模型中MVC.

控制器应负责从模型传递数据到视图和从视图回到模型.因此,控制器是用户与之交互的内容与程序如何建模和存储问题状态之间的桥梁.该管道,可以这么说.

这里的关键是业务逻辑和管道逻辑之间的区别.在我看来,自动生成的帐户控制器所做的主要是管道,而不是真正的业务逻辑.请记住,管道逻辑根本不一定是短路的,因此您不需要施加人为限制(例如"控制器中最多X个呼叫").


Mun*_*qar 11

我的团队从webforms(asp.net)转移到mvc时做了很多研究,并提出了以下结构.据我所知,它不是关于应用程序的大小.它关于保持代码清洁和清晰.

DALProject

AccountsDAL.cs --- > Calls SP or any ORM if ur using any
Run Code Online (Sandbox Code Playgroud)

BLLProject

AccountsBLL.cs ---> Calls DAL
Run Code Online (Sandbox Code Playgroud)

WebProject

Model
    AccountsModel --- > Contains properties And call BLL
Controllers
    IndexController ---> Calls Models and returns View
Views
    Index
Run Code Online (Sandbox Code Playgroud)

控制器应负责模型和视图之间的数据传递.除此之外,不应该有任何不必要的代码.例如,如果您正在记录它应该在模型级别而不是控制器上完成.


tre*_*ddy 11

这个话题似乎有些混乱.大多数人似乎都倾向于将MVC模式与N层架构混淆为一种或两种情况.实际情况是这两种方法可以一起使用,但一种不依赖于另一种,也不需要.

N层架构涉及将应用程序分成多个层.一个简单的例子是将应用程序拆分为表示层,业务逻辑层和数据访问层.

MVC是一种处理应用程序表示层的设计模式.完全可以按照MVC方法设计应用程序,而不将业务逻辑和数据访问逻辑与表示层分离,从而最终得到单层设计.

结果,如果您遵循MVC方法而不将应用程序分离为层,则最终会得到模型,视图和控制器,这些模型,视图和控制器具有一些业务规则和数据访问逻辑与其余逻辑混合在一起.

根据定义,在N层体系结构中,表示层应该只能与业务逻辑层进行通信,因此它应该认为任何MVC组件只能与业务逻辑层进行通信.

如果您正在构建一个不涉及演示的应用程序,因此不是表示层,那么您不必关心MVC模式.但是,即使没有涉及表示层,您仍然可以将应用程序拆分为多个层,从而遵循N层设计.


Kol*_*yon 9

业务逻辑不应出现在您的模型视图或控制器中。应该有一个单独的业务逻辑层;该层的唯一目的是处理您的业务逻辑。这更符合SOLID

如果您将业务逻辑放在 MV 或 C 中,您最终会得到难以测试/重用的代码。

把逻辑放在模型中怎么样?

这是一个糟糕的解决方案。

您将最终陷入对象依赖对象的依赖地狱在此处输入图片说明

即使你有一个简单的函数,你仍然需要满足所有的依赖来调用它。

它还会导致无缘无故地传递不必要未使用的数据。这也可能会影响性能,具体取决于它变得多糟糕。

我还应该提到单元测试在 a** 中变得很痛苦,因为你必须模拟多个对象来测试一个简单的函数。

适用的清洁代码原则

  1. 类/函数只需要完成工作所需的东西。
  2. 如果可能,函数应采用 3 个或更少的参数
  3. 智能命名类/函数/变量(遵循微软标准)
  4. 不要将业务逻辑耦合到模型视图或控制器

控制器

在您的控制器中,您应该能够使用依赖注入来注入业务逻辑层。确保您的控制器仅用于将信息路由到业务逻辑层。控制器中不应直接包含业务逻辑。任何验证都需要IValidatable在模型上处理。任何业务逻辑都需要路由到单独的层。


aha*_*usa 5

一般来说,业务逻辑不应驻留在任何MVC播放器中;它只能由您的控制器操作消耗

正如许多人提到的,最好创建一个库来托管业务逻辑,作为一组与客户无关的可重用组件。

通过这种方式,我们可以大大提高软件的可重用性,兼容性,可伸缩性和可测试性。我们还减少了对某些框架功能的依赖,这使得向新/不同技术的移植变得更加容易。

多年来,将我们的业务逻辑抽象成一个独立的程序集(一个或多个程序集)一直对我们有好处。然后,几乎任何.NET技术(ASP.NET MVC / API / Core,WPF,Win Forms,WCF,UWP,WF,控制台等)都可以使用我们的业务逻辑。

此外,我们希望中间层能够处理业务规则和验证逻辑,以减少对.NET MVC框架的依赖。例如,我们避免使用.NET MVC验证帮助程序,而是依靠我们自己的帮助程序。这是另一个因素,使我们能够轻松使用任何.NET技术的业务逻辑。

通过这种方式在逻辑上设计我们的中间层,使我们能够轻松实现以下物理体系结构:

在此处输入图片说明

它是用Peasy.NET编写的,多年来为我们提供了很好的服务。事实上,我们决定将其开源。

如果有人对我们的中间层是什么样子感到好奇,那么这里有一个与客户无关的业务层示例。它还展示了多个.NET客户端(ASP.NET MVC,Web Api和WPF)的使用情况。

希望这对某人有帮助!


Whi*_*eyJ 5

我的一般答案是业务逻辑通常分为两类:

面向对象的业务逻辑:被建模为对象(在模型中),通常作为存储库注入。

过程业务逻辑:进入具有可注入控制器的接口的服务。

控制器逻辑:控制如何接收命令并将其传递给模型/服务,然后将这些结果传递给视图的逻辑。

控制器不应该有业务逻辑,它是设计模式的一个非常具体的部分,用于控制用户界面如何将输入传递给处理业务逻辑的模型(或服务,如果您的问题本质上是程序性的)。