从DDD中实体和值对象的逆向思考想到的
目前好多搞软件开发的人仍然从数据库编程的思想出发考虑问题。实际在我刚接触编程的时候也是数据库的设计思想,脑子里总是想着数据如何存储的,然后再去设计实现。从DDD的角度,这个是完全错误的思想,而且也违背了OO设计思想。
DDD中的实体和值对象在我刚开始接触的时候,理解了一点,但是总感觉欠缺什么地方没有搞明白,总是考虑持久化的问题,总在思考:既然在实体中包含了值对象,那这个值对象的数据如何存储(也许是数据库思想深入的缘故)。但是随着对DDD的深入,突然有了个逆向思维值对象的思考,不知道是否这样理解妥当。
实体和值对象的思考层面是业务层的内容。在这里抛弃如何持久化的问题。我们只是在设计我们的领域模型,让他更符合业务规则。
但是毕竟在软件实现的时候,持久化是我们要考虑的,虽然思考的时机有可能延后,但是不是可以回避的问题。我这样思考,OO是对象的集合,对象间的作用。数据库是过程化,数据是平行的,没有先后,没有主次,那么如果从数据库的思想出发,如何将这些平行的数据转化为OO中的对象是一个出发点(虽然这个出发点不对,但是是逆向的思考),数据库中的字段对应着对象的属性,此时问题来了,如何将这些字段组装到一个对象中。字段在对象中找到合适归属是个问题,以往我们从数据库结构直接生成POJO的做法就是一种,但是从这个角度讲,这变成了等价转换,中间没有任何的变化,只是表现形式不一样而已。表对应实体,属性对应字段。完全成为了一种数据库表的对象表现形式,对象完全成为了数据库的表中数据的载体。这种方式是反模式,也就是我们常说的贫血模型。从这个角度考虑显然是错误。主要是因为中间少了一个环节,这个环节就是如何把数据库的平行结构转换为对象结构,而不是单纯的拷贝(注意:逆向思考)。也就是转换为实体和值对象的结合,代表我们领域里的真正模型!这个也就是利用DDD分析的一个方面(当然DDD的分析不会是我们这里讨论的从数据库角度考虑的问题,我们这里只是逆向的倒推而已)
如何真的能从数据库的这种结果转换为真正意义上的实体和值对象。那么也就完成了关系数据到业务实体模型的转换。
这样才能真正将关系平行数据(过程式开发)向真正实体模型(面向对象开发)转换。
这个时候再想想,我们在开发中的一部分也就是在做目前的逆向思维的操作,通过数据库表结构,利用eclipse 来生成所谓的贫血实体POJO,这个时候完全失去了对象的意义,POJO完全成为了数据的载体,没有业务模型存在。
好一点的做法(尽管很荒唐)是:在数据库结构出来后,自动生成了POJO后,然后再将一些字段合并成为对象,表示他们应该集中到一个或者多个对象中。但这个时候又要被数据库牵着总,因为我们要考虑他们如何持久化到对应的表中的问题,所以这个时候的分析始终脱离不了数据库的结构。依然约束了你的模型分析。
以上说的在开发中很常见,很多人也都是这么来做的。这个反向思考反映了两个问题:
一:我们使用的是面向对象的语言JAVA,但是面向对象的特性好象在这个开发过程中没有任何体现,那我们为什么要用JAVA,用PB,DELPH也可以吧,开发还快,何必自讨苦吃。
二:尽管我们是想利用JAVA来OO,但是从我们开始数据库结构设计开始,我们都是在设计平行关系。没有层次行,只是平行的。所以无论你怎么想在POJO中体现OO,都会被数据库结构牵着走,因为你的脑海始终有数据库结构的影子,违背了数据库设计的结构,就不能被持久化(虽然有hibernate).这样,你依然不能OO。
综上,这样的思考方式终归应用OO语言没有任何意义,还不如去换其他过程语言实现来得快点(因为好多人都说JAVA复杂,而且大多数是以过程开发的人居多)
那么这个时候我们换一下考虑方式,抛开数据库,从DDD的想法出发,设计出的实体模型,既符合业务,又是OO的,那有人会问,这个时候有实体和值对象的问题,如何持久化呢?大家别忘了,hibernate为我们做了。这个也就是我们为什么要用hibernate的原因,虽然我们使用的实体和值对象是两个对象,实体可以对应数据库中的一张表,但是值对象呢,实际也是同一张表了(这只是一种简单的方式而已),只是我们把值对象平铺一下,把里面的属性提取出来,和实体中的属性平行,一同放到数据库中。这个提取,平铺的过程也就是hibernate为我们做了,那么这个时候考虑下,表结构是依据我们的实体和值对象结构来生成的,所以现在不是我们依赖数据库了,而是数据库的结构是受实体和值对象结构约束的(利用了hibernate的hbm2dll来实现),这个时候,数据库已经被我们抛到九霄云外了。不用理采他。他只用来hibernate数据而已。我们只要用我们的JAVA来做OO的东西就行了。
当然,我们还要熟悉hibernate,你才能更好的理解如何将实体和值对象转换为数据库结构。
以上也是我有感而发的,理解不到位的地方请大家指正
[该贴被lovejdon于2009-09-25 17:57修改过]