关于设计模式:MVC中的业务逻辑

Business logic in MVC

我有两个问题:

Q1。 MVC模式中"业务逻辑"到底在哪里? 我在模型和控制器之间感到困惑。

Q2。"业务逻辑"是否与"业务规则"相同? 如果没有,有什么区别?

如果你能用一个小例子来解释它会很棒。


所有的拳头:
我相信你正在混合MVC模式和基于n层的设计原则。
使用MVC方法并不意味着您不应该对应用程序进行分层。
如果你看到MVC更像是表示层的扩展,那么它可能会有所帮助。
如果将非表示代码放在MVC模式中,您可能很快就会陷入复杂的设计中。
因此,我建议您将业务逻辑放入单独的业务层。

看看这个:维基百科有关多层架构的文章
它说:

Today, MVC and similar model-view-presenter (MVP) are Separation of Concerns design patterns that apply exclusively to the presentation layer of a larger system.

无论如何......在谈论企业Web应用程序时,从UI到业务逻辑层的调用应该放在(表示)控制器中。
这是因为控制器实际处理对特定资源的调用,通过调用业务逻辑来查询数据,并将数据(模型)链接到适当的视图。

泥告诉你,业务规则进入模型。
这也是事实,但他混淆了(演示)模型(MVC中的'M')和基于层的应用程序设计的数据层模型。
因此,将与数据库相关的业务规则放在应用程序的模型(数据层)中是有效的。
但是您不应该将它们放在MVC结构化表示层的模型中,因为这仅适用于特定的UI。

此技术与您使用域驱动设计还是基于事务脚本的方法无关。

让我想象一下:

表示层:模型 - 视图 - 控制器

业务层:域逻辑 - 应用程序逻辑

数据层:数据存储库 - 数据访问层

您在上面看到的模型意味着您有一个使用MVC,DDD和数据库独立数据层的应用程序。
这是设计更大的企业Web应用程序的常用方法。

但您也可以缩小它以使用简单的非DDD业务层(没有域逻辑的业务层)和直接写入特定数据库的简单数据层。
您甚至可以删除整个数据层并直接从业务层访问数据库,但我不建议这样做。

这就是诀窍......我希望这会有所帮助......

[注意:]
您还应该意识到,现在应用程序中不仅仅有一个"模型"。
通常,应用程序的每一层都有自己的模型。
表示层的模型是视图特定的,但通常独立于所使用的控件。
业务层还可以具有称为"域模型"的模型。当您决定采用域驱动方法时,通常会出现这种情况。
这个"域模型"包含数据和业务逻辑(程序的主要逻辑),通常独立于表示层。
表示层通常在某个"事件"(按下按钮等)上调用业务层,以从数据层读取数据或将数据写入数据层。
数据层也可能有自己的模型,通常与数据库相关。它通常包含一组实体类以及数据访问对象(DAO)。

问题是:这如何适应MVC概念?

答案 - >不是!
好吧 - 它有点但不完全。这是因为MVC是一种在1970年代后期为Smalltalk-80编程语言开发的方法。当时GUI和个人计算机非常罕见,甚至没有发明万维网!
今天的大多数编程语言和IDE都是在20世纪90年代开发的。
那时计算机和用户界面与20世纪70年代完全不同。
当你谈到MVC时,你应该记住这一点。
Martin Fowler写了一篇关于MVC,MVP和今天的GUI的非常好的文章。


业务规则包含在模型中。

假设您正在显示邮件列表的电子邮件。用户单击其中一个电子邮件旁边的"删除"按钮,控制器通知模型删除条目N,然后通知视图模型已更改。

也许管理员的电子邮件永远不应该从列表中删除。这是一个商业规则,知识属于模型。视图最终可能以某种方式表示此规则 - 可能模型公开了一个"IsDeletable"属性,该属性是业务规则的一个函数,因此视图中的删除按钮对于某些条目是禁用的 - 但规则本身未包含在视图中。

该模型最终是您数据的守门人。您应该能够在不触及UI的情况下测试业务逻辑。


在我看来,术语业务逻辑不是一个精确的定义。 Evans在他的书"领域驱动设计"中谈到了两种类型的业务逻辑:

  • 域逻辑。
  • 应用逻辑。

在我看来,这种分离更加清晰。并且认识到存在不同类型的业务规则也意识到它们并非都必须在同一个地方。

域逻辑是对应于实际域的逻辑。因此,如果您正在创建会计应用程序,那么域规则将是关于帐户,过帐,税收等的规则。在敏捷软件规划工具中,规则将类似于根据积压中的速度和故事点计算发布日期,等等

对于这两种类型的应用程序,CSV导入/导出可能是相关的,但CSV导入/导出的规则与实际域无关。这种逻辑是应用逻辑。

域逻辑肯定会进入模型层。该模型还将对应于DDD中的域层。

但是,应用程序逻辑不一定必须放在模型层中。这可以直接放在控制器中,或者您可以创建一个托管这些规则的单独应用程序层。在这种情况下最合乎逻辑的取决于实际应用。


A1:业务逻辑在MVC中转到Model部分。 Model的作用是包含数据和业务逻辑。另一方面,Controller负责接收用户输入并决定做什么。

A2:A Business RuleBusiness Logic的一部分。他们有has a的关系。 Business LogicBusiness Rules

看看Wikipedia entry for MVC。转到概述,其中提到了MVC模式的流程。

另请参阅Wikipedia entry for Business Logic。提到Business LogicBusiness RulesWorkflow组成。


这是一个已回答的问题,但我会给出"一分钱":

业务规则属于模型。
"模型"总是由(逻辑上或物理上分开)组成:

  • 表示模型 - 一组非常适合在视图中使用的类(它是针对特定的UI /演示而定制的),
  • 域模型 - 模型的UI独立部分,和
  • repository -"模型"的存储感知部分。

业务规则存在于域模型中,以适合表示的形式公开于"表示"模型,有时在"数据层"中复制(或强制执行)。


正如一些答案所指出的,我认为对多层与MVC架构存在一些误解。

多层体系结构涉及将应用程序分解为层/层(例如,表示,业务逻辑,数据访问)

MVC是应用程序表示层的架构风格。对于非平凡的应用程序,不应将业务逻辑/业务规则/数据访问直接放入模型,视图或控制器中。这样做会将业务逻辑放在表示层中,从而减少代码的重用和可维护性。

该模型是放置业务逻辑的非常合理的选择,但更好/更易维护的方法是将表示层与业务逻辑层分离,并创建业务逻辑层,并在需要时简单地从模型中调用业务逻辑层。业务逻辑层将依次调用数据访问层。

我想指出,在一个MVC组件中找到混合业务逻辑和数据访问的代码并不罕见,特别是如果应用程序没有使用多个层构建。但是,在大多数企业应用程序中,您通常会在表示层中找到具有MVC体系结构的多层体系结构。


将业务层放在模型中用于MVC项目是没有意义的。

假设您的老板决定将表示层更改为其他内容,您会被搞砸!业务层应该是一个单独的程序集。模型包含来自业务层的数据,该数据传递到要显示的视图。然后在帖子上,例如,模型绑定到驻留在业务层中的Person类,并调用PersonBusiness.SavePerson(p);其中p是Person类。这是我的工作(BusinessError类缺失但也会在BusinessLayer中):enter image description here


Q1:

业务逻辑可以分为两类:

  • 域逻辑,例如电子邮件地址上的控件(唯一性,约束等),获取发票产品的价格,或者根据产品对象计算shoppingCart的总价格。

  • 更广泛和复杂的工作流程,称为业务流程,例如控制学生的注册流程(通常包括几个步骤,需要不同的检查,并且具有更复杂的约束)。

  • 第一类进入模型,第二类属于控制器。这是因为第二类中的案例是广泛的应用程序逻辑,并且将它们放在模型中可能会混合模型的抽象(例如,我们不清楚是否需要将这些决策放在一个模型类或另一个模型类中,因为它们是相关的二者皆是!)。

    请参阅此答案,了解模型和控制器之间的具体区别,此链接用于非常精确的定义,此链接也是一个不错的Android示例。

    关键在于,上面"Mud"和"Frank"提到的注释都可以是真实的,并且"Pete"(业务逻辑可以根据业务逻辑的类型放在模型或控制器中)。

    最后,请注意MVC因上下文而异。例如,在Android应用程序中,建议使用一些与基于Web的定义不同的替代定义(例如,请参阅此文章)。

    Q2:

    业务逻辑更通用,(如上所述,"decyclone")我们之间有以下关系:

    business rules ? business logics


    Model = CRUD数据库操作的代码。

    Controller =响应用户操作,并将用户的数据检索请求或删除/更新传递给模型,具体取决于组织特定的业务规则。这些业务规则可以在辅助类中实现,或者如果它们不是太复杂,则直接在控制器操作中实现。控制器最终要求视图自我更新,以便以新显示的形式向用户提供反馈,或者像"更新,谢谢"等消息,

    View =基于模型查询生成的UI。

    关于业务规则应该去哪里,没有严格的规则。在一些设计中,它们进入模型,而在其他设计中,它们包含在控制器中。但我认为最好将它们与控制器保持一致。让模型只关心数据库连接。