与dto一起使用DDD构建API

时间:2016-12-19 09:16:04

标签: api architecture domain-driven-design dto hexagonal-architecture

我开始使用dto(数据传输对象),我对构建API系统架构的最佳方法有所怀疑。

想象一个域实体' A'与' B'' C'和' D'。我们提供服务' S'返回一个包含所有" A' s"的json列表。创建一个' ADTO'是对的。在该服务中,填写" BDTO"," CDTO""和" DDTO"?如果那时我们有另一项服务" S2",我们需要返回一组特定的" B"然后我们需要创建另一个" B2DTO& #39; S"与" C2DTOS"," D2DTO"" ...?这是正确的方法吗?

我看到这样,我们将拥有一个巨大而复杂的DTO树,每个用例都有一个特定的DTO。

修改

我忘记了装配工的一部分。是否有必要为每个DTO实现不同的汇编程序?例如,对于实体A,我们有两个DTO。我可以使用相同的汇编程序,还是更好地使用A1Assembler和A2Assembler?

2 个答案:

答案 0 :(得分:1)

我认为你误解了你的DTO是什么。粗略地说,你会有两种DTO 1)它们可以是您的域实体,然后您可以返回ADTO,BDTO和CDTO。但是那些DTO可以相当一致(为什么B2DTO与BDTO有任何不同)

如果你看看你的json会看什么

{
 Id: 1
 name: "foobar",
 $type: "A",
 B: [ {
      name: "b-bar",
      $type: "B"}]
 CIds: [ 2,23, 42]
}

在这里,您可以看到2种对象,其中一些(B' s)在您的DTO中作为子对象完整返回。其他(如C)由Id转换,可以单独查询。如果它实施了C查询的S2,你就不在乎。

2)当你进入像CQRS这样的架构时,你会得到不同的DTO。 (投影或命令),但你也会在DTO的命名中看到这一点。例如是 AListOnOverviewPageDTO,AUserEditDetailDTO等

现在拥有不同的DTO是非常有意义的,因为它们是代表非常不同的用例的投影。 (而不是DDD中常见的完整对象)

更新您想要不同DTO的原因有两个。首先,它允许您单独优化每个呼叫。也许列表需要更快(使用CQRS),您可以在数据上放置正确的索引,以便更快地返回listDTO。它允许您更轻松地推断使用情况。由于每个DTO代表1个用例/屏幕(否则你会在userlistDTO中得到正确的情况,我需要在这种情况下仅填充这3个字段..etc。)。 此外,您需要确保您的API是诚实的。永远不会回归'#34;年龄"具有空数据但具有一些其他呼叫的字段返回相同的用户但是具有另一个呼叫返回具有实际年龄的相同用户。它会让你的后端显得破碎。但是,如果我有/ users / list的调用以及对/ users / 1 / detail的另一个调用,那么如果详细调用返回了关于特定用户的更多字段,那将是很自然的

答案 1 :(得分:1)

您的DTO应代表您希望客户拥有的一组数据。通常,你永远不应该复制'您的实体进入DTO,因为您可能拥有不想与世界分享的字段。我们假设您正在自动创建跟踪'具有输入该数据的ID的列,或者说您具有带密码字段的Customer实体。您不希望它成为您的DTO的一部分。这就是为什么在使用AutoMapper等时必须非常小心的原因。

当您设计DTO时,请专门考虑客户端从该端点需要什么。有时DTO可能看起来一样,而且没问题。此外,您的DTO可以根据需要简单或复杂。一个疯狂的例子,让我们说一个页面,你显示一个艺术家,他的歌曲,这些歌曲的投票率和一些额外的数据。

如果您的用例证明了这一点,您可以将所有这些都放入DTO中。他们所做的就是携带数据。

是的,您的服务应该返回DTOS(POCO)。

此外,DTO只是命名惯例。不要陷入" dto"后缀。 A'命令'来自客户端的是DTO,但在这种情况下,您可以将其称为AddNewCustomerCommand。

有道理吗?