ORM真的不适合DDD
第一篇帖子,先自我介绍一下,我从07年开始关注并实践DDD,也一直在关注jdon的成长(虽然一直没有注册ID并发言)。自己的tech stack是.NET阵营的,一致也在致力推广.NET下DDD的实践。但设计和架构上的思想基本还是一致的。
最近在思考一些ORM和DDD的问题,但是不知道我的思路是否正确。还请banq以及各位大师指点。
问题来自一个非常简单的建模:文章(Article)、类别(Category)。根据当前的应用场景,从聚合划分上看,简单地说,“文章”、“类别”都属于聚合根,由于类别不是文章应具备的一个属性(因为文章本身不会因为没有被归到某个类别而不成其为文章),反之亦然,所以它们之间互相是没有引用的。
稍作分析,可以发现,其实在这个例子中,还有一个隐藏的聚合,称之为“分类(categorization)”,它是对文章与类别之间关系的描述,当然,这个“分类”也无法聚合“文章”和“类别”,因为“文章”、“类别”两者与“分类”的生命周期是不同的,因此只能通过ID关联。于是,模型大致如下(抱歉是C的代码):
|
在得到了上面的假设之后,我开始使用NHibernate(Java阵营是Hibernate)试图完成对上述模型的持久化。根据DDD,Repository管理聚合生命周期,Repository模式的引入,让Domain Model能够独立于持久化机制(ORM或者其它),从而剥离出一个非常纯净的Domain Model。于是,结合NHibernate,我原以为实现一个基于NHibernate的Repository,就能将聚合直接由Repository转交给NHibernate,从而使用NHibernate这一ORM产品来实现对象生命周期管理。
不幸的是,我发现我无法在NHibernate中配置用于上述Model的映射方案:Categorization.CategoryID属性是关联到Category.ID的(从数据库角度看,就是一个外键关联),然而要在NHibernate中正确地配置外键关联,就必须要求两个对象之间有一对一、一对多等等属性引用。但一开始我们就分析了:在我们的Domain Model中,Category和Categorization之间、Article和Categorization是无法直接引用的(领域建模不允许这么做)。
于是,我就意识到,DDD社区中所谓的Impedance Mismatch,并不是说Domain Model与关系型数据库之间的Mismatch,而是Domain Model与整套关系模型之间的Mismatch。因此,要解决这里的问题,我们还需要有一层面向NHibernate ORM的对象关系模型(即持久化模型),并在Repository中将Domain Model转换为持久化模型,然后再使用NHibernate。
总结起来,这个过程就是:
Domain Model -> Repository -> (translate to) Persistance Model -> ORM (eg. NHibernate)
换句话说,相对于其它对象数据库和NoSQL而言,ORM无法很好地支持DDD,还需要有一层从Domain Model到Persistance Model的映射。
不知我的理解是否正确。恳请指点。
[该贴被admin于2014-03-09 07:44修改过]