![]() |
1
2
对。我不认为这是个问题。继续阅读以了解原因。
否。使聚合返回需要在聚合的每个方法上的事件中持久化和/或引发的数据。
原始示例。现实世界需要更精细的反应,也许
对内部实体执行相同的操作。让实体重新运行由于其方法调用(包括其ID)而更改的数据,在AR中捕获此数据,并为持久性和eventPublisher构建propper输出。这样,您甚至不需要向AR公开实体ID为的公共只读属性,也不需要向应用程序服务公开AR的内部数据。这是摆脱Getter/Setters包对象的方法。
有时,业务规则要检查和应用,只属于一个实体,其内部状态和AR只是充当网关。这是可以的,但如果你觉得这个模式太多,那么这是一个错误的AR设计的迹象。也许内部实体应该是AR而不是内部实体,也许您需要将AR拆分为几个AR(其中一个是旧的ner实体),等等。。。不要对只有一个或两个方法的类感到吃惊。 针对dee zg的意见:
都不是。聚合和实体是域概念,而不是持久性概念;您可以有文档存储、列存储、关系等,它们不需要与您的域概念1:1匹配。您不会从persistence读取聚合和实体;而是使用从持久性读取的数据在内存中构建聚合和实体。聚合本身不需要持久化,这只是一个可能的实现细节。记住,聚合只是一个组织业务规则的构造,它不是一个表示状态的表示。
您的事件具有上下文(用户意图)和已更改的数据(以及标识持久性中的内容所需的ID),因此编写一个
你为什么要设计一个有状态和行为的班级? 抽象、封装、重用等 SOLID 设计。如果实体拥有确保操作的域规则和不变量所需的一切,那么该实体就是该操作的AR。如果您需要实体无法完成的额外域规则检查(即,实体没有足够的内部状态来完成检查,或者不能自然地融入实体和所代表的内容),那么您必须重新设计;有时可以对执行额外域规则检查的聚合进行建模,并将其他域规则检查委托给内部实体,有时可以更改实体以包含新事物。这是太域上下文依赖,所以我不能说有一个固定的重新设计策略。 请记住,不要在代码中对聚合和实体建模。您只需要用行为来对类建模,以检查域规则以及执行检查和响应更改所需的状态。这些类可以作为不同操作的聚合或实体。这些术语仅用于帮助沟通和理解类在每个操作上下文中的角色。当然,您可能会遇到这样的情况:操作不适合实体,您可以使用V.O.持久性ID对聚合进行建模,这样就可以了(遗憾的是,在DDD中,在不知道域上下文的情况下,默认情况下几乎一切都可以了)。 你想从比我解释得更好的人那里得到更多启示吗?(不以英语为母语是这些复杂问题的障碍)看看这里: https://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-1 http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-2 http://blog.sapiensworks.com/post/2016/07/14/DDD-Aggregate-Decoded-3 |
![]() |
2
1
在逻辑意义上,可能是这样的,但具体地用持久性来实现这一点意味着我们所拥有的往往是不必要的复杂。
不一定,例如,您可以拥有只读实体。 问题的存储库部分已在中解决 another question . 读取不是问题,有多种技术可以防止外部世界的写入访问,但仍然允许持久层直接或间接地填充实体。
你可能有点草率地把关注点放在同一个篮子里,而事实上这些关注点略有不同
仅仅因为值对象最好是不可变的,并且不强制执行聚合级别不变量(尽管它们强制执行自己的数据完整性),并不意味着实体不能对某些相同的特性进行微调组合。 |
![]() |
3
1
你在考虑数据。住手。:)实体和值对象不是数据。它们是可以用来为问题域建模的对象。实体和值对象只是对问题建模时自然产生的事物的分类。
对。此外,对象中的所有状态都应该是私有的,并且从外部无法访问。
不,我们不会公开已经存在的信息。如果信息已经存在,那就意味着已经有人对此负责了。因此,联系该对象为您做事情,您不需要数据!这基本上就是 Law of Demeter 告诉我们。 经常实施的“存储库” 做 你需要访问数据,你说得对。他们是一个坏模式。它们通常与ORM结合在一起,在这种情况下更糟糕,因为您将失去对数据的所有控制。
诀窍是,你不必这么做。你创建的每个对象(类)都是有原因的。如前所述,为了创建额外的抽象,对域的一部分进行建模。如果这样做,一个存在于更高抽象级别上的“聚合”对象将永远不希望提供与下面的对象相同的方法。这意味着没有任何抽象。 这个用例只在创建面向数据的对象时出现,这些对象除了保存数据之外几乎没有其他作用。显然,你会想,如果你不能把数据拿出来,你怎么能用这些做任何事情。然而,这是一个很好的指标,你的设计还没有完成。 |
![]() |
4
0
这些问题在CQRS体系结构中并不存在,CQRS体系结构中的写模型(聚合)不同于读模型。在平面架构中,聚合必须公开读取/查询方法,否则将毫无意义。
是的,这样你就清楚地表达了它们不是外用的事实。
存储库是一个特例,不应以与应用程序/表示代码相同的方式查看。它们可以是同一个包/模块的一部分,换句话说,它们应该能够访问嵌套的实体。 可以将实体视为/实现为具有不可变ID的对象和表示其状态的值对象,类似于(在伪代码中):
你看到了吗?你可以的
安全地
归还
是的,这保护了聚合的封装,也允许聚合保护它的不变量。 |
![]() |
5
0
我不会写太多。只是一个例子。一辆汽车和一个齿轮。汽车是根的集合体。齿轮是一个子实体 |
![]() |
Tony Raimo · 域实体是否应该调用存储库? 7 年前 |
![]() |
Seb · DDD只读存储库返回“值对象” 7 年前 |
![]() |
tlt · 使用嵌套对象和大集合进行聚合根优化 7 年前 |
![]() |
PatrickSJ · DDD,状态对象/值对象 7 年前 |
![]() |
msmani · DDD更改聚合根id 7 年前 |
![]() |
DuskMcDusk · 逻辑和性能中的聚合根冲突 7 年前 |