ORM真的不适合DDD

13-10-08 daxnet
第一篇帖子,先自我介绍一下,我从07年开始关注并实践DDD,也一直在关注jdon的成长(虽然一直没有注册ID并发言)。自己的tech stack是.NET阵营的,一致也在致力推广.NET下DDD的实践。但设计和架构上的思想基本还是一致的。

最近在思考一些ORM和DDD的问题,但是不知道我的思路是否正确。还请banq以及各位大师指点。

问题来自一个非常简单的建模:文章(Article)、类别(Category)。根据当前的应用场景,从聚合划分上看,简单地说,“文章”、“类别”都属于聚合根,由于类别不是文章应具备的一个属性(因为文章本身不会因为没有被归到某个类别而不成其为文章),反之亦然,所以它们之间互相是没有引用的。

稍作分析,可以发现,其实在这个例子中,还有一个隐藏的聚合,称之为“分类(categorization)”,它是对文章与类别之间关系的描述,当然,这个“分类”也无法聚合“文章”和“类别”,因为“文章”、“类别”两者与“分类”的生命周期是不同的,因此只能通过ID关联。于是,模型大致如下(抱歉是C#的代码):

public class Article
{
    public virtual Guid ID { get; set; }
    public virtual string Title { get; set; }
    public virtual string Content { get; set; }
}

public class Category
{
    public virtual Guid ID { get; set; }
    public virtual string Name { get; set; }
}

public class Categorization
{
    public virtual Guid ID { get; set; }
    public virtual Guid CategoryID { get; set; }
    public virtual Guid ArticleID { get; set; }
}
<p>

在得到了上面的假设之后,我开始使用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修改过]

                   

14
w438418754
2013-10-08 14:10
有关系的,Categorization与Article(或Category) 是多对一的关系,

daxnet
2013-10-08 16:00
对,我们的理解是有关系的,然而正如我上面的分析,在Domain Model确定这些聚合的时候,情况却不一样。

px96004
2013-10-08 16:37
不太理解啊...既然要求

Category和Categorization之间、Article和Categorization是无法直接引用的(领域建模不允许这么做)

那就不引用了呗...

在hibernate里面不设置 一对一,一对多之类的关系呗...

不就行了么?

daxnet
2013-10-08 17:31
当然可以不设置,但在自动产生ID值的时候会存在问题,比如如果使用guid generator,那么当我们创建一个Article的时候,如果同时希望能够将它归类到一个类别中,于是就需要在同一个事物中同时更新categorization,但这时候事实上Article的ID没有生成。

虽然可以使用assigned的方式,由构造函数自己产生ID,但这种做法还是有些不自然。

猜你喜欢
11Go 1 2 3 4 ... 11 下一页