兴致来了,再多说一点吧,呵呵。
就是,在event sourcing模式下,我在聚合根基类里设计了三个方法,分别是:
1. OnEventHappened(event) //表示某个事件发生了
2. WakeupAggregateRoot<T>(id) //表示要唤醒另外一个指定ID和类型的聚合根
3. OnAggregateRootCreated(aggregateRoot) //表示某个聚合根被创建了
有了这三个方法,在领域模型中,应用event sourcing模式实现聚合根与聚合根的交互时,就变得很游刃有余。
第一个方法就是通知有一个新的领域事件发生了,这个方法在所有的event sourcing框架中都有,老外一般命名为ApplyEvent(个人觉得这个名字不怎么贴切);这里我们的目的应该是通知某个事件发生了,那么按照惯例On是通知什么什么的意思,Happened表示发生了,合在一起正好明确的表示某个事件发生了。针对该事件,聚合根可以首先自己响应,然后改变自己状态;而外部系统,如CQRS的查询端,则可以event bus发布事件后收到该事件,然后响应它。
第二个方法是在“我们如果想设计通过ID来关联聚合根时”,就变得非常有用,因为我们只有另外一个聚合根的ID,但有时我们又想访问该聚合根的某个方法,在经典的DDD下,一般只有两个方法,要么通过第三方领域服务来协调,要么直接通过对象引用关联,利用ORM的lazyload机制。而在event sourcing模式下,聚合根是通过事件溯源得到,所以无法应用ORM来实现,自然也就无法利用lazyload的机制,所以我设计了该方法(相当于用自己的方式实现了lazyload)。为了思考该方法的名称,我想了很久,最终还是用WakeupAggregateRoot,因为我认为领域模型中的所有对象都是生活在内存中的对象,不存在从另外一个地方取过来的说法,对于聚合根来说,仓储对他是不可见的,仓储可以理解为存放了整个领域模型中所有聚合根对象的一个内存池。我们一定是在需要该关联对象的时候直接“呼叫它”,”唤醒它“,但是我们又不想直接存放该对象的引用,所以需要一种手段明确将它从内存唤醒,从而与他配合工作;
第三个方法的背景是:有时我们在某个聚合根内做了一件事情,并且由于职责所需它在做完这件事情后随即创建了另外一个聚合根对象。但是new 一个对象虽说也是创建对象,但是终究没有其他任何人知道你new了一个对象,当然,我们都知道聚合根对象只是被new出来还是不够的,我们终究还是要将它放入某个内存集合或数据库。但是new出该聚合根对象的对象又不知道该怎么把该对象放入集合或数据库,它能做的只能是通知别人“我new了一个聚合根”,我觉得:"聚合根不应该有意图去告诉别人请你帮我保存一下另一个聚合根或保存一下自己,对一个聚合根来说,它应该压根就不知道保存为何物,保存一般来说是以前数据库的思维"。所以,我引入了OnAggregateRootCreated方法,用来起到某种通知作用,这种通知可以这样理解:"我new了某个聚合根,请大家知晓一下“,仅此而已,完全没有更多如”请大家帮我保存一下“的意图。
我发现,这三个方法的引入,可以解决大部分event sourcing模式下聚合根与聚合根的交互问题,从此我基本不用再依赖于领域服务之类的设计构造块了。当然DCI中的角色与场景的引入,那对event sourcing以及DDD来说,又可以更自然的进一步的消除领域服务了。
[该贴被tangxuehua于2013-01-04 22:55修改过]