聚合根。兔子洞到底有多远

时间:2010-01-22 15:02:30

标签: c# domain-driven-design repository-pattern aggregate aggregateroot

我正在尝试将Repository模式用于我当前的项目,而我目前正在尝试对域进行建模并找到聚合根。

我已经读过“级联删除”规则,该规则指出如果在删除根时删除成员没有意义,那么它不应该是根目录的一部分。

我将以警察事件为例: -

事件(聚合根) - 这可能包含调查人员,每位官员的注释。它还可能包含嫌疑人的受访日期列表。 是否为此事件获得了闭路电视录像?每次看CCTV的日志和谁? 是中央电视台为证据/法庭等制作的副本

似乎IncidentAggregate可能会变得庞大,因为看起来所有事情都会挂起。

我的问题是双重的,聚合根应该管理多少,并且根源是一个好主意?

这可能不是一个特别好的例子,因为你可能永远不会删除类似警察事件的内容,但我希望它能更好地描述我的问题。

3 个答案:

答案 0 :(得分:10)

聚合通常包含引用到其他聚合根。删除包含聚合时应删除这些引用,但它们指向的聚合将保留。

使用你的比喻。我们将假设的报告只是一个事件汇总的一部分,并将与汇总一起删除。没有其他汇总可以直接访问这些报告。

但是,事件聚合将引用聚合,代表人员,嫌疑人和CCTV查看日志条目。

答案 1 :(得分:9)

聚合是一组具有相同生命周期的对象。

如果您删除了某个事件,您还想删除调查人员吗?不 - 如果你这么做,你很快就会没有警察离开。调查人员不在事故集合中。

你列出的其他事情,嫌疑人,采访,闭路电视等等。答案是 - 这取决于。

这取决于您的问题域。你的系统在做什么?它的范围是什么?它解决了什么问题?

如果唯一的工作是跟踪一系列事件并假设嫌疑人,采访和闭路电视只是因为一次事故而在系统中,那么是的,将它们全部集中在一起可能是合适的。如果事件被删除,嫌犯,访谈和中央电视台都可以去。

例如,如果您还从市中心摄像机网络收集了CCTV录像的跟踪档案。也许你试图监控它们的有效性和可靠性。如果是这样,您需要以不同方式处理CCTV录像。它将与其自己的生命周期处于不同的聚合中。如果您删除了某个事件,您仍然希望保留其他事件和性能指标的闭路电视录像。

聚合内容和内容取决于您的问题域。或者更确切地说,这取决于您对问题域解决方案进行建模的方式。

思考生命周期。

答案 2 :(得分:1)

“扎根是根本好主意吗?”

我认为简短的回答是否定的。正如Kurt所说,您应该将引用保留给其他聚合。为了清楚起见,通过引用我的意思是识别对象。所以也许你的事件聚合会有一个属性,如

public IEnumerable<Guid> InvestigatingOfficerIds 
{ 
    get { return _investigatingOfficerIds.AsReadOnly(); }
}

public IEnumerable<OfficerReference> InvestigatingOfficerIds 
{ 
    get { return _investigatingOfficerIds.AsReadOnly(); }
}

因此,OfficeReference是一个代表官员身份价值的类(在引擎盖下可能是一个Guid)。

如果您的域逻辑需要使用突发事件和调查人员执行操作,您可以将此逻辑抽象为域服务,并使用IOfficerRepository使用事件聚合上提供的ID来获取人员聚合。