【问题标题】:Is the Controller in MVC considered an application service for DDD?MVC 中的 Controller 是否被视为 DDD 的应用程序服务?
【发布时间】:2013-09-09 12:45:03
【问题描述】:

我正在为 MVC 的 M 部分应用 DDD,经过一些研究(正在学习!),我意识到我需要我的控制器与域服务(在模型中)进行交互。这将使我的控制器成为域服务的消费者,因此成为应用程序服务(在 DDD 术语中)。这是准确的吗?控制器和 DD 定义的应用服务有区别吗?

【问题讨论】:

    标签: model-view-controller domain-driven-design


    【解决方案1】:

    控制器在 DDD 中不被视为服务。控制器在 UI 层中运行。应用程序服务从数据库获取数据、验证数据、将数据传递给客户端(MVC 可以是客户端,但来自 winforms 应用程序的请求也可以)等等。

    控制器所做的只是为来自 UI 的请求提供服务。它不属于应用程序域。

    【讨论】:

    • 控制器通过将请求(或请求的相关部分)传递给模型来处理来自视图的请求。 MVC 是一种架构,绝对可以应用于 winforms 和 web 应用程序。我请求对控制器的位置有所不同。 View 绝对是唯一的 UI 层,MVC 的重点是让这个 UI 层与控制器分开。不过,您的观点很好;感谢您的回复。
    • -1。控制器是请求/命令协调器。在六边形架构中,控制器位于应用程序服务/命令处理程序/查询处理程序的正上方。控制器是一个请求翻译器,并与通信协议(上层)和命令/查询处理程序(来自下层的应用程序服务)耦合。控制器可以被视为应用程序服务外观,因为它们翻译和准备命令/查询/消息以供较低层(应用程序服务/命令查询处理程序)处理。
    • -1 因为控制器与 DDD 无关。将控制器放在哪里无关紧要,您可以说控制器只是消息/通信协调器,它们以两种方式耦合:ui 和应用程序服务。您可以在没有 UI(纯命令上下文)的有界上下文中拥有控制器。并且您可以有一个仅用于演示的有界上下文(一个仅用于查询 2 个或更多有界上下文的复合业务组件)。附言控制器与 UI 的耦合度很低,它们只需要一组请求参数,无论从哪里来。
    【解决方案2】:

    应用层位于领域层和表示层之间。控制器是表示层的一部分,向应用程序层发送命令或查询,应用程序服务使用域模型的服务和对象执行它们。所以控制器不同于应用服务,它们可能与实际的通信形式绑定,例如HTTP。你不应该直接从控制器调用域服务,这可能是错误代码的标志。

    Domain Driven Design: Domain Service, Application Service

    • 域服务:封装不适合域对象的业务逻辑,并且不是典型的 CRUD 操作 - 这些将属于存储库。
    • 应用程序服务:由外部消费者用来与您的系统对话(想想 Web 服务)。如果消费者需要访问 CRUD 操作,它们会暴露在这里。

    因此,您的服务可能是应用程序服务而不是域服务,或者某些部分应用程序服务,某些部分域服务。您应该检查并重构您的代码。我想 4 年后这并不重要,但我目前正在开发的应用程序也有同样的想法。这个应用程序可能太小而无法在其上使用 DDD,因此将控制器与应用程序服务混淆是这里过度设计的标志。

    何时开始添加更多层是一个有趣的问题。我认为每个应用程序都应该以某种domain model and adapters 开头以连接到该域模型。因此,如果应用程序足够简单,则可能不需要添加 2 层以上。但这只是一个想法,我对 DDD 的经验并不丰富。

    【讨论】:

      【解决方案3】:

      分层架构将应用程序拆分为 UI 层、应用程序层、领域层和基础设施层(Vaugn Vernons 实施领域驱动设计(位置 2901))。控制器属于这种更广泛的设计架构的“应用层”,因此将直接与模型中的域服务交互,并被视为应用服务。不仅如此,它显然还将使用可用的实体和聚合。

      【讨论】:

      • 如果你看 pg. 72 Evan 的 DDD 你会看到图 4.1 显示控制器是 UI 层的一部分。这是有道理的,因为如果 V 和 C 位于不同的层中,那么当层应该只通过间接和接口连接时,它们之间就会有紧密的耦合。
      • @Louis,我没有读过 Vaugn Vernons 的书,但我刚刚完成了一个成功的 DDD 项目。我只能说控制器在一个完全独立的项目中,即客户端项目。在我们的案例中,客户端是 MVC 前端。它可能是任何其他客户端。应用程序层是一个完全独立的项目,它独立存在。它有自己的验证器,可以通过 WCF 接口提供数据。 MVC 客户端中的控制器只是调用应用层的代理方法。除此之外,他们没有执行任何其他功能。
      • @Gordon V 和 C 可以通过使用被动视图或监督控制器来解耦。对于某些应用程序,耦合它们也不一定是一个坏主意。这在很大程度上取决于正在开发的应用程序的细节。根据您对埃文斯第 72 页的引用,我将收回我的答案,因为似乎还有其他方法与我的不同。感谢您的回复。我希望我们能够就 SO 进行良好的讨论,而不会因为没有建设性而关闭问题的风险;)
      • @Greg,您绝对可以拥有一个完整的 MVC 应用程序作为客户端。当您以 DLL 的形式使用设计良好的应用程序时,就会发生这种情况。 MVC 隔离了那段代码提供的功能。我的问题旨在检查较低的发展层次。如果您将 DDD 用作包含 MVC 架构的一部分,则控制器将用作应用程序层。如果您创建一个单独的应用程序层,您将复制很多(如果不是全部)控制器中的代码。如果是验证器:如果要验证输入,请使用控制器。如果是数据,请使用实体。
      • @Louis - 是的,这很快就会被关闭。正如您所说的那样,我们有大量重复的代码,但是当您构建完全相互独立的层时,这是可以预期的。任何代码共享都会产生依赖关系。我们无法使用控制器进行验证,因为该应用程序可能正在为已经编写自己的系统接口的客户端提供服务,因此在这种情况下,我们将无法控制客户端验证。这就是为什么必须在应用层重复验证的原因。
      【解决方案4】:

      DDD Reference 中根本没有提到控制器。所以我认为从 DDD POV 答案是不确定的。所以我会考虑更实际的问题:“我们是否需要分离控制器和应用程序服务”

      优点:

      • 将输入处理与用例实现分开。

      缺点:

      • 额外的间接层使对简单案例的理解变得复杂。 (通过许多层提取数据而不实际做任何事情来实现一些琐碎的事情也很烦人)。

      所以如果输入处理混淆了用例逻辑,我会选择控制器和应用程序服务的分离。如果两者都足够简单,我会选择将用例逻辑保留在控制器中,以便您可以轻松地在代码用例中看到与输入处理分开的情况。

      【讨论】:

        猜你喜欢
        • 2011-03-01
        • 1970-01-01
        • 2011-09-29
        • 2016-01-16
        • 2011-09-04
        • 1970-01-01
        • 1970-01-01
        • 2012-05-06
        • 2010-12-03
        相关资源
        最近更新 更多