再谈面向对象的数据设计

李战 2003-04-17 02:07:51
哈哈哈
面向对象的问题似乎永远是个无底洞,面向对象的数据库更是看不见的黑洞。为什么要用面向对象的思想来设计数据库,是因为传统的数据库设计思想不能解决日益复杂的业务数据关系。

反对面向对象的数据库设计也是可以理解的,因为,长期以来的确还没有成熟的商业化的面向对象数据库出现,更不用说其性能要多么优秀。但面向对象的路却一直伸向远方,永没有回头的路标。

假如让你对我们日常的对象建模,最简单的莫过于:家人、朋友、网友、公司、部门、员工、经理、用户、客户、供应商....你会用几个关系表来表达?

这些都是很实在的现实对象,现不用考虑合同、订单、发票等等。
我们先来最直接的,每一个对象建立一个表如下:
家人 Family (Name, Sex, Age, Birthday, Relation...)
朋友 Friend (Name, Sex, Age, Tel, ...)
网友 Neter (Name, Sex, Age, NikeName, QQ, ...)
同事 Staffer(StafferNo, Name, Sex, Age, WorkAge, Tel, ...)
经理 Manager (Name, Level, ...)

不要说我这样建模太简单,很多实际系统的确就是与这样的形式差不多。这样做的好处是直观,一个对一个,编程也方便呀。

一些有经验的分析人员会将一些共同的字段抽象出来,放到另一个表中,不同的字段才分开存储在不同表中。例如,我们可以建立一个人员表(Person)来存放Family, Friend, Neter, Staffer的那些共同的Name, Sex, Age字段,然后构造一个ID来关联共同部分的和不同部分的两个表。

这个抽象出Person表的设计方式便是面向对象数据库设计的雏形,那个ID也就是所谓的对象标识。这些表的字段可能就变为以下形式:
人员 Person (ID, Name, Sex, Age, ....)
家人 Family (ID, Birthday, Relation...)
朋友 Friend (ID, Tel, ...)
网友 Neter (ID, NikeName, QQ, ...)
同事 Staffer(ID, StafferNo, WorkAge, Tel, ...)
经理 Manager (ID, Level, ...)

当要访问同事数据时,实际上是将Person表和Staffer表通过ID连结起来的数据集。

越来越多的系统分析和设计人员认识到ID在数据关联之间的特殊作用,而关系数据库的开发商也为此提供一种称为“自增量”字段的东东来适应着永需要。这种ID一般对系统的使用者没有任何意义,仅仅是为了解决关系表的主键和关联问题。

这种ID其实就是面向对象数据库中普遍应用的对象标识。因为在面向对象的数据库中,任何一个对象记录都会有一个绝对唯一对象标识。记得以前我讲个一个王菲的故事,我想,多少人都会理解的。

在对象模型实现为关系表的过程中,所谓“一类一表”的原则就是指抽象出的每一个类,无论其继承关系多深,属性字段多少,只要有一个类,便建立一个关系表。访问一个类的时候,即访问该类极其所有父类的那些表的关联数据集。一个检索数据的SQL语句往往是非常壮观的,例如:

select * from C1 join C2 on C2.ID=C1.ID ... join Cn on Cn.ID=C1.ID ..... where ...

插入、修改或删除对象记录时,也往往会分成几个insert、update和delete语句来实现。

而面向对象数据库的目标是,将着一切都简化为OOSQL来实现,例如查询同事数据:

select * from Staffer where ....

这里的Staffer不再是个简单的表,其也会返回父表Person的字段。对象数据库会幕后根据类与类的关系,实现关联。插入、修改或删除对象记录也是如此。似乎,也只有这样才能解决对象数据库的检索问题,并保持与关系数据库的兼容。当然,OOSQL的语法可能是别的形式,或者是SQL语法的扩充。

我们再来考虑一个比较有趣的情况。如果你在网上认识了一个女孩,那么在你系统的网友表中一定会有一条关于这个女孩的记录,当然,肯定也会在Person表中有一条关联记录。后来,你和她成为了要好的朋友,于是,在系统的Friend表中也会有一条记录,其ID还是原来的。在你的推荐下,老板同意她到你的公司上班,这时,Staffer表中又会多一条记录。她干得不错被老板提拔为经理,你的Manager表中就少不了她。最后,你和她相爱并结婚,哈,Family表中都会有记录了!

这其实是一个对象类型演化的问题,同时也是一个面向对象思想前沿研究的问题。这样的问题还包括其它例子,如对象构造过程问题、生存周期问题、时态属性问题。很早以前我说个一个小蝌蚪找妈妈的故事,就是这个问题的典型例子。

小蝌蚪本来是青蛙身上的一个卵细胞,细胞与主体显然是整体与部分之间的关系。但这个部分被分离出来成为一个独立的对象,而这个对象的属性与青蛙似乎相差很大。但随着类型的不断演化,小蝌蚪的鳃消失了,尾巴越来越短,慢慢地长出了腿。最终与青蛙妈妈一样了,请问:这个小青蛙与青蛙妈妈是部分与整体的关系呢,还是继承关系?

这似乎是个哲学问题,但所有科学问题最终会遇到哲学问题!有头脑的程序员是会从哲学方面来思考软件结构的。

这些建模问题恐怕不能简单地从整体还是部分,组成还是继承,引用还是拥有等传统的面向对象的思想来考虑。如果能够,那么你思考一下,你刚才认识的那个女孩在这些类表之间到底是什么关系呢。

本来,组织和分类都是人的意识产生的,这是我们人类认识和思考世界的基本方法。当面向对象的思想面世的时候,人们认识到这本来就是人类思维的基本原则。因此,广泛的被人们所接受,迅速成为最普及的软件思想。结果很简单,但其中走过的路实在太漫长......

希望明天飞来更多的砖头,哈哈哈

李战.深圳
...全文
25 点赞 收藏 5
写回复
5 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
blueshrimp 2003-04-17
再次表示关注,现实世界太复杂了,就像上次一位朋友讲的,医院信息系统用了一年,就达到了100G的数据

王菲出生时,就是一个对象了,有唯一编号。而她的名字,身份证等都只是一个属性。属性可以改,但同时必须保留原数据。要不然,不就像失忆了一样了吗。身份证虽改了,但老身份证注册的房子就不是我产权了吗?这肯定是不行了。

但楼主提到的青蛙问题,就没办法解决了。从一个细胞变成蝌蚪,再变成青蛙,又有子青蛙。那是先有鸡还是先有蛋的问题了。定下来,我们就说他是先有蛋。蛋的Parent为nil,从这个蛋开始,后面的蛋就都有parent了。就像有些人家里的祖谱,他总有一个开始吧。
回复
blueshrimp 2003-04-17
再次表示头晕,看完了,大概理解了
回复
yoisyois 2003-04-17
帮你把王菲的故事加上 ^_^

从前,在北京降生了一个漂亮的小女孩。接生的李阿姨说,她的声音这么大,好象想要全世界的人都听到。 他的父母就为她取了一个很好听的名字,叫“王菲”。于是,所有的小朋友就叫她“王菲”,“王菲”就是她童年的标识。 在她上初二的时候,认识了二班另一个叫“王菲”的同学,而且和她同一天生日。不过,同学们常常将她俩叫错,后来,就分别叫她们“大王菲”和“小王菲”。
在大王菲18岁的那一年,她领到了她的身份证。从此,她有了新的身份标识“100321690808022”,这一标识可以唯一区别中国大陆的每一个人。同时,原来二班的“小王菲”也领到了她自己的身份证,“100321690808006”。于是,人们就可以用身份证号,唯一标识两个“王菲”了,虽然谁也不会直接叫她们的身份证号码。 由于她的歌唱的非常好,没多就就成了歌星。歌迷们将“王菲”这一标识与她的歌紧紧地联系在一起。
后来她去了香港发展,并将自己的名称更改为“王靖雯”,同时还领到了香港的身份证,有了香港的身份标识。 没多久,王靖雯和一个弹电吉他的小子相爱了。那小子说,还是“王菲”这个名字好听。后来,“王靖雯”又变回“王菲”了。结果,歌迷们又遇到了麻烦,是将她的歌关联到“王菲”还是“王靖雯”呢,在歌迷中引起一阵混乱。
她和那个弹电吉他的小子结婚了,香港政府将他们的身份证号码,用结婚证书关联起来。可是,月老在酒醒之后发现了这一错误,就将关联的记录删除了。 虽然,她和那个弹电吉他的小子分手了,但是,正如接生的李阿姨说的那样,她的声音的确让全世界的人都听到了。
回复
blueshrimp 2003-04-17
先UP一下再接着看。
回复
yoisyois 2003-04-17
开了眼界。^_^
回复
发帖
数据库相关
创建于2007-08-02

2451

社区成员

Delphi 数据库相关
申请成为版主
帖子事件
创建了帖子
2003-04-17 02:07
社区公告
暂无公告