子聚合实体的域驱动设计存储库
Domain Driven Design repository for child aggregate entity
在阅读了 DDD 和聚合并查看了一些像这样的 Whosebug 帖子之后
Update an entity inside an aggregate
我对聚合的职责和存储库有一些疑问。
例如,如果我们假设我们有用户和地址实体以及一个不变量,表示一个用户最多只能有 3 个符合这种方式的地址并聚合这些域规则。
考虑到这一点,假设当您符合聚合对用户 class 内的地址子实体的访问时,将始终通过用户 class 方法,有些方法像这样将存在:
user.registerNewContactAddress("街头废话")
user.updateContactAddress(address_id,"街头废话")
...
在这个基本场景中,我的问题是:
1) 假设不应该存在地址存储库,但是,在所有情况下都是强制规则还是不鼓励规则?
我在考虑是否需要列出系统中的所有地址,例如,使用遍历所有用户并检索其所有地址的地址存储库显然效率更高。
或者,例如,寻找“附近”地址的用户案例。
那么,也许只有“findAll”和“findXX”方法的地址存储库符合 DDD 哲学?留下由用户聚合管理的地址的插入和删除看不变量?
2) 例如,如果我们有 30.000 个地址而不是最多 3 个地址(这只是一个愚蠢的案例,我知道,对不起),会发生什么情况。
在这种情况下,我们是否应该保留 user.changeAddress(address_id,"street blablb") 方法?
我想检索用户并在内存中遍历他的所有地址会变得有点低效,因此,在另一种情况下,我认为通过 ID 直接调用地址存储库可能更好。
谢谢
您描述的用例是关于读取用户的所有地址。对于读取操作,不仅允许具有绕过通过聚合访问数据的特定查询操作。它甚至受到鼓励。
另请参阅对类似问题的回答。
聚合和存储库针对写入操作进行了优化,其中需要保持业务不变性。要查询只需要读取操作(例如显示数据)的数据,应该绕过域模型,从而绕过聚合和存储库,以优化读取所需数据。如果需要,这甚至可能意味着在 ORM 未提供所需性能的情况下进行原始查询。
注意:如果您需要能够在用户上下文之外(独立)操纵女演员,您可能错过了一个单独的地址聚合。在那种情况下,我宁愿将 Address 建模为 User 中的某个引用类型值对象,例如地址Id。除非您在用户聚合执行的业务逻辑上下文中需要更多地址数据。
和另一个注意事项:一般来说,我会认为一个地址是一个值对象而不是一个实体,除非你真的在多个用户之间共享相同的地址“实体”,这是不太可能或必要的。由于仅凭地址的属性就可以将一个地址与另一个地址区分开来,因此我认为不需要任何身份来使其成为一个实体。
值对象通常建模为聚合的一部分。在关系数据库中,这可能意味着它们分布在相同 table 的列中,或者对于值对象的集合,这通常作为序列化数据完成,例如 JSON。这也减少了潜在的性能问题,因为所有内容都是从同一个 table.
查询的
在阅读了 DDD 和聚合并查看了一些像这样的 Whosebug 帖子之后
Update an entity inside an aggregate
我对聚合的职责和存储库有一些疑问。
例如,如果我们假设我们有用户和地址实体以及一个不变量,表示一个用户最多只能有 3 个符合这种方式的地址并聚合这些域规则。
考虑到这一点,假设当您符合聚合对用户 class 内的地址子实体的访问时,将始终通过用户 class 方法,有些方法像这样将存在:
user.registerNewContactAddress("街头废话") user.updateContactAddress(address_id,"街头废话") ...
在这个基本场景中,我的问题是:
1) 假设不应该存在地址存储库,但是,在所有情况下都是强制规则还是不鼓励规则?
我在考虑是否需要列出系统中的所有地址,例如,使用遍历所有用户并检索其所有地址的地址存储库显然效率更高。
或者,例如,寻找“附近”地址的用户案例。
那么,也许只有“findAll”和“findXX”方法的地址存储库符合 DDD 哲学?留下由用户聚合管理的地址的插入和删除看不变量?
2) 例如,如果我们有 30.000 个地址而不是最多 3 个地址(这只是一个愚蠢的案例,我知道,对不起),会发生什么情况。
在这种情况下,我们是否应该保留 user.changeAddress(address_id,"street blablb") 方法? 我想检索用户并在内存中遍历他的所有地址会变得有点低效,因此,在另一种情况下,我认为通过 ID 直接调用地址存储库可能更好。
谢谢
您描述的用例是关于读取用户的所有地址。对于读取操作,不仅允许具有绕过通过聚合访问数据的特定查询操作。它甚至受到鼓励。 另请参阅对类似问题的回答。
聚合和存储库针对写入操作进行了优化,其中需要保持业务不变性。要查询只需要读取操作(例如显示数据)的数据,应该绕过域模型,从而绕过聚合和存储库,以优化读取所需数据。如果需要,这甚至可能意味着在 ORM 未提供所需性能的情况下进行原始查询。
注意:如果您需要能够在用户上下文之外(独立)操纵女演员,您可能错过了一个单独的地址聚合。在那种情况下,我宁愿将 Address 建模为 User 中的某个引用类型值对象,例如地址Id。除非您在用户聚合执行的业务逻辑上下文中需要更多地址数据。
和另一个注意事项:一般来说,我会认为一个地址是一个值对象而不是一个实体,除非你真的在多个用户之间共享相同的地址“实体”,这是不太可能或必要的。由于仅凭地址的属性就可以将一个地址与另一个地址区分开来,因此我认为不需要任何身份来使其成为一个实体。
值对象通常建模为聚合的一部分。在关系数据库中,这可能意味着它们分布在相同 table 的列中,或者对于值对象的集合,这通常作为序列化数据完成,例如 JSON。这也减少了潜在的性能问题,因为所有内容都是从同一个 table.
查询的