Domain driven design DDD:加载整个骨料将导致性能问题

Domain driven design DDD:加载整个骨料将导致性能问题,domain-driven-design,cqrs,Domain Driven Design,Cqrs,大多数DDD书籍(例如DDD的模式和原则)强烈建议在从数据库获取数据时加载整个聚合。原因是聚合是一致的边界。 但在一些常见情况下,这会导致严重的性能问题。 下面是我面临的一个真实例子: 我有一个聚合根,它是一个带有属性的workobject实体。此集合中还有其他实体: 工作对象的附加文件列表。每个文档都是一个实体。(类文档包含真实文档的元数据) 注释列表。每个注释都是一个实体` 活动列表。每个活动都是一个实体,表示在此工作对象上完成的活动 归档文件的列表。每个ArchivedFile都是一个实体

大多数DDD书籍(例如DDD的模式和原则)强烈建议在从数据库获取数据时加载整个聚合。原因是聚合是一致的边界。
但在一些常见情况下,这会导致严重的性能问题。
下面是我面临的一个真实例子:
我有一个聚合根,它是一个带有属性的
workobject
实体。此集合中还有其他实体:

  • 工作对象的附加
    文件列表。每个
    文档
    都是一个实体。(类
    文档
    包含真实文档的元数据)
  • 注释列表
    。每个
    注释都是一个实体`
  • 活动列表
    。每个
    活动
    都是一个实体,表示在此工作对象上完成的活动
  • 归档文件的列表。每个
    ArchivedFile
    都是一个实体,表示已在外部系统中存档的文档。(类
    ArchivedFile
    包含实际存档文件的元数据)
  • 这些实体属于聚合,因为
    workobject
    上的更改也将主要影响这些实体的状态。
    现在我有以下问题:
    在UI中,有一个位置,用户可以从中获取其收件箱中的所有
    workobject
    s。这可能超过100个
    workobject
    s甚至更多。但是,在此时为每个
    工作对象加载整个聚合(
    注释
    s、
    活动
    文档
    s)是没有意义的。这会减慢应用程序的速度,从而导致糟糕的用户体验。
    其思想是在数据网格中仅向用户显示
    workobject
    的属性。如果用户执行特定事件,如单击特定的
    工作对象
    ,则会在加载特定
    工作对象
    详细信息的位置加载特定表单。这将是加载整个聚合的合适点(即,
    注释
    s、
    活动
    文档
    s)。但是大多数DDD书籍(例如DDD的模式和原则)警告不要在聚合中使用延迟加载,而是在加载聚合根时加载整个聚合。
    我们应该如何通过遵守DDD规则来解决这个问题

    我们应该如何通过遵守DDD规则来解决这个问题

    通常的回答是:当您想要的是一个报告时,不要使用聚合模式

    延迟加载是执行域动态时的“代码气味”;如果在进行更改时留下了大量数据,这强烈表明留下的信息属于不同的聚合

    但是对于一个有效的只读操作,比如一个报告?我们不会改变任何东西,所以我们不需要约束来确保我们的改变是正确的,所以我们不需要我们用来描述约束的信息


    有关分离读写的更多想法,请查看伞下描述的模式(“命令-查询-责任分离”)。

    我同意延迟加载可能是出于错误的原因,聚合边界可能绘制错误。但是,如果不是在涉及修改聚合的每个业务事务期间访问聚合的所有子实体,那么它不一定是气味。默认情况下,我自己不会使用延迟加载,但出于性能原因,它可能是合理的,并且非常适合于写密集型服务。当然,前提是骨料设计合理。