【问题标题】:Where is business logic situated in MVC pattern?MVC 模式中的业务逻辑在哪里?
【发布时间】:2011-05-30 09:30:24
【问题描述】:

我使用 Zend 框架和 Doctrine。在许多项目中,业务逻辑都内置在 控制器 中。这种方法对我来说似乎是错误的。

我见过的最好的设置是使用服务层,这是编写业务逻辑的地方。我所要做的就是创建一个表单,对其进行验证,并在服务层中使用一些业务逻辑。结果验证、业务逻辑和使用一种方法(例如:newProduct($postData))。

在 MVC 中组织业务逻辑的正确方法是什么?也许我需要看一些书,或者看一些源代码示例。

【问题讨论】:

  • MVC 控制器和模型:*.com/questions/467113/…
  • 将 MVC isn't applicable 组织到 Web 框架的一种“真正的方式”。所以,不要尝试。另请参阅 MVP,它已取代 "MVC"
  • @mario:该模式可以通过位于其顶部的请求/响应模式来很好地维护(提供 Web 存在并掩盖下面对 MVC 更友好的域逻辑)。但是开发人员需要敏锐地意识到两者之间的分离。而且我同意 MVC Web 框架本身试图隐藏这一点并使自己有点用词不当。每当潜在雇主问我是否“了解 MVC”并且我知道他们在谈论 ASP .NET MVC 框架时,我觉得有义务提出这一点 :)

标签: php model-view-controller zend-framework symfony1


【解决方案1】:

我不能说 Zend 框架(或者你正在使用它构建的任何东西),但在 MVC 模式中,业务逻辑通常属于模型。

您之前可能听过这样的说法,即您应该“保持控制器轻便而模型重”(或其一些变体)。这个想法是模型是你的领域(你无处不在的语言),所有的业务逻辑都应该在它们和它们的交互中进行编码。控制器只是 MVC 中的事件处理程序,用于接收请求并将这些请求转换为模型。

编辑:(回应您的评论)- 恐怕我们在这里遇到了语言障碍。但是,为了补充一点并希望在您自己构建模型和数据作为主要方面对您有所帮助,请考虑 Eric Raymond 的一句话:“智能数据结构和愚蠢的代码比其他方式工作得更好。”

这个想法是,“逻辑”存在于您的数据结构中,由此您可以构建一个“丰富”的域模型,其中包含逻辑和功能。这与“贫血”域模型相反,后者只是平面数据结构(或 DTO),仅表示数据状态并且没有任何功能。

使用智能数据结构,使用它们的代码(将在您的控制器以及其他各种地方)不需要复杂或复杂。它只需要告诉模型发生了什么并指导他们做他们需要做的事情。模特们拥有真正做到这一点的所有诀窍。

这比“智能代码和愚蠢的数据结构”更受欢迎,因为模型是贫血的 DTO(它们有它们的用途,不要误会我的意思),并且所有逻辑都采用更程序化的格式,每个过程都需要拥有执行手头业务任务的所有专业知识。这会导致大量代码重复。

我希望这会有所帮助。正如我所说,我很难理解您问题的全部范围。

编辑:另一件要考虑的事情,因为我不确定您将“数据是主要”问题放在哪里。 “数据结构”和“数据持久性”之间存在差异,这种差异在这里绝对至关重要。你的数据结构就是你的模型,丰富了业务逻辑。您的数据持久化就是数据库中的数据。

很多时候(如果你问我的话,这太常见了),这些概念在编程中会被混淆。在大多数自动生成的代码和有用的框架以及所有这些东西中,“模型”倾向于直接映射到数据库表并简单地表示这些表中的记录。这并不总是错误的,但它具有误导性。

业务逻辑不在数据库中。它不在数据的平面表示中。当然,数据库可以包含它自己的持久性逻辑(例如引用完整性、触发器、业务逻辑代码不知道的审计等),但它不包含您通常在流程图中看到的业务流程业务逻辑。

对于任何给定框架的标准操作程序,这些概念可能会打破常规。正如我所说,我真的不能为框架说话。但就我个人而言,我倾向于提倡“好代码”而不是“流行使用给定工具”。

【讨论】:

  • 是的,我更感兴趣的组织重模型的真正方式是什么? ZF 让我们自己构建模型。 Doctrine 通过模式 Data Mapper + 自己的 ServiceLayer 帮助我们,看起来不错。但是在这种方法中,数据是主要的,业务逻辑依赖于数据,扩展系统存在问题。
  • 我之前投了赞成票,只是随机阅读了这个问题——想再次投赞成票!很好的答案:-)
  • @richsage:谢谢。我觉得我在这个方面获得了一些动力。也许我应该继续修改它并把它变成一篇博文。
  • @David - 请这样做,这会很好。我已经开始从 Doctrine 1 迁移到 Doctrine 2,根据您的回答,数据结构/持久性现在是分开的。来自 Doctrine 1 “model-is-a-db-record” 的哲学有点令人困惑!
  • @richsage:请记住,在域设计中真正无知持久性是危险的,因为您可能在逻辑上将自己描绘成一个角落并损失很多性能。在设计项目时,我发现最好的方法当然是首先设计业务域,但偶尔会退后一步,考虑持久性和其他依赖关系,以寻找需要做出的任何妥协。
【解决方案2】:

我将提供一些我对 MVC 模式编码的看法。对于懒惰的程序员来说,很容易弄乱控制器和模型之间的代码。

以下是我的文件夹结构:

  1. 控制器:应该轻巧干净,这里唯一要做的就是确定应该加载哪些模型或视图来响应请求。
  2. Views:甚至认为它可以直接访问模型,但我更喜欢通过控制器来完成。并保持 html 干净。
  3. 模型:做了所有的事情,但分成文件夹。
    • 类/对象:包含基于数据库架构的所有对象。
    • Repository/Factory:包括查询、插入、更新和删除方法。仅将一个文件映射到一张表。
    • 服务:业务逻辑、登录、注销或与数据库无关的所有内容,甚至将表连接在一起并返回结果。
    • Utils:基于 Repository/Factory 的静态视图方法。

希望对您有所帮助!并欢迎任何建议。

【讨论】:

    【解决方案3】:

    我会说业务层是控制器的一部分,因为它包含使用户能够与视图和模型进行交互的所有组件。从应用数据和业务规则的检索、处理、转换甚至管理。

    【讨论】: