【问题标题】:In a MVC application, should the controller or the model handle data access? [closed]在 MVC 应用程序中,控制器或模型应该处理数据访问吗? [关闭]
【发布时间】:2025-11-22 19:30:01
【问题描述】:

我们公司正在就应该在哪里调用业务逻辑来执行 CRUD 操作进行一些哲学辩论。

我认为模型应该包含您的数据结构,并且控制器应该负责填充数据。

我的同事认为所有填充都应该在模型类本身中完成,并由控制器简单地调用。这使控制器保持整洁(但在我看来,会使模型混乱)。

他还认为,任何返回 Json 对象的调用都应该发生在模型中,而不是控制器中。模型会向控制器返回一个数组,然后控制器会将其作为 Json 对象返回。

每种方法有哪些不同的优点/缺点,是否有正确或错误的方法?

【问题讨论】:

  • 好。让我们知道您所在的项目/框架/平台的类型应该会更好地帮助我们。

标签: model-view-controller


【解决方案1】:

模型应该处理数据访问。

来自MSDN

模型。模型对象是应用程序中实现的部分 应用程序数据域的逻辑。通常,模型对象 在数据库中检索和存储模型状态。例如,一个产品 对象可能会从数据库中检索信息,对其进行操作,然后 然后将更新的信息写回 SQL 中的 Products 表 服务器数据库。

【讨论】:

    【解决方案2】:

    所有业务逻辑都应该在MODEL中。

    记住,每一层的职责是:

    • 控制器 - 模型和视图之间的桥梁。决定下一步去哪里
    • 查看 - 显示数据,收集用户输入
    • 模型 - 业务逻辑、数据存储接口。

    最大的收获之一是维护和(后来的)扩展。一般来说:

    • 如果您需要更改业务逻辑,则不需要修改控制器或视图。
    • 如果您更改视觉显示,则无需修改模型或控制器。
    • 如果您更改工作流程,则无需修改视图或模型。

    要执行上述操作,每一层都应该不了解其他层才能正常工作。例如,view 应该接收它的数据,并且不需要知道它来自哪里以正确显示它。 控制器 不需要了解模型的底层结构就可以与之交互。 模型应该不知道如何显示数据(例如,格式化)或工作流程。

    “他还认为,任何返回 Json 对象的调用都应该发生在模型中,而不是控制器中。模型会向控制器返回一个数组,然后控制器会将其作为 Json 对象返回。”

    没有。模型不应该格式化数据。它也不应该读取格式化的数据。那就是污染模型并进入business logic = display logic的地狱级别。

    JSON(进来或出去)只是另一种观点。所以出去吧:

    Data Store -> Model -> Controller -> View
    

    进来:

    View -> Controller -> Model -> Data Store
    

    【讨论】:

    • 感谢所有伟大的 cmets。很难选择一个“正确”的答案,因为它们都是正确的,但 Bryan 似乎是最完整的。
    • “模型 - 业务逻辑,数据存储接口”和“模型不应该格式化数据。它也不应该读取格式化数据。”那么当您有需要添加到数据库的 json 数据时会发生什么?显然,您的逻辑中的模型不应该接受就是这样,json。所以应该重新设计。通过谁?通过一个接口进入模型。但是您刚刚说接口是....“模型...(是)数据存储接口”。那里至少有一个看似矛盾的地方需要解决或澄清。
    • 哇,如果有一个你写的小项目示例,那肯定会很好。我认为这对我来说会很清楚。即使只是名称和地址示例..
    • 在 PHP 中,模型不能做$stmt->fetch(PDO::FETCH_CLASS, $this)。我可以通过$this->id = $object->id 手动转换所有属性,但它可能真的很长并且不容易维护(如果有任何列更改)。这是否意味着 PHP 希望我们在控制器中进行查询?或者有什么合适的代码可以替换:$stmt->fetch(PDO::FETCH_CLASS, $this)?
    • 许多 MVC 指南声称用户输入必须在控制器内部...
    【解决方案3】:

    在 MVC 中,模型负责处理数据访问。优点是所有数据访问代码都由模型逻辑封装。如果您在控制器中包含数据访问代码,您将膨胀控制器并破坏 MVC 模式。

    【讨论】:

      【解决方案4】:

      你的控制器方法应该尽可能的精简,这意味着数据访问属于模型(或者更具体地说,是一个 Repository 对象)。

      把你的控制器方法想象成一个开关场......它们只负责将任务委派给其他方法执行。

      如果您在控制器中编写任何 Linq 代码,则您正在创建一个依赖项,如果您的站点结构发生更改,则必须对其进行修改,并且您可能会复制数据访问代码。但是模型中的GetCustomer 仍然是GetCustomer,无论您从控制器的哪个位置调用它。这有意义吗?

      比简单地访问数据更广泛的业务逻辑可以放入它自己的业务逻辑层,这被认为是模型的一部分。

      我不太确定 JSON。 JSON 只是一种替代数据表示;如果您有一个实用方法可以将您的数据类转换为 JSON,请从模型中调用 GetCustomer,然后在您的控制器方法中执行到 JSON 的转换。

      【讨论】:

        【解决方案5】:

        仅供参考,我的主要语言是 PHP,所以你可以对这一切持保留态度。

        MVC 和受 MVC 启发的模式中的业务业务逻辑必须位于 模型 层中。是的,模型应该是一个层,而不是一个类或对象。

        大部分上述逻辑将驻留在domain objects 中,但其中一些最终会在services 中,这应该类似于模型层中的“*”结构,通过该表示层(视图和控制器)与模型层交互。

        服务还应该促进存储抽象(data mappersdata access objectsunits of work 和/或repositories)与域对象之间的交互。这些结构将处理持久和临时存储并处理数据完整性。

        这种分离简化了代码库的维护和测试。您无需接触数据库(或任何其他形式的存储)即可轻松测试域逻辑。

        控制器(以及来自其他 MVVM 和 MVP 模式的等效结构)应该从用户请求中提取信息并更改模型层(通过使用服务)和视图的状态。

        如果您实现 MVP 或 MVVM,那么类似控制器的组件将承担额外的职责,包括从模型层到视图的数据传输,但在经典和 Model2 MVC 模式中,视图应该是一个主动结构,它从模型层请求数据。

        至于 JSON 的生成,这实际上应该发生在视图中。 视图 应该包含所有(或大部分,取决于您使用模板的方式)演示逻辑。它应该从模型层(直接或通过中介)获取信息,并基于该信息生成响应(有时从多个模板创建它)。 JSON 只是一种不同的响应格式。


        2005 年发布的 Rails 框架产生了巨大的影响(而且大部分是负面的)。它的最初目的是成为原型设计框架——快速创建一次性代码。为了实现这一点,他们将模式简化到了关注点分离被破坏的程度。

        他们用活动记录结构的集合替换了模型层,这很容易在控制器中生成和合并视图功能,留下模板作为完整视图的替代品。它是最初目标的完美解决方案,但是当它开始在其他领域传播时,引入了大量对 MVC 和 MVC 启发的设计模式的误解,例如 “视图只是一个模板” 和 “模型是 ORM”.

        【讨论】:

          最近更新 更多