【问题标题】:Application service responsability vs optimized DTO's应用服务责任与优化的 DTO
【发布时间】:2019-03-29 02:26:27
【问题描述】:

在我认为是 DDD 的三个原则之间,我感觉自己的 MPA ABP 应用程序开发陷入了困境:

  • 应用程序服务不必绑定到控制器。我的意思是控制器不必总是只使用一个应用程序服务。因为应用服务的概念没有呈现在脑海中
  • DTO 必须满足视图需要,以最大限度地减少 HTTP 数据传输。所以有时我们必须为每个实体/概念和每个视图设计一个 DTO 类。
  • 应用服务获取始终返回 DTO。

现在我有一个遵循 Master-Detail 原则的视图:从实体列表中选择 Master 部分中的一个实体通过 Ajax 调用加载 Details 部分中的实体详细信息。但是Master部分的实体选择是由Ajax同步的下拉列表级联进行的:ParentEntities > Entities。

什么选择尊重更好的 DDD?

  1. 把GetAllParent()、GetAllEntities(parentId)和GetEntity(id)全部放在MyViewApplicationService中,那么我的应用服务就可以返回优化的DTO来满足我的视图需求,但是违反了DDD原则强>,
  2. 将这三种方法中的每一种都放在不同的应用程序服务中,在脑海中隔离更多“领域”,但 DTO 是面向领域的,有点通用。所以DTO 没有优化
  3. 让控制器负责映射到适合视图需求的 DTO,但不应该这样做

【问题讨论】:

    标签: domain-driven-design aspnetboilerplate


    【解决方案1】:
    • 应用程序服务不必绑定到控制器。我的意思是控制器不必总是只使用一个应用程序服务。 因为应用服务概念没有考虑到呈现。

    应用程序服务不依赖于客户端类型,而是依赖于客户端需求。它们返回客户端需要的数据,因此从这个意义上说,应用程序服务考虑到了客户端(表示)。

    • 应用程序服务始终获取和返回 DTO。

    并非总是如此。正如 Vaughn Vernon 在他的《实施 DDD》一书中(第 512 页)所说,还有 DTO 的替代方案:

    • 调解员

    • 域负载对象

    • 状态表示

    • 用例优化存储库查询(对 CQRS 关闭)

    • 数据转换器

    什么选择尊重更好的 DDD?

    1. 把GetAllParent()、GetAllEntities(parentId)和GetEntity(id)都放到MyViewApplicationService中,那么我的应用服务就可以返回了 针对我的视图需求优化了 DTO,但违反了 DDD 原则,

    您不应根据客户端技术 (MyView) 命名应用程序服务,而应根据它提供的功能来命名。

    1. 将这三种方法中的每一种都放在不同的应用程序服务中,记住更多的“域”,但 DTO 是 面向领域,有点通用。所以 DTO 没有优化。

    如果您将这 3 种方法放在一个服务中,或者您为每种方法提供一个服务,这并不重要。无论如何,控制器都应该调用它们。

    1. 让控制器负责映射到适合视图需求的 DTO,但它不应该这样做。

    如果您的意思是应用程序服务返回域对象并且控制器将它们转换为 DTO,那么不,您不应该这样做,因为您将域公开给客户端。

    【讨论】:

      【解决方案2】:

      我想我理解你的问题,让我们从头开始:

      ...把GetAllParent()、GetAllEntities(parentId)和GetEntity(id)都放到MyViewApplicationService...

      商务人士会理解其中哪些词?这些词中的任何一个是无处不在的语言的一部分吗?

      它们当然都是纯技术的,因此应该是细节,不应该影响架构。基本上他们会在错误的地方,他们根本不应该是可见的。

      ...但是 DTO 是面向领域的,有点通用。所以 DTO 没有优化...

      DTO 不应该是任何远程面向对象的一部分。但是,您并没有说您想要面向对象,所以我们不要纠缠于此。

      不过,如果您的对象应该是面向领域的,那么为什么它不适合(未优化)专门为该领域编写的应用程序?

      我认为问题在于您的“对象”实际上是在建模与域不同的东西。它可能对数据库表或其记录进行建模。

      我的意思是,如果您要显示产品的配置文件,那么您的“对象”应该是 ProductProfile,而不是通用的 Product。或ProductDetails,或ProductHeroImage,等等。 那些东西是 领域的,也可能在需求文档中提到。

      让控制器负责映射到适合视图需求的 DTO,但它不应该这样做。

      为什么不应该这样做?如果您的功能的目的是向用户显示一些数据,那么为什么不将其视为“业务功能”。我的意思是它应该是相反的。 “视图”是您想要的业务功能,以及数据库/存储库/控制器/服务或任何“只是”技术,应该只是一个细节,在架构中不可见。

      免责声明:我必须承认,这些观点并不是大多数项目在 DDD 下所做的,但也许你会发现它在未来对这些项目提出更多质疑。:)

      【讨论】:

      • 我知道商务人士无法理解“GetAllParent()、GetAllEntities(parentId) 和 GetEntity(id)”。我想在我的问题中保持通用性。
      • 使用 ABP,控制器可以从应用程序服务中获取 DTO。我不认为控制器被“允许”重新映射到更合适的 DTO。我的意思是:DTO 只包含视图需要的数据,以最小化 HTTP 流量。
      • 好的,如果框架强制做出这些决定,那么您真的无能为力了。但是,这听起来确实很像面向技术的解决方案,而不是面向领域的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2019-01-30
      • 2010-12-06
      • 1970-01-01
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      相关资源
      最近更新 更多