0

我有一个Agenda持有 many Card,并且 aCard有 multipleDetailItem持有一个像Email,Phone和 aLabel

所以,我可以这样做:

agenda = new Agenda()

oneCard = new Card()
item = new DetailItem(new Email("x@y.z"), new Label("Work")
oneCard.addItem(item)

agenda.addCard(oneCard)

按照规则,只能有一个具有“x@yz”值DetailItemEmail实例,因此如果您尝试使用该数据添加一个新项目,它将引发异常。

在我尝试更新DetailItem. 我找不到让我觉得舒服的方法。

我试着从商业模式而不是实现细节的角度来思考,但我不能长时间搁置它们,它们进入了我喜欢或不喜欢的领域。

问题是我将拥有一个 REST 接口,并且我有两种做事方式。

  1. /cards/<cardId>使用新detailItems' array, fetch the 卡发送一个by ID, create a newPUT with the new data provided in the PUT, and sync the current
  2. 将 PUT 发送到 /cards//items/,获取Card,找到DetailItem,并以与选项 1 中相同的方式更新它

如果我选择选项 1,我必须DetailItem从当前Card中删除所有新选项中不存在的内容。这导致一些由 ORM 生成的 INSERT 查询和一些 DELETES。根本没有更新。

如果我选择选项 2,我将有许多 PUT 来更改多个项目,这根本不具备性能,它会导致我向其中引入一个 ID 字段,DetailItem以便我可以识别它们,这引入了一些不属于领域!。

我发现的唯一选择是使用选项 1,并发送如下请求:

{
  ...
  detailItems: [
    {
      type: "email",
      oldValue: "x@y.z",
      oldLabel: "Work",
      newValue: "a@b.c",
      newLabel: "Work",
    }
  ]
}

所以我可以做这样的事情:

card = agenda.getCardIdentifiedBy(the_identifier)

for(itemUpdate in jsonData.detailItems)
  itemClass = ValueClassMapper.from(itemUpdate.type) // "email" -> Email
  oldItem = new DetailItem(new itemClass(itemUpdate.oldValue), new Label(itemUpdate.oldLabel))
  newItem = new DetailItem(new itemClass(itemUpdate.newValue), new Label(itemUpdate.newLabel))
  card.updateItemWith(oldItem, newItem)

但是,我不知道,也许我有一个错误的抽象有人可以帮忙吗?提前致谢!

4

1 回答 1

0

您在这里遇到的部分问题是 HTTP 远程创作语义与自治域模型的概念不一致。

HTTP PUT的意思是“使您的本文档副本看起来像我的本文档副本”。它类似于“保存文件”或“将这些行提交到数据库”。请求的语义适合贫血数据存储的模型。

另一方面,我们的领域模型通常是自治状态机,它们希望根据新信息自行决定应该转换到什么状态。换句话说,所有域模型交互大致遵循以下模式:

domainModel.change(newInformation)

然后模型会根据这些信息更改自己的数据结构(应用程序代码负责将新信息解析为领域模型可以理解的数据结构)。

这并不意味着您不能将 HTTP 和 REST 与域模型一起使用;但这确实意味着资源模型看起来与您在此处描述的非常不同。

最直接的方法是将新信息发布到您的议程资源(自治域实体确实不希望您尝试直接修改其内部)。

POST /agenda/12345
Content-Type: application/json

{
  ...
}

然后,您的应用程序负责解析请求的正文,然后将该解析的表示传递给您的议程域实体,然后域实体将决定如何/是否将新信息与它已经知道的信息集成关于。

另一种方法是将新信息视为要存储的新文档,其中每个新文档都有自己的 URI:

PUT /messages/67890
Content-Type: application/json

{
  ...
}

其中更改/agenda/12345是存储消息的副作用 - 请参阅Webber 2011。请注意,这种方法会使缓存失效更具挑战性。

于 2020-12-13T18:53:06.997 回答