2017-02-05 76 views
1

我想知道如何使用DDD和CQRS对日历进行建模。我的问题在于越来越多的事件。我认为日历是包含事件(日历事件)的聚合根。我不想在我的命令中使用ReadSide,但我需要在域级别检查事件冲突的方法。聚集根包括大量的儿童

回答

4

我想知道如何使用DDD和CQRS对日历进行建模。我的问题在于越来越多的事件。

“长寿命”聚合最常见的答案是打破这一生的情节。例如,会计师将在end of the fiscal year关闭的临时帐户。

在您的具体情况下,可能不是“日历”,比如“二月日历”,“三月日历”等等,无论您的域名是否适合。

林不知道我是否正确DDD aproach在验证方面。我相信重点不是让模型进入无效状态

是的,但无效状态是一个棘手的事情来定义。 Udi Dahan提供this observation

一个微秒的时间差应该不会影响核心业务行为。

更简洁,处理命令A,接着通过处理指令B产生一个有效的状态,那么它也应该是真实的,你先结束了处理命令B,然后A.

让我们选择你的“事件碰撞“的例子。假设我们处理scheduleMeeting(A)scheduleMeeting(B)两个命令,并且域模型理解AB碰撞。谜语:我们如何确保日历保持有效状态?

不失一般性,我们可以翻转硬币来决定哪个命令先到达。我的硬币出现尾巴,因此命令B首先到达。

on scheduleMeeting(B): 
    publish MeetingScheduled(B) 

现在会议指令A到达。如果您的有效日历不允许冲突,那么你的实现需要看起来像

on scheduleMeeting(A): 
    throw DomainException(A conflicts with B) 

在另一方面,如果你拥抱的想法,命令到达应该不会影响结果,那么你需要考虑另一种方法。也许

on scheduleMeeting(A) 
    publish MeetingScheduled(A) 
    publish ConflictDetected(A,B) 

也就是说,Calendar聚合被建模为不仅跟踪计划的事件,而且跟踪已经出现的冲突。

另请参阅:aggregates and RFC 2119

+0

谢谢你的回答。关于将日历分成几个月的想法对我来说似乎完全有效。林不知道我是否正确DDD aproach在验证方面。我相信关键是不要让模型进入无效状态 - 这意味着必须通过日历了解所有自己的事件(如Agreggate Root)。 – ayeo

+0

我想你需要详细解释一下系统如何利用最终一致性,因为你描述它的方式,你仍然需要较大的聚合边界以检测甚至发生了冲突。通过最终的一致性,事件可以是单独的聚合,您可以完全摆脱日历中事件的集合(将其替换为查询)。 – plalx

+0

当我在做某种资源管理时,我最终得到了Day的概念。不出所料,其他从业者也得出了同样的结论。您可以同时具有活动和日期,并检查它们是否相互兼容(日期有空,活动可以降落到几天)。 –

3

事件也可能是一个聚合根。我不知道你的商业约束,但我认为,如果两个事件colide你可以通知用户以某种方式采取手动操作。否则,如果你真的真的需要他们不要colide你可以使用快照来加速巨大的日历AR。

我不想在我的命令中使用ReadSide,但我需要在域级别检查事件冲突的方法。

您无法在集合命令处理程序中查询读取模型。对于碰撞检测,我会创建一个特殊的DetectColisionSaga,订阅EventScheduled事件,如果发生碰撞,应该检查(可能是异步,如果是多个事件)并以某种方式通知用户。

+0

谢谢,但访问被认为是良好做法的域的读方? – ayeo

+0

你是什么意思的“域”?你的意思是写作方面? –

+0

是的,基本上就这个问题而言,我的意思是写一面。就我掌握的命令而言,它们应该直接在域模型上执行(由处理程序执行)。 – ayeo