MVC应用程序,这个逻辑属于哪里?

时间:2012-12-10 04:52:40

标签: asp.net-mvc model-view-controller

在上周的工作中,我们举行了一次会议/演讲,重新思考我们如何做MVC,基于我们老板的大量研究和一些其他SO问题的阅读。对我来说,有一点需要注意的是,当人们说“与数据分离逻辑”时,我可能会更准确地说“与数据分开逻辑”。如果你做第一个,你可能会成为贫血领域模型的牺牲品。我这是对的吗?

其次,我们了解到MVC不会在任何地方包含您的业务逻辑。这应该位于与Web应用程序不同的单独服务层或BLL中。协调这两点似乎有点棘手 - 一个特定的逻辑是否与数据对象一样,正如基本的OOP原则所规定的那样,还是在一个单独的层中?

这是我现在需要帮助的具体示例。我相信这将属于服务层,但我还有其他问题。假设我有一些行为将多个不同类型的不同实体作为输入。它运行,然后作为输出,它可以修改输入实体,并生成新实体作为记录。在我的情况下,这是一个游戏,但你可以说它就像一个交易。涉及多个人,一些产品和生成的收据。

  1. 简单的问题,你会把这个逻辑放在哪里?它是一个可以实例化的独立类吗?
  2. 难题(对我而言)是谁负责调用此代码?让控制器做到这一点会感觉不对。或者这正是它的工作?如果它不能在任何一个特定页面上运行,但是只要用户在特定时间之后访问该站点,该怎么办?基础控制器?
  3. 一般来说,你如何决定“这属于我的实体类,以便它不只是一堆getter和setter”和“这属于我的服务层”?或者我混淆了......实体类是否属于服务层?

1 个答案:

答案 0 :(得分:4)

让我们先梳理一些术语。您所说的“服务层”通常被称为“域模型”,正如您所说,不要与MVC模型混淆。在最基本的层面上,MVC模型封装了域模型。这两个交互如何不由模式本身定义,但模型存储状态逻辑方式是实现有两种不同的状态:

  • 域状态 - 在现实世界中,这通常会以某种方式存储在数据库中,但域模型不应将任何数据源公开给MVC模型。这允许域模型保持适当的封装。任何改变或访问此数据的逻辑都应该使用相关但抽象的访问器来完成,以便MVC模型访问。

  • 应用程序状态 - 例如“目前正在编辑哪条记录?”

要回答您的问题,这实际上取决于您对数据的处理方式。如果您正在进行任何类型的处理,那么这应该在域模型中完成。如果您只是获取显示所需的数据集合,则MVC模型应查询域模型以检索相关数据。然后,视图应该向模型查询此数据。

所以回答你的问题:

  1. 在这种情况下:处理数据的事务应该在域模型中。它可以直接访问所有相关数据,只需使用任何必需参数调用即可。这提高了可重用性,因为它不直接与MVC模型相关联。
  2. 从技术上讲,如果您的控制器直接访问域模型,它比MVC更接近MVVM实现。但是,这不是一件坏事,只要您的域模型采用与域逻辑无关的参数,就不存在真正的问题。但是,控制器不应构建域对象(例如,创建用户帐户并将其传递给模型)。拥有位于MVC三元组之外的域模型的原因正是如此:因此调用代码无关紧要,域逻辑与其运行的体系结构无关。这是一件好事。 MVC是个人的,有时域逻辑只是数据处理。关于“每当用户在特定时间之后访问站点”时,这是域逻辑,因此当然应该进入域模型。哪里取决于触发事件的确切内容,但在这种情况下,它可能是登录例程的一部分或类似。
  3. 事实上。实体(我假设你指的是指单个域对象,用户,产品,博客等的对象?)实际上可能不会包含很多逻辑,因为它们主要是数据结构。订单可以具有“getProducts()”或“getDeliveryAddress()”,其获取相关实体,但域模型将对数据本身进行任何处理。
  4. 根据经验,几乎任何改变数据或处理来自多个实体的数据的逻辑都应该在域模型中发生。这有两个主要原因:1。可重用性,逻辑可以从任何地方重用。 2.封装。一旦开始将此逻辑放入实体中,您最终会遇到域实体依赖于其他域实体的情况。这导致现实世界中的代码非常脆弱,因为您最终会在以后引入任意规则,例如“这些客户无需输入付款详细信息”。 “这是一个公司客户,他们没有账单地址”,如果你已经建模你的“订单”类构建依赖于一个集合或产品用户和账单地址这将成为一个比处理更大的任务在域模型的早期阶段。