c# - 通过 REST 进行 DDD 更新

标签 c# asp.net-web-api2 domain-driven-design

我是 DDD 的新手,我正在尝试找出一种使用 PUT 动词来更新聚合的方法。

如果聚合中的所有属性都有私有(private) setter ,那么很明显我需要为每个业务需求设置一组功能。举个例子

supportTicket.Resolve(); 

我很清楚,我可以使用诸如 /api/tickets/5/resolve 之类的端点来实现这一点,但是如果我想提供一种自动更新整个票证的方法怎么办?

例如,用户可以使用以下主体向 /api/tickets/5 发出 PUT 请求

{"status" : "RESOLVED", "Title":"Some crazy title"}

我需要在 ApplicationSercvice 中做这样的事情吗

if(DTO.Status != null && dto.Status == "RESOLVED")
  supportTicket.Resolve();
if(DTO.Title != null)
  supportTicket.setNewTitle(DTO.title);

如果是这种情况,并且更改工单标题有一些业务逻辑可以防止在工单已解决时更改它,我是否应该在更新聚合时考虑某种优先级排序,或者我的看法完全错误?

最佳答案

Domain Driven Design for RESTful Systems -- 吉姆·韦伯

what if i want to provide a way to update whole ticket atomically?

如果您想以原子方式更新整个工单,请放弃聚合;如果您真正想要的是具有 CRUD 语义的键值存储,那么聚合是您框中的错误工具。

聚合只有在它们是要执行的域的业务规则时才有意义。当您只需要一把铲子时,不要制造拖拉机。

As an example, user can make a PUT request to /api/tickets/5

那会弄得一团糟。在 CRUD 实现中,通过向资源发送新状态的表示来替换资源的当前状态是合适的。但这根本不适合聚合,因为聚合的状态不受您(客户/发布者)的控制。

更合适的习惯用法是将消息发布到总线上,当域处理该消息时,会产生实现您想要的更改的副作用。

PUT /api/tickets/5/messages/{messageId}

现在您的应用程序服务会查看消息,并向聚合发送命令

if(DTO.Status != null && dto.Status == "RESOLVED")
  supportTicket.Resolve();
if(DTO.Title != null)
  supportTicket.setNewTitle(DTO.title);

这没关系,但在实践中更常见的是使消息明确说明要做什么。

{ "messageType" : "ResolveWithNewTitle"
, "status" : "RESOLVED"
, "Title":"Some crazy title"
}

甚至...

[
  { "messageType" : "ChangeTitle"
  , "Title" : "Some crazy title"
  } 
, { "messageType" : "ResolveTicket"
  }
]

基本上,您希望为应用提供足够的上下文,以便它可以进行真正的消息验证。

let's say I had aggregates which encapsulated needed business logic, but besides that there is a new demand for atomic update functionality and I am trying to understand a best way to deal with this.

因此,处理此问题的正确方法首先是在领域级别上进行处理——与您的领域专家坐下来,确保每个人都理解需求以及如何使用通用语言等来表达需求。

在聚合根中实现您需要的任何新方法。

一旦您的用例在域中得到正确支持,您就可以开始担心您的资源是否遵循之前的模式 - 资源只接收传入的请求,并调用适当的命令。

关于c# - 通过 REST 进行 DDD 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37890512/

相关文章:

c# - 如何防止 C# 中窗体的 keydown 事件多次触发?

c# - WebAPI 是否支持按 block 读取分块请求?

c# - 如何修补聚合根

TDD 演示/指南/视频,包括假存储库或域模型

domain-driven-design - 我应该始终使用服务,还是可以直接使用存储库?

c# - 如何在 C# 中将 .docx 转换为 .pdf

c# - 任务并行库代码在 Windows 窗体应用程序中卡住 - 作为 Windows 控制台应用程序正常工作

c# large doubles 比较

c# - 发送不记名 token 时 API 端点返回 "Authorization has been denied for this request."

asp.net-web-api2 - 如何将 Swagger 页面设置为 Web api 2 项目的默认登陆页面?