对领域驱动设计的初步认识(六)
第一次看到banq关于JF的PPT时,我突然发现原来可以这样建模,领域模型是这样丰富,让领域对象充满了色彩。过去看到的OO都是“简单实体建模”:即从需求中挖出几个实体对象,然后填充属性,至于其它的东西只要会查询就行了。这种建模方式随处可见,实在是太流行了,似乎让我们相信其实OO就是“贫血对象”。DDD之所以让领域对象富有生命,是因为值对象的存在。DDD采取的是“特征建模”思想,领域对象不仅仅有实体对象,还有表示状态的值对象。
DDD强调“充血模型”。在复杂业务中,这很有用,可以提高对象的可复用性。但是要注意,“充血模型”虽然很好,但其背后却隐藏玄机。复杂场景中,如果所有的行为都放到了对象中,那领域对象就会变得沉重无比,带来各种副作用。同时,描述状态的值对象往往不是一蹴而就,而是充满着变化,难以把握。当业务不明时,"贫血模型"容易把握,这也就是为什么现在”充血模型“不多,而"贫血模型"大行其道的原因。
DDD认为"领域对象应该是有行为的",大家都认可。如果说"贫血模型"造成了对象和行为的分离的话;那么"充血模型"也是有问题的,因为DDD中简单地认为把行为放到对象中就行了,殊不知这其实是关于对象和行为之间的一种静态地僵化的看法。而DCI对这种思想进行了修正,认为对象在场景中才具有行为。对于DCI中的对象(数据),我的理解和banq不同。我认为DCI中的对象(数据)是一种裸对象,但却不是简单意义上的"贫血对象"。DCI中的对象和行为是一种动态关系,是依赖于场景而存在的。这也就是说对象不会无缘无故的产生行为,(呵呵,那是神经病),对象具有行为一定是有意义的。也许有人担心场景会变成"贫血对象"模式下service那样的噩梦,造成对象和行为的分离。其实不用担心,在DCI中可以用"事件"把对象和行为联系在一起就避免了"贫血对象"的问题。呵呵,这是不是应了中国的一句老话:"分久必合,合久必分"。
关于jivejdon中的Account,在我看来不太准确。我是从复杂场景来看这个问题的,我们都知道在企业里account这个领域对象是属于HR模块的,真正的Account对象并不独属于Jive这个域。所以在jivejdon中应该有一个独立的account对象,然后有一个AccountInJive对象,这个AccountInJive对象才拥有Account和AccountMessageVO值对象。(大家可以讨论一下:如果Account在另外一个服务器上,那么这个account在JiveJdon是贫血对象还是领域对象?)
另外,对于DDD中的聚合,我也有不同的理解。其实DDD提出聚合的概念是为了保证领域内对象之间的一致性问题。但是我对DDD中对"聚合"这个概念的落地形式表示质疑,DDD特别强调聚合根的封装性,然而这可能会导致领域内对象之间的逻辑强耦合。也许有人说领域内部的对象是高内聚的,这样做没关系。但是在实战中,领域模型内部的值对象往往存在着变数,这是我们认识客观世界的必然规律。然而这会导致领域模型的不稳定性。所以我认为及时领域内部的对象也应该注意低耦合,这个问题同样需要靠事件来解决,事件才是保证领域对象一致性的关键。
[该贴被flyzb于2010-11-17 22:56修改过]