MVC中的业务逻辑


183

我有两个问题:

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

Q2。“业务逻辑”与“业务规则”相同吗?如果没有,有什么区别?

如果您可以举一个小例子来解释,那将是很好的。

Answers:


173

模型中包含业务规则。

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

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

该模型最终是您数据的看门人。您应该完全可以测试业务逻辑,而无需触摸UI。


5
谢谢你的例子。对于管理员的电子邮件条目(控制是否可以删除),我们是否可以使用控制器来控制?
hmthur

2
@mud如果我们将模型划分为两层,即服务层和存储库...服务层负责业务逻辑,存储库负责数据层...怎么办?

3
@PeterMatisko“模型只能携带数据。” 您不了解M在“ MVC”中的含义。V纯粹是陈述。C是表示和模型之间的粘合剂。(实际上,“ VC”通常被认为是表示层,并且MVC的流行变体,例如MVVM-Model View Viewmodel-使其更加清晰。)M就是其他一切:所有数据逻辑您的应用程序。您可以将数据和业务逻辑隔离在这一层中,并且可以将该层的数据部分称为“模型”,但这并不是“ MVC”中的“ M”所指的。

1
@PeterMatisko “在laravel中,人们将所有东西都扔进了控制器或模型中。糟糕的架构。” 不好怎么办?请明确点。“ V”表示“视图”。并非视图的所有内容都必须以“ M”或“ C”表示。 “ MVC仅仅是不够的,它没有明确地谈论业务逻辑及其放置位置当然可以。“ M”是您的应用程序的模型,它是您的数据,围绕它的业务逻辑以及所有非表示形式的内容。“ V”和“ C”是表示层,用户输入和输出。

2
@Mud问题在于,laravel仅将“模型”称为数据载体。当教程说Laravel使用MVC,然后您看到“模型”具有非常特定的用途时,您最终不知道在何处放置业务逻辑。唯一合理的地方是控制器,这不好。我没有做这个,我只是评论了我经常看到的典型的laravel项目(和教程)。
彼得·马蒂斯科

190

全部:
我相信您正在混淆MVC模式和基于n层的设计原则。

使用MVC方法并不意味着您不应该对应用程序进行分层。
如果您将MVC更像是表示层的扩展,则可能会有所帮助。

如果将非表示形式的代码放在MVC模式中,您可能很快就会陷入复杂的设计中。
因此,我建议您将业务逻辑放在单独的业务层中。

看看以下内容:Wikipedia关于多层体系结构的文章

说:

如今,MVC和类似的模型视图呈现器(MVP)是“关注分离”设计模式,这些设计模式仅适用于较大系统的表示层

无论如何...当谈论企业Web应用程序时,从UI到业务逻辑层的调用应放置在(表示)控制器中。

这是因为控制器实际上处理对特定资源的调用,通过对业务逻辑的调用来查询数据,并将数据(模型)链接到适当的视图。

Mud告诉您,业务规则已纳入模型。
确实如此,但是他将(表示)模型(MVC中的“ M”)和基于层的应用程序设计的数据层模型混合在一起。
因此,将与数据库相关的业务规则放置在应用程序的模型(数据层)中是有效的。
但是,您不应将它们放在MVC结构化表示层的模型中,因为这仅适用于特定的UI。

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

让我为您形象化:


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


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


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


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

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

多数民众赞成在技巧...我希望这会有所帮助...

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

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

答案->不是!
好吧-确实可以,但不是完全。
这是因为MVC是1970年代后期针对Smalltalk-80编程语言开发的一种方法。那时,GUI和个人计算机非常少见,甚至还没有发明万维网!当今的大多数编程语言和IDE都是在1990年代开发的。那时的计算机和用户界面与1970年代完全不同。
在谈论MVC时,请记住这一点。
Martin Fowler写了一篇有关MVC,MVP和当今GUI的很好的文章。


10
+1可正确列出mvc和n层应用程序之间的差异。我开发的大多数企业应用程序都具有n层,并且仅将mvc用作表示层。
Retired_User

可以说1)在MVC(表示层)中查看模型2)一些C#技术(业务层)用于授权事务,核心业务规则逻辑。3)(数据访问层)中的存储库和工作单元,请指导可用于构建业务层的某些技术(或最佳实践模式),这些技术应自由允许并允许模型和存储库从表示层的控制器访问(上层)层)。基本上,我认为添加,删除,更新及其组合作为业务逻辑,应该保留在事务下。请为此散布一些光线。
Mark Macneil Bikeio '16

嗨,拉胡尔,如果我正确理解您的话,那么您是对的。CRUD操作基本上是业务交易的原子部分。我个人更喜欢使用像Hibernate这样的功能强大的OR映射器作为存储库,而不是构建自己的。那是因为休眠已经在内部实现了工作单元模式。另外,我通常将业务交易放入单独的业务服务中。
弗兰克

对于视图模型,我可以为您提供以下示例:仅在图像中有一个带有双列表视图的GUI。此双列表视图使用双列表视图模型作为其数据模型。该数据模型只是两个简单列表的组合。因此,与用于创建视图模型的两个简单列表不同,双列表视图模型依赖于表示层的实现,因为它不是域模型的一部分。根据要创建的GUI,在某些情况下,可能需要将特定于视图的模型绑定到视图而不是域模型。
弗兰克

业务规则/逻辑部分很难解释。为了开始任何数据处理,您可以从您的一项服务中调用一个方法。这意味着您基本上开始了交易。如果此方法包含业务逻辑,则将其称为“事务脚本”。这通常是一件坏事,因为它几乎不可重用。如果此方法调用您的域模型的业务逻辑,那将更好。这意味着必须以一种能够包含业务逻辑的方式来设计您的域模型。这种域驱动的方法不适用于不完整或错误的域模型。
弗兰克

73

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

  • 域逻辑。
  • 应用逻辑。

我认为这种分离要清晰得多。随着人们意识到存在不同类型的业务规则,人们也意识到它们不一定都走在同一个地方。

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

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

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

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


1
这是真的!这里有两种模型:视图模型和域模型。我认为几乎不幸的是,MVC项目的布局使新手开发人员认为他们应该将代码填充到View Model中。
乔纳森(Jonathan)

1
发现您的答案更容易接受和理解。谢谢。
雷沃

27

A1:业务逻辑Model参与其中MVC。的作用Model是包含数据和业务逻辑。Controller另一方面负责接收用户输入并决定要做什么。

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

看一看Wikipedia entry for MVC。转到概述中提到MVC模式流的地方。

也看看Wikipedia entry for Business Logic。提到Business LogicBusiness Rules和组成Workflow


16

正如几个答案所指出的那样,我相信对多层vs MVC体系结构会有一些误解。

多层架构涉及将您的应用程序划分为多个层/层(例如,演示,业务逻辑,数据访问)

MVC是应用程序表示层的体系结构样式。对于非平凡的应用程序,不应将业务逻辑/业务规则/数据访问直接置于模型,视图或控制器中。为此,需要在表示层中放置业务逻辑,从而减少代码的重用性和可维护性。

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

我想指出,在MVC组件之一中找到将业务逻辑和数据访问混合在一起的代码并不少见,特别是如果应用程序不是使用多层设计的。但是,在大多数企业应用程序中,通常会在表示层中找到具有MVC架构的多层架构。


2
关于此事的最佳答案。应该投票更高。最差的答案被标记为已接受。
彼得·马蒂斯科

最佳答案..毫无疑问
Salman

这是否取决于数据和应用程序的大小?对于一个小型应用程序,我猜所有逻辑都可以毫无疑问地进入模型。如果是这样,开始划分为单独的层的大小阈值是多少?
mLstudent33

15

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

业务规则属于模型。“模型”始终由(逻辑上或物理上分开)组成:

  • 表示模型 -一组非常适合在视图中使用的类(针对特定的UI /表示而定制),
  • 域模型 - 模型的UI独立部分,以及
  • 存储库 -“模型”的存储感知部分。

业务规则存在于域模型中,以适合演示的形式展示给“演示”模型,有时在“数据层”中被复制(或强制执行)。


5

将您的业务层放入MVC项目的模型中没有任何意义。

假设您的老板决定将表示层更改为其他内容,那您将被搞砸了!业务层应为单独的程序集。模型包含来自业务层的数据,该数据传递给视图以显示。例如,然后在发布时,模型绑定到位于业务层中的Person类,并调用PersonBusiness.SavePerson(p);。其中p是Person类。这是我的工作(缺少BusinessError类,但也会在BusinessLayer中使用):在此处输入图片说明


您能否澄清这一说法?“ 模型包含来自业务层数据,数据传递给视图以显示。”
Anthony Rutledge,

2

Q1:

业务逻辑可以分为两类:

  1. 领域逻辑,例如电子邮件地址上的控件(唯一性,约束等),获取发票产品的价格,或基于其产品对象计算shoppingCart的总价。

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

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

看到这个答案的模型和控制器之间的具体区别,这个环节非常精确的定义,也该链接为一个不错的Android例子。

关键是上面“ Mud”和“ Frank”提到的注释既可以是真实的,也可以是“ Pete”的(根据业务逻辑的类型可以将业务逻辑放入模型或控制器中)。

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


Q2:

业务逻辑较为笼统,并且(如上文提到的“ decyclone”),它们之间具有以下关系:

业务规则⊂业务逻辑


0

您为什么不引入服务层。那么您的控制器将变得精简且更具可读性,那么您所有的控制器功能将成为纯粹的行动。您可以根据需要在服务层中分解业务逻辑。代码可重用性高。对模型和存储库没有影响。


-5

模型= CRUD数据库操作的代码。

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

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

关于应将业务规则放在何处,没有一成不变的规则。在某些设计中,它们进入模型,而在另一些设计中,它们包含在控制器中。但是我认为最好将它们保留在控制器中。让模型仅担心数据库连接性。


如果将业务规则放入控制器中并且您有很多很多动作-您将要多次复制业务规则吗?不会。您将使用帮助程序方法或某种类将其分开。将“事物”放入模型所属的模型中。
G. Stoynev

3
MVC不是用于CRUD数据库操作的应用程序模式(尽管可以通过这种方式使用),因此,模型不能是“用于CRUD数据库操作的代码”。该模型定义了应用程序的实体,包括数据和业务规则。控制器协调视图和模型之间的交互。该视图是用户界面,它公开了模型以及控制器公开的模型中的可用操作。
乔恩·戴维斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.