client-server - DDD - 在不更新整个聚合根的情况下更新实体的小细节

标签 client-server domain-driven-design dto clean-architecture

假设我的 AggregateRootOrder-Model。有一个包含 OrderItems(实体)的集合。 我只有一个 Repository 用于 AggregateRoot(订单),但没有用于 OrderItems。

当客户只想更新一个小的更改,例如一个 OrderItem 上的 Remarks 字段时,我该怎么办?

我目前的理解是客户端通过DTO 发送更新。然后中间件加载整个订单,然后更新单个细节,并将整个订单提交到存储库。

如果我理解正确的话,这是现实生活中的一个好习惯,还是您会以不同的方式处理它?这听起来对我来说性能不佳且维护不友好。

最佳答案

正如 DDD 中的所有内容一样,答案在于领域规则。一切都必须围绕规则而不是数据结构。

警告:下面的例子太简单了!

您必须更改一个订单项的Remarks 字段,所以请问您:Remarks 字段更改操作有哪些限制和不变性? OrderItem 是否具有为此所需的所有信息?如果是,那么在这种情况下 OrderItem 是您的聚合根。

是否某些备注不允许进入 OrderItem,因为它属于某种类型的订单,但其他订单类型允许此备注。那么 Order 就是你的聚合根。

这为您提供了有关如何处理它的线索,但是因为您的评论加载一个包含所有 OrderItems 的订单只是为了更改一个 OrderItem Remark 是绝对不高效的。

“I’m sorry that I coined the term ‘objects,’ because it gets many people to focus on the lesser idea. The big idea is ‘messaging’” ~ Alan Kay

还记得我说过 DDD 必须强调环绕规则而不是环绕数据结构吗? 所以,不要考虑数据结构。围绕命令和事件(消息)和规则对所有事物进行建模。让你的持久性存储库为该命令带来适当的聚合根,使用 AR 来应用命令,返回一个域事件产生的变化,并使用该事件来持久化新的系统状态并通知其他服务有关变化。

来自 Aggregate root invariant enforcement with application quotas 的代码示例

class ApplicationService{
    public void registerUser(RegisterUserCommand registerUserCommand){

      var user = new UserEntity(registerUserCommand.userData); //avoid wrong entity state; ctor. fails if some data is incorrect

      RegistrationAggregate agg = aggregatesRepository.Handle(registerUserCommand); //handle is overloaded for every command we need. Use registerUserCommand.tenantId to bring total_active_users and quota from persistence, create RegistrarionAggregate fed with TenantData

      var userRegisteredEvent = agg.registerUser(user); //return domain changes expressed as a event

      persistence.Handle(userRegisteredEvent); //handle is overloaded for every event we need; open transaction, persist  userRegisteredEvent.fromTenant.total_active_users where tenantId, optimistic concurrency could fail if total_active_users has changed since we read it (rollback transaction), persist userRegisteredEvent.user in relationship with tenantId, commit transaction

    eventBus.publish(userRegisteredEvent); //notify external sources for eventual consistency

  }

这允许您从持久性中将 OrderItemRemarkManagerAggregate 带入内存,其中仅包含更改备注所需的信息(即 OrderItem ID、当前备注、OrderItem 状态、所属的 OrderType 等);只需使用它来应用操作并将更改应用到持久性。

稍后您可能会担心为多个操作重用聚合(当然总是在同一个限界上下文中)或者甚至根据需要进行重构。

关于client-server - DDD - 在不更新整个聚合根的情况下更新实体的小细节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59035684/

相关文章:

java - 查找可能的 ServerSocket 列表

design-patterns - 在域驱动设计中使用摘要对象

c# - OData 是公开非 CRUD API 的好方法吗?

c# - 如何将多个请求 DTO 映射到单个路由

c - 当客户端套接字在C中终止时如何防止服务器套接字关闭?

database - Delphi 2009客户交​​流

domain-driven-design - ddd中上游上下文和下游上下文之间的关系

Java Jackson 如何在序列化过程中解开原始值?

c# - WCF 数据服务和映射的 DTO

java - 我的JDBC sql语句有什么问题