99

几天前, Derik Whitaker 发表了一篇文章,这引起了我一段时间以来的好奇:业务逻辑是否应该存在于控制器中?

到目前为止,我看到的所有 ASP.NET MVC 演示都将存储库访问和业务逻辑放在控制器中。有些甚至还会在那里进行验证。这导致了相当大、臃肿的控制器。这真的是使用MVC框架的方式吗?看起来这最终会导致大量重复的代码和逻辑分布在不同的控制器上。

4

6 回答 6

75

业务逻辑确实应该在模型中。你应该瞄准胖模型,瘦控制器。

例如,而不是:

public interface IOrderService{
    int CalculateTotal(Order order);
}

我宁愿有:

public class Order{
    int CalculateTotal(ITaxService service){...}        
}

这假设税收是由外部服务计算的,并且需要您的模型了解外部服务的接口。

这将使您的控制器看起来像:

public class OrdersController{
    public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...}

    public void Show(int id){
        ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService);
    }
}

或类似的东西。

于 2008-10-24T21:00:17.017 回答
65

我喜欢Microsoft Patterns & Practices提供的图表。我相信这句格言“一张照片胜过千言万语”。

该图显示了 MVC 和业务服务层的架构

于 2012-07-17T21:17:53.143 回答
14

这是一个有趣的问题。

我认为有趣的是,大量示例 MVC 应用程序实际上未能遵循 MVC 范式,即真正将“业务逻辑”完全置于模型中。Martin Fowler 指出,MVC 不是四人组意义上的模式。相反,如果程序员要创建超出玩具应用程序的东西,则必须将模式添加范式中。

所以,简短的回答是“业务逻辑”确实不应该存在于控制器中,因为控制器具有处理视图和用户交互的附加功能,我们只想创建一个目的的对象。

一个更长的答案是,在将逻辑从控制器移动到模型之前,您需要对模型层的设计进行一些思考。也许您可以使用 REST 处理所有应用程序逻辑,在这种情况下,模型的设计应该相当清晰。如果没有,你应该知道你将使用什么方法来防止你的模型变得臃肿。

于 2009-01-19T20:04:51.700 回答
13

您可以查看 Stephen Walther 编写的这个很棒的教程,该教程显示了使用服务层进行验证

了解如何将验证逻辑从控制器操作中移到单独的服务层中。在本教程中,Stephen Walther 解释了如何通过将服务层与控制器层隔离来保持关注点的清晰分离。

于 2011-04-17T22:10:16.633 回答
9

业务逻辑不应包含在控制器中。控制器应该尽可能瘦,最好遵循以下模式:

  1. 查找域实体
  2. 作用于域实体
  3. 为查看/返回结果准备数据

此外,控制器可以包含一些应用程序逻辑。

那么我在哪里放置我的业务逻辑呢?在模型中。

什么是模型?这是一个很好的问题。请参阅Microsoft 模式和实践文章(感谢 AlejandroR 以获得出色的发现)。在这里,模型分为三类:

  • 视图模型:这只是一个数据包,具有从视图传递数据和向视图传递数据的最少逻辑(如果有的话),包含基本的字段验证。
  • 领域模型:具有业务逻辑的胖模型,对单个或多个数据实体进行操作(即实体 A 处于给定状态,而不是实体 B 上的操作)
  • 数据模型:存储感知模型,包含在单个实体中的逻辑仅与该实体相关(即如果字段 a 则字段 b)

当然,MVC 是一种范式,有多种形式。我在这里描述的是 MVC 只占据顶层,参见Wikipedia 上的这篇文章

今天,MVC 和类似的模型-视图-展示器 (MVP) 是关注点分离设计模式,专门应用于更大系统的表示层。在简单的场景中,MVC 可能代表系统的主要设计,直接进入数据库;但是,在大多数情况下,MVC 中的控制器和模型对服务或数据层/层的依赖松散。这都是关于客户端-服务器架构的

于 2013-08-28T11:01:46.797 回答
-1

如果您使用依赖注入器,您的业务逻辑将转到它们,因此您将获得整洁干净的控制器。

于 2014-06-13T15:26:12.727 回答