
>一个孩子报名参加
>孩子可以到达
>孩子可以离开
目标是跟踪访问的次数,生成发票,记录(例如午餐,伤害等),以防止访问.到目前为止,这些其他 *** 作将是与系统最常见的交互,因为访问每天开始一次,但有趣的事情一直在发生.
我正在努力的不变量是:
>如果孩子已经在这里,他们就无法到达
据我所知,我有以下选择
1.单个聚合根子
创建一个Child聚合根,其中包含事件ChildEnrolled,ChildArrived和Childleft
这看起来很简单,但由于我希望每个其他事件与访问相关联,这意味着访问将是Child聚合的实体,每次我想添加注释或任何内容时,我都必须获取所有访问对于那个孩子,永远.似乎效率低下且相当无关紧要 – 孩子本身和其他每次访问都与孩子午餐时的情况无关.
2.儿童和访问的总体根源
Child会直接使用ChildEnrolled,而Visit会获取ChildArrived和Childleft.在这种情况下,我不知道如何维持不变量,除了让访问为此目的服务,我见过这是灰心丧气的.
是否有另一种方法来强制使用此设计的不变量?
这是一种虚假的不变量
我认为这是可能的,我应该防止多个人同时登录同一个孩子,或延迟意味着使用多次点击“登录”按钮.我认为这不是答案.
我错过了一些明显的东西
这似乎最有可能 – 这肯定不是一些特殊的雪花,这通常是如何处理的?我几乎找不到具有多个AR的示例,更不用说带有列表的示例了.
解决方法 骨料你在谈论访问以及访问期间发生的事情,所以它似乎是一个重要的领域概念.
我想你也会有一个DayCareCenter,所有关心的孩子都在这里注册.
所以我会选择这个聚合根:
> DayCareCenter
>孩子
>参观
顺便说一句:我看到另一个不变量:
“孩子不能同时在多个日托中心”
“多次点击’登录’按钮”
如果每个命令都有一个唯一的ID,它是为每次有意的尝试生成的 – 不是每次点击都产生的(无意的),你可以缓冲最后n个收到的命令ID并忽略重复.
或者您的消息传递基础设施(服务总线)可以为您处理.
创建访问
由于您使用多个聚合,因此必须查询一些(可靠,一致)存储以查明是否满足不变量.
(或者如果很少发生冲突并且手动“取消”无效访问是合理的,那么最终一致的读取模型也会起作用……)
由于儿童只能进行一次当前访问,因此儿童只会存储关于上次开始访问的一些信息(事件).
每当开始新的访问时,都会查询任何先前访问的“真实来源”(写模型)并检查访问是否结束.
(另一个选择是访问只能通过Child聚合结束,再次存储一个“结束” – 在Child中的事件,但这对我来说感觉不太好……但这只是个人观点)
查询(验证)部分可以通过特殊服务完成,或者只是将存储库传递给方法并直接在那里查询 – 这次我使用第二个选项.
这是一些C#-ish脑编译的伪代码来表达我认为你可以处理它的方式:
public class DayCareCenterID{ public string Value { get; set; }}public class DayCareCenter{ public DayCareCenter(DayCareCenterID ID,string name) { RaiseEvent(new DayCareCenterCreated(ID,name)); } private voID Apply(DayCareCenterCreated @event) { //... }}public class VisitID{ public string Value { get; set; }}public class Visit{ public Visit(VisitID ID,ChildID childID,DateTime start) { RaiseEvent(new VisitCreated(ID,childID,start)); } private voID Apply(VisitCreated @event) { //... } public voID EndVisit() { RaiseEvent(new VisitEnded(ID)); } private voID Apply(VisitEnded @event) { //... }}public class ChildID{ public string Value { get; set; }}public class Child{ VisitID lastVisitID = null; public Child(ChildID ID,string name) { RaiseEvent(new ChildCreated(ID,name)); } private voID Apply(ChildCreated @event) { //... } public Visit VisitsDayCareCenter(DayCareCenterID centerID,IEventStore eventStore) { // check if child is stille visiting somewhere if (lastVisitID != null) { // query write-sIDe (is more reliable than eventual consistent read-model) // ...but if you like pass in the read-model-repository for querying if (eventStore.OpenEventStream(lastVisitID.Value) .Events() .Any(x => x is VisitEnded) == false) throw new BusinessException("There is already an ongoning visit!"); } // no pending visit var visitID = VisitID.Generate(); var visit = new Visit(visitID,this.ID,DateTime.UtcNow); RaiseEvent(ChildVisitedDayCenter(ID,centerID,visitID)); return visit; } private voID Apply(ChildVisitedDayCenter @event) { lastVisitID = @event.VisitID; }}public class CommandHandler : Handles<ChildVisitsDayCareCenter>{ // http://csharptest.net/1279/introducing-the-lurchtable-as-a-c-version-of-linkedhashmap/ private static Readonly Lurchtable<string,int> lastKNownCommandIDs = new Lurchtable<string,bool>(LurchtableOrder.Access,1024); public CommandHandler(IWriteSIDeRepository writeSIDeRepository,IEventStore eventStore) { this.writeSIDeRepository = writeSIDeRepository; this.eventStore = eventStore; } public voID Handle(ChildVisitsDayCareCenter command) { #region example command douplicates detection if (lastKNownCommandIDs.ContainsKey(command.CommandID)) return; // already handled lastKNownCommandIDs[command.CommandID] = true; #endregion // OK,Now actual logic Child child = writeSIDeRepository.GetByAggregateID<Child>(command.AggregateID); // ... valIDate day-care-center-ID ... // query write-sIDe or read-sIDe for that // create a visit via the factory-method var visit = child.VisitsDayCareCenter(command.DayCareCenterID,eventStore); writeSIDeRepository.Save(visit); writeSIDeRepository.Save(child); }} 备注:
> RaiseEvent(…)立即在场景后面调用Apply(…)
> writeSIDeRepository.Save(…)实际上保存了事件
> Lurchtable用作固定大小的MRU命令列表
>如果您感兴趣,可以为它提供服务,而不是传递整个事件存储
免责声明:我不是知名专家.这就是我接近它的方式.在这个答案中可能会损害一些模式. 总结
以上是内存溢出为你收集整理的domain-driven-design – 当列表中存在不变量时定义聚合根全部内容,希望文章能够帮你解决domain-driven-design – 当列表中存在不变量时定义聚合根所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)