Domain driven design 实体应该有方法吗?如果有,如何防止在聚合外部调用它们

Domain driven design 实体应该有方法吗?如果有,如何防止在聚合外部调用它们,domain-driven-design,Domain Driven Design,所以,如果聚合中存在一个实体,那么防止外部世界执行类似于aggregate.entity.SomeMethod()的操作的最佳/常用方法是什么?(如果聚合上存在实体的getter) 聚合是否应该公开实体,还是它的getter应该始终提供实体的值对象表示?(实际上是一个用于打断直接引用的副本) 或者,另一方面,实体是否应该贫血,是否应该将其所有方法移动到聚合?聚合不应该以允许从外部更改聚合内部状态的方式公开数据 这意味着聚合根对象不应该分发对内部实体的引用。如果要更改聚合的状态,则向根实体发送一条

所以,如果聚合中存在一个实体,那么防止外部世界执行类似于
aggregate.entity.SomeMethod()
的操作的最佳/常用方法是什么?(如果聚合上存在实体的getter)

聚合是否应该公开实体,还是它的getter应该始终提供实体的值对象表示?(实际上是一个用于打断直接引用的副本)


或者,另一方面,实体是否应该贫血,是否应该将其所有方法移动到聚合?聚合不应该以允许从外部更改聚合内部状态的方式公开数据

这意味着聚合根对象不应该分发对内部实体的引用。如果要更改聚合的状态,则向根实体发送一条消息,该逻辑决定是自己执行工作还是委派工作

根对象的查询应返回值

缺乏活力的实体没有多大意义——如果你要沿着这条路走下去,你最好用价值对象保持简单


谢谢你的回答!您能否扩展一个答案:1)这是否意味着聚合应该向外部世界公开实体的副本,以便其内部实体从外部是不变的?或者它是如何暴露的?2) “根对象的查询应该返回值”是什么意思

简短回答:您根本不应该将“实体”暴露在聚合之外

实体的动机是它们改变状态。聚合的动机是它们协调实体之间状态的变化。如果从聚合中泄漏实体,则聚合将不再能够协调所有更改

因此:如果您想更改聚合,“告诉,不要问”。您将信息传递给聚合根,它将在根中创建/修改相应的实体


如果不想更改聚合,请使用返回查询答案的不可变表示形式的查询。这种不可改变的表现形式的确切性质可能因语言而异;在最初的领域驱动设计文本中,示例取自Java,其中使用“值对象”实现不可变表示。参见第五章。

这是一个可见性范围的问题。这取决于您使用的编程语言。例如,在java中,我将聚合放在一个包中。聚合根实体将是公共的。其他的将具有包范围,即,没有用于可见性的关键字

谢谢你的回答!您能否扩展一个答案:1)这是否意味着聚合应该向外部世界公开实体的副本,以便其内部实体从外部是不变的?或者它是如何暴露的?2) 你们所说的“根对象的查询应该返回值”是什么意思?哦,所以实体只是在聚合内部工具中以保持其状态,而不是暴露于外部世界。我得说这让我大开眼界!然后我想,无论聚合向外部世界公开了什么,都不会影响它的不变量,这些不变量总是通过显式聚合方法强制实现的。正确的?(是/否就足够了)让我困惑的是,至少存储库需要来自所有聚合子级(包括实体)的数据。所以,至少出于这个目的,为了使存储库能够将聚合映射到DAO,应该将实体属性(与保存到db相关)公开,但我想,这样做是作为值对象的。实体(作为聚合根或聚合中的子实体)本身存在,并不是因为它必须有任何用途。聚合内的实体在聚合外没有标识!,所有实体都有。您可以通过其id访问实体,如果根实体执行此操作,您不能直接访问实体,但可以通过根访问实体。通常,聚合中的实体类似于E/R模型中的弱实体,或UML中的组合。用于组合的id(其中一部分是根的id)。“我只是不理解聚合根中实体的用途”-@deezg,这是一个非常好的问题,可能应该从这里单独提问。TL;博士,因为我们正在为一个领域建模……downvoter能解释downvote吗,这样我就可以改进这个问题了?谢谢你的聚合根将在一个专用的包中,而不仅仅是根。整个聚合是一个包。包包含所有聚合元素:根实体、其他实体、值对象。。。具有“public”访问修饰符的唯一元素应该是根实体。其余的元素应该没有访问修饰符,这样它们就不能从包外部访问,它们只有包的可见性。是的,你是对的,对不起。我的意思是,你会有每个集合的专用包吗?对于任何规模合适的项目来说,听起来都有很多包(尽管我对java和包的最佳实践知之甚少)。没有太多包,因为受限上下文通常没有太多聚合。首先,每个BC都有一个包,然后每个BC内的每个聚合都有一个包。甚至更多。。。每个BC都是一个独立的包,它是一个可部署的单元,一个微服务。否则,您将拥有一个整体,这并没有那么糟糕,因为您的代码在包中组织得很好。是的,软件包中的最佳实践是只在您想在软件包外公开的内容上使用public关键字,其他内容应使用no-access修饰符隐藏。非常感谢您的回答!这是很多有用的信息!