dee*_* zg 5 domain-driven-design
[从这个问题和评论中跟进:实体是否应该有方法,如果有,如何防止它们被外部聚合调用]
正如标题所说:我不清楚作为孩子的实体的实际/确切目的是什么?
根据我在很多地方读到的内容,这些是作为聚合子项的实体的属性:
在我看来,这转化为几个问题:
那么,为什么我们有一个实体而不是只有值对象?只有值对象、聚合和公开值对象的所有方法(我们已经复制实体信息)看起来更方便。
附注。我想将子实体集中在聚合上,而不是实体集合上。
[更新以回应康斯坦丁·加尔贝努的回答和评论]
那么,实际上,你会有这样的事情吗?
public class Aggregate {
...
private _someNestedEntity;
public SomeNestedEntityImmutableState EntityState {
get {
return this._someNestedEntity.getState();
}
}
public ChangeSomethingOnNestedEntity(params) {
this._someNestedEntity.someCommandMethod(params);
}
}
Run Code Online (Sandbox Code Playgroud)
您遇到的这些问题在 CQRS 架构中不存在,其中写入模型(聚合)与读取模型不同。在扁平架构中,聚合必须公开读取/查询方法,否则就没有意义。
- 实体应该是私有的才能聚合
是的,这样你就清楚地表达了它们不供外用的事实。
- 我们需要一个只读副本值对象来公开来自实体的信息(例如,至少存储库能够读取它以便保存到数据库)
存储库是一种特殊情况,不应以与应用程序/演示代码相同的方式查看。它们可以是同一包/模块的一部分,换句话说,它们应该能够访问嵌套实体。
实体可以被视为/实现为具有不可变 ID 的对象和表示其状态的 Value 对象,如下所示(伪代码):
class SomeNestedEntity
{
private readonly ID;
private SomeNestedEntityImmutableState state;
public getState(){ return state; }
public someCommandMethod(){ state = state.mutateSomehow(); }
}
Run Code Online (Sandbox Code Playgroud)
所以你看?您可以安全地返回state嵌套实体的 ,因为它是不可变的。德墨忒尔法则会有一些问题,但这是你必须做出的决定;如果你通过返回状态来打破它,你第一次可以使代码更容易编写,但耦合度会增加。
- 我们在实体上拥有的方法在聚合上重复(或者反之亦然,我们在聚合上拥有的处理实体的方法在实体上重复)
是的,这保护了聚合的封装,并且还允许聚合保护它的不变量。