MVC:业务逻辑应该放在哪里?是否有明确的答案?

4

我目前正在尝试重构一个C# MVC应用程序,尽管我对该模式的经验有限。在研究这个主题时,我似乎不断地陷入到关于最佳实践的两极相反的观点中。

我的最大问题是控制器中有太多的内容。它们可以工作,但它们充满了难以重构和测试的业务逻辑。模型大多只是薄薄的DTO。那么,我应该从哪里开始放置这些有用的业务逻辑,以便重新组织和测试呢?

很多人说应该将其放在模型中。但是你会听到一些人说它最终应该放在控制器中。还有其他人告诉你,模型仅包含数据而不包含任何其他内容的原则是该模式的基本原则。

然后你会听到有人告诉你应该把它放在第四种类别中,即ViewModel。现在我已经在WPF中使用MVVM并熟悉这种范例。但是将其添加到MVC中似乎只是为了盲目遵循一种模式规定而复制了很多其他地方已经完成的工作。
另一个选择是将其放入某种辅助类中。这似乎是一个常见的建议,我不会提供链接。但这样做似乎是对另一个类的浪费,该类除了为单个控制器提供函数之外没有存在的意义。这似乎是面向对象编程原则的根本违反。
这个问题是否有明确的“正确”答案?如果有,为什么会有这么多混淆?如果没有,如何在这些观点的泥沼中评估最佳解决方案?

你似乎错过了最重要的一点:服务。这就是SOLID的全部意义:将业务逻辑抽象成单一职责的服务,可以轻松地进行单元测试,并且可以注入到其他服务和控制器中。我强烈建议阅读.NET中的依赖注入这篇文章,以了解如何在复杂应用程序的上下文中将它们整合在一起。 - NightOwl888
你了解CQRS模式吗?基本上你的控制器可以很简单。将命令传递给知道如何执行这些命令的处理程序,查询也是一样的。 - Bishoy
3个回答

3
在MVC中,M代表视图模型(view model),它包含了视图所需的数据,使得视图保持尽可能简单。这个视图模型在控制器中创建并传递给视图,但正如您所说,控制器的逻辑应该尽可能简单 - 不要放置业务逻辑。
这个业务逻辑应该放在服务中 - 这些服务可以是使用WCF暴露的远程服务、Web API,或者只是一个带有方法的类库。概括地说:
1. 控制器调用服务以获取模型形式的数据。业务逻辑在这些服务中,返回的模型仅仅是POCO。 2. 控制器根据接收到的模型创建视图模型,其中包含最适合视图的格式的属性。 3. 控制器将视图模型传递给视图,视图使用视图模型来构建自己。

感谢您的建议。对于这个问题,类库实际上是我处理的最终方法。鉴于这些类中的许多函数不会在其他地方使用,从代码重用的角度来看,这是否有些浪费? - Bob Tway
1
不,我甚至建议针对接口进行编程,这样可以轻松地模拟服务(测试等)。这是一个有价值的抽象;而且很可能一些服务操作将在各种控制器中被重复使用。 - L-Four

2
我不认为有一个明确的“正确”答案。我认为这取决于个人偏好以及数据操作的复杂程度。
在我们公司,我们使用辅助类/服务进行组织。我们的控制器除了接收模型、操作它并将其返回给视图之外,不包含任何功能。
我们有大量的数据操作,如果在控制器中进行操作,会变得非常混乱。
大多数人都同意控制器中不应该包含任何逻辑。区别在于这种逻辑应该放在哪里。对于我们公司来说,把它放在模型本身中是荒谬的,因为需要进行大量的操作。如果没有大量的操作,我会把它放在模型中。

1

我目前参与的项目中,我们尽量将控制器保持不涉及业务逻辑,而是将其拆分为工作单元。我相信采用这种模式是为了能够根据客户等情况更换工作单元。

而我之前参与的项目则全部在控制器中实现,并在必要时拆分为较小的共享帮助程序。

我认为没有严格的正确或错误方式。大多数情况下,这似乎取决于开发人员的个人喜好。


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