飞跃迷雾,把OO看清楚

(一)抽象之美
OO直接翻译过来就是“面向对象”,它作为一种编程思想可以说是划时代的进化。虽说可能不是传说中的“银弹”(解决软件太复杂的万能灵丹),但是却能使挣扎在“焦油坑”中,那些绝望而无助的受难者猛然间看到希望。写《人月神话》的时候OO还没有出来,现在作者很可能对于这一项技术性的变革投以赞赏的目光。
有 人说,编程是门艺术。而我认为,更重要的思想认识是——软件工程是门哲学。事实上,面向对象最重要的思想我认为就是来源于哲学思想。具体来说,就是——抽 象化。这里我直接把百度百科里面关于哲学里的抽象引述一遍——“抽象是认识复杂现象过程中使用的思维工具,即抽出事物本质的共同的特性而暂不考虑它的细 节,不考虑其他因素。 ”通过抽象化,我们的软件系统就可以抓住事物的共性,从而抓住事物的本质。由于诸多因素,导致的结果是——软件需求在不断变化。而事物本质变化却不会像需 求变化那样大。这样,应付需求的变化,我们只需要在原来抽象化的软件模型的基础上做局部修改。举个例子:我们制造出汽车,放在普通公路上,我们的需求是安 全、便捷的行驶,放在赛道上则是需要尽可能跑得快。两者需求大不同,却不需要我们重复创造两个汽车类,而是只要在汽车类的基础上做局部的修改。从这个方面 来看,我认为,可以把“面向对象”理解为“面向类”。
另外,通过面向对象的方法建立的软件模型也符合人类认识事物的习惯,便于理解。这一点,对于 一个软件团队来说,是高效沟通的有力保障,它所带来的益处完全可以提高到战略高度。因为一个清晰明了的设计模型,是团队成员相互沟通的有力保障。这一点, 在《人月神话》书中也花了大量篇幅介绍团队成员如何有效沟通,前辈们甚至用上了微型胶片来减少存档量。如今,一个简单明了的设计模型减少了很多这方面的投 入。
关于“面向对象”的认识,到了这一层,我们似乎可以用平静的心去实现陌生领域中的软件建模,而不是面对复杂多变的需求焦虑又不知所措,就像 “焦油坑”中绝望无助的怪兽,越挣扎下沉的越快,也不会面对当下层出不穷的新技术、新概念产生迷茫、踌躇不前。剩下的问题就是捕获需求,抽象化,寻找其中 的类……而那些设计模式、持久化等概念便会自上而下的体会到。到那时,我们或许会因为与前辈在思想上产生共鸣而会心一笑。
光说不练假把式,这里拿一个例子来结尾。大学OO教材有个电梯建模的习题,需求简单明了,就拿这个举例吧。
现实生活中,坐电梯无非就是涉及到以下一些内容:电梯、人、楼层、信号灯、上、下、开门、关门……软件建模就是一种“思想实践”,这些内容都是在我们脑子里,并不是要造出实体。所以,可以根据上面获得一些零散的信息,抽象的归纳客观事物的映射。比如,什么是电梯?电梯是能上能下将人送到预定的楼层。好了,有了这个简单的定义(不一定要求很准确,只要在可容忍的范围就行,而这个范围是系统愿景确定的),我们大致归纳出电梯的属性有:楼层、信号灯、电梯门这些。这个电梯类具有的行为可以有:上、下、停、开门、关门。这里为什么不把楼层和人单独归纳出一个类来?因为人其实是电梯的使用者,而楼层在坐电梯这个客观事件中只是一个数字,并没有什么行为。
但是,坐电梯这个事件,光有个电梯似乎还是不行的。因为,还要符合将人送至他想到达的楼层的愿望。这就涉及到人在哪个楼层,他是上还是下,他要上或者下到几楼。这里我们找不到客观实物来映射到软件模型,不像电梯类是客观现实中存在的实物。那么,这里我们就要抽象归纳出客观世界中看不见,摸不着的东西来。回到现实中来看,例如电梯在1楼,5楼有人要下,那么电梯就上到5楼,停下来,人进去。电梯根据人的指令,下到他想到的楼层。如果电梯在1楼上到5楼途中,2楼有人要上,电梯就会在2楼停下来。再如果,2楼的人要去10楼,电梯就不会在上的途中停在5楼,而是上到10楼后停下来,再下到5楼停下来。这样我们就可以发现——电梯只管上和下,至于在哪里停,则是根据人发出的指令。而这些指令其实就是一串数字,一串要求电梯在哪里停的数字,而且是随时可能变化的。比如,刚才说的那种情况,停车数字是1(电梯开始停的楼层)、2、10、5、1(5楼要下的楼层)。这样,我们就可以抽象出一个类,一个客观现实中看不到,摸不着的类——电梯停队列类。这个类属性有最高层、最底层、需要停的楼层,行为有添加需要停的楼层,移除需要停的楼层。
下面是对应的类图。



从这个例子中可以看出,电梯类很容易找到。但是电梯停队列则是我们对现实世界中的业务流程进行归纳、抽象得出来的。所以,我认为,软件建模的重心,其实是在对业务流程的抽象上。
上述整个过程符合人们日常惯性思维,现实和模型映射起来很自然。可以将这个过程看成是一个“创建世界”的过程,是一件很愉悦的过程,最起码我是非常喜欢这种“建造”软件模型的过程,这种抽象抽象再抽象的过程。这个例子需求简单明了,我们很容易就收集到了足够的素材来归纳、抽象。如果是在一个陌生的领域创建软件模形,抽象素材从哪里来,怎样抽象?我们就要探索需求,而探索需求过程不仅限于OO,但是OO的思维方式却能更好的和问题域中的专家沟通,更好的理解需求。

2011年03月14日 11:07 "showerxp"的内容
电梯类很容易找到。但是电梯停队列则是我们对现实世界中的业务流程进行归纳、抽象得出来的。 ...

楼主其他都写得很好,大家都有共识,但是现在为什么不同人建模结果不一致呢?这说明建模本身有些规律或科学性没有受到重视,如果能够重视这个规律,我想大家建模的结果可能就相差无几。

现在我们就讨论一个规则:电梯队列作为业务流程归纳抽象,是否有必要?而这个电梯队列和电梯性质是否一样,如果画类图,很容易让人将两者性质等同。

在实际生活中肯定是无电梯队列的,那么我们为什么要抽象电梯队列呢?没有抽象出电梯集合,或电梯服务呢?这些疑问就导致了不同人建模的结果不一样。

如果细分楼主电梯队列中元素,我看可以分解为几个值对象:电梯运动规则(最高楼层 最小楼层);电梯状态(电梯当前在哪一层);电梯服务(提供给客户上下的指令)。

我想用这两个值对象,一个服务,以电梯为根实体,形成一个DDD聚合边界,是不是更加简单明了清晰呢?

2011年03月14日 11:07 "showerxp"的内容
再如果,2楼的人要去10楼,电梯就不会在上的途中停在5楼,而是上到10楼后停下来,再下到5楼停下来。 ...

可能乘坐的电梯不同,还是我记错了,好像是会停下来的,不过先还是继续往上升,而后再下来。

每个用户的愿望可表示为一个请求,请求可以用(出发楼层,目的楼层)二维坐标表示,比如(5, 1) (2, 10)。

现在假如只有一个请求(5,1),比较简单,电梯从其所停的楼层跑到5楼停,开门,关门;然后跑到1楼停,开门,关门。电梯的开门、关门、信号灯显示、上、下等诸多操作比较简单,容易明白。

但存在多个请求时,如何对请求进行排队,并将二维坐标集调整为一维坐标集(如上面的{(5,1)、(2, 10)}调整为{2,10,5,1}),好让电梯挨个进行处理。这个需要制定策略,也就说对请求进行动态排序(统筹)是个重点,排得好,对所有乘客都公平,且客观上也会节约乘客的时间。

showerxp 对这个没有详细说,希望可以补充一下。

2011年03月14日 18:37 "jdon007"的内容
可能乘坐的电梯不同,还是我记错了,好像是会停下来的,不过先还是继续往上升,而后再下来。 ...

这个也许是需求不同,我遇过两种电梯,一种是请求按钮分上下,这种是会根据请求而决定是否停下,顺路则停,否则不停;另外一种是不分的,不管你上还是下,都停。

其实对电梯的分析,我仍是一种多用户思维(原因是不会因为停止使用某层而停止整个电梯,或者说电梯控点是可增减的)。所以可以把每个控点看作一个用户,电梯为聚合根,可内聚运动规则(策略)。那么监控设备,可以统计电梯的使用状况(有点像持久化)。

至于策略,我自己想到一种:一个记录请求的双向链表,链表长度跟控点个数一样,层与层之间开始检测,当下一个请求跟方向当时运动方向相同则停下。

电梯自动化控制软件的建模需要考虑乘客的需求,而解决需求的满意度可以从两个方面衡量:1)公平 2)效率。所以,制定策略可以从这两者入手:1)公平优先兼具效率 2)效率优先兼具公平。

在贴子中1,2,10,5,1的排序在这两点上都不尽善人意,试分析一下。

先复述一下问题,电梯的初态为1,第一个请求为(5,1), 在电梯经过第2层时,第二个请求为(2,10)。现在假设电梯跑一层的时间为1个单位时间,简单起见电梯停的时间不计算在内。那么电梯最公平同时最高效地将两位乘客运往目的层的时间是 (5-1) * 2 + (10-2) = 16(单位时间)。但实际两者往往不能两全,这常常只是理想。

计算一下帖子中的排序方式花了多少个时间单位(所有乘客花费的时间之和。这里效率的含义是乘客花费的时间之和,而不是电梯的工作时间),(10-1)*2 + (10-2) = 26 (单位时间),第一个乘客本来只需要等(5-1)*2个单位时间就可以到达目的地,现正却需要(10-1)*2个单位时间,对他来说相当不公平。

那么我们现在根据第一个原则来制定策略,公平优先,比如先发出请求的电梯先服务,第一个乘客需要(5-1)*2 = 8个单位时间,第二个乘客需要(5-2) + (5-1) + (2-1) + (10-2) = 16个单位时间,总共时间24个单位时间,无论从公平还是效率的角度比帖子中的方案要好。此外,还需要兼具效率,比如电梯在运输第一位乘客时(1->5, 5->1),顺路的可以搭乘,比如一个(1->5)的过程中,第三位乘客的请求为(3,5),在(5->1)的过程中,第四位乘客的请求为(4,1),就可以搭乘。

用数学的方式大致描述一下。设电梯初态为N0, 请求队列的一个请求为(N1, N2), 第二个请求为(N3, N4)。那么电梯的响应序列为(N0->N1->N2), 如果(N3, N4)可以刚好可以插入在(N0->N1)或(N1->N2)的过程中,那么电梯的响应序列为(N0->N1->N3->N4->N2)或(N0->N1->N3->N4->N2)。

公平优先兼具效率,效率往往达不到最高,具体例子就不试举了。如果采用第二种原则:效率优先兼具公平,这个应该会难一些,统筹时间,节约时间有时并不容易。若还考虑到每个请求的权重,即有基本相同愿望的乘客的人数,就更难了。如果电费极其昂贵,此时就得从效率优先的角度考虑,而且考虑的是电梯的工作时间,而不再是乘客花费的时间之和了。

当然基于同样的原则也可能产生不同的策略,比如同样根据第一种原则可以采用公交车式的策略。电梯每次只管1个方向开,乘客顺路则上车,到达目的地则下车,对乘客来说也是公平的,而后兼具效率,比如电梯对已有向上的请求都已经处理,而且等了片刻,在停的楼层之上并无新的向上的请求,就可以转头解决向下的请求。

感觉这里采用OO或DDD对其建模也许没有必要或者说不是核心,根据用户的需求将其提炼或抽象为一个“排序”问题,也是一种建模,模型的表达方式不止OO,不止DDD,也不止数学。总之,建模或抽象应该带来更清晰、简洁的语义,促进我们更有效地解决问题,形式上的东西可随后考虑。

2011年03月15日 10:46 "jdon007"的内容
1)公平优先兼具效率 2)效率优先兼具公平。 ...

恩,这才是回归自然。

至于DDD还是其他思维建模,完全可以自选,只是一个方案,必须由此至终都是以一种严谨的思维贯穿其中,不能多选,因为不能保证一种思维里面和另一种思维兼容,或者说不会出现误解。而DDD只是其中一种选择,若果认为自己比DDD更好,而且也是严谨的,可以选用自己的,不过对于某些人而言,学DDD能成为自己的快餐。

2011年03月14日 16:13 "banq"的内容
电梯队列作为业务流程归纳抽象,是否有必要? ...

这个问题是见仁见智。生活中,没有看得见摸得着的电梯队列,而且这个名词还是我姑且用之。但是,肯定有电梯队列的这个业务流程。也怪我没有完全把电梯说明白,导致“电梯队列”这个东西不清不白。
我认为,决定电梯上还是下很简单,就是电梯所在楼层与下一次停车楼层比较。比如,电梯停止在1楼,下一停车楼层是10楼,电梯就上,反之则下。如果电梯上了10楼停下来,那么电梯就继续比较下一次停车楼层,比如5楼。也就是说,电梯的运行,始终只盯着下一次停车楼层。而电梯每经过一层就会重新确认一下下次停车楼层,也就是说,在电梯从1楼到10楼的过程中,下一次停车楼层可能随时改变,比如变成6楼。对于电梯来说,我的工作很单纯,就是当前楼层和下一停车楼层对比。而至于下一停车楼层怎样改变,我给出的方案就是电梯队列,或者说电梯停车队列更准确。

这个例子,我无非想说:抽象来源于生活,高于生活。抽象化的结果,可能是客观实体的映射,也可能是事物运行规律的映射。

这样看,上面的类图就还差一些东西,电梯类要加上“当前楼层”和“下一停车楼层”。至于值对象这个问题,在这里看无关痛痒,不是本文讨论重点。

本人觉得,软件建模没有客观性标准答案,根本标准是符合需求。
[该贴被showerxp于2011-03-15 14:17修改过]

2011年03月15日 10:46 "jdon007"的内容
感觉这里采用OO或DDD对其建模也许没有必要或者说不是核心,根据用户的需求将其提炼或抽象为一个“排序”问题,也是一种建模,模型的表达方式不止OO,不止DDD,也不止数学。 ...

是的。但是我所强调的OO软件建模就是一个抽象化的过程,为什么强调这个过程,是应为软件发展的趋势所定。

转一篇文章:解读抽象的力量——记图灵奖得主Barbara Liskov演讲

2009年,我在图灵奖获奖仪式上要做一个讲话,在我想这个演讲怎么讲的时候,我就决定把我看过的论文再重新看一看,就是说我达到获得图灵奖的成就的那些最初的想法是什么,今天我非常想与大家分享这个。

我在斯坦福大学拿到了博士学位,当时学的是人工智能,我在读博士读到一半的时候,决定放弃人工智能转而研究计算机系统,当然了,学博士最后要拿学位的,这样才能做进一步研究。我决定上学的时候先不转型,拿到学位以后再转型。之后我在一个机构工作,主要是做一些计算机的研究,我在博士毕业以后开始做计算机系统的研究了。

首先我参加了维纳斯机器的一个设计,当时谈一种微编程,也就是说我们给计算机一个小的指令组,而且给它很小的只读内存,这样在非常弱的指令组上面是没有办法写的。对于这个项目来说非常有趣的一点,Interdata 3这个指令组和今天的一个架构是没有什么不同的,当时人们写的很多程序是机器程序,而且要想直接使用那么弱的指令组编程是非常难的,今天编程语言更加高级,由编译器生成。这个指令组相对来说还是比较标准化的,我把这个信号语给放进去了,放在当时的一个操作系统上面,我认为在硬件当中必须要有这样的配置。

到70年代末期我又开始推进一个新的项目了,大家看到我们主要做系统设计,不再做任何的人工智能,而且是边做边学来理解计算机系统,70年代末又开始变成编程方法论。

当时政府发现他们正在经历软件危机,今天我们仍然在经历软件危机。这是什么意思?我们不了解如何高效地运用软件,那时候软件匮乏是很大的问题,有大批的失败项目。刚开始我们有一个想法,然而软件不能达到我们的要求,最后导致整个项目必须放弃。那个软件的成本比今天要高得多,比方说一个大型机的耗资能够达到几十万美元,大家根本不了解软件怎么做出来,大家感觉软件可以轻而易举的做出来,而且软件不花钱,硬件花钱,所以当时人们不愿意在软件方面投资、花钱,这样对于软件编程员来说工作很难做,而且他们的工作不受重视。今天众所周知软件也是很贵的,不会为了硬件牺牲软件了。

为准备我的图灵获奖感言,我去年又重读了几篇论文,这个很有价值,今天介绍给我们的同学们也读这几篇论文。在给美国研究生做报告的时候,我发现大部分人没有读过这些论文,建议大家去读:

首先想给大家讲的是E.W.Dijkstra写的Go To Statement Consider Harmful这篇论文,这个论文当时发表的时候引起了很大的争议。当时大家感觉很奇怪,让大家放弃Go to语句,我们就很难推理程序。一旦不能推理程序在做什么的时候,你怎么能确保程序会去做你想做的事情呢?而当你对程序做出推理的时候发现程序文本是一个静止的东西。你要推理的是程序动态的执行,你推理的过程如果想做得更加简单的话,你要能够把静态和动态统一在一起,如果用Go to转到这个做法,这样就很混乱,就没有结构。有一个结构化的方式理解程序更好理解。

还有另外一个非常重要的论文,是D.L.Parnas写的Information Distribution Aspects of Design Methodology,关于这样的话题写了两篇文章,写的是程序结构问题,他的论文当中有一些很有意思的论断,他说这个项目是由模块组成的,不知道这些模块究竟是什么,他说我们知道这样一个结构,必须了解这个结构,但是结构本身是不清楚的。模块是什么呢?想把这些模块组合起来,并且模块之间产生互动的话,就必须说明你的代码是正确的,必须理解这些模块是相互联系的,不是说这样的模块对另外模块产生预算,而是整个模块相互联系。所以在论文当中提出了非常重要的一条,各个模块之间的联系是模块相互之间的假设。这样一个联系其实比你想象的更为复杂,必须进行深入的了解。

当时我读这些论文的时候推出了我的Venus系统。我使用了他们论文当中提供的方法,当时搞了自己的团队,承担了很重要的任务。在我们项目最开始决定用一个特别的开发推动我们这个项目。讲到项目的时候,会有各种各样的流程,这些流程他们也是相互之间进行呼叫的,但是也会产生很多总体的变量。在 Venus中,我们会把整体的命令行分散,我们叫做分隔。对于每一个模块有自己所谓的指令表,每一个指令表有自己的变量,各个指令之间相互互动的时候叫做运算。也就是说同一个分割中有不同的运算。这样一种概念实际上是模块化的概念,在Venus项目中引用了这个。那个时候希望搞一个操作系统,就是用这种模块化的概念。

S.Schuman和P.Jourrand在他们的论文中谈到了可扩展语言的作用,当时这个论文是在1967年发布的,主要有两种方法,困难性的语言必须让编程语言改变语言,这样他们可以进一步的进行调整,里面有语意,讲到语意进一步拓展句法,看起来是非常有道理的。

还有一篇O-J. Dahl和C.A.R Hoar于1972年写的非常有轰动效应的一篇文章,Hierarchical Program Structures。在当时对于封闭没有产生概念,所以说没有把抽象以及分割两者之间结合起来。还有一篇是J.H.Morris的Protection in Programming Languages。这篇文章又开始讨论模块化的问题,模块化是非常重要的概念,如果有很大项目,每个模块规模又是比较大的,所以你要修正你的程序,必须修正不同的模块,要考虑这个模块是否完成了它应该做的事情。当时Morris问的问题是如何保证使用模块化的方式可以进行良好的调试。

到1974年夏天快结束的时候又要做一个抉择:下一步研究如何做。当时我选择继续研究设计程序语言,提出了抽象数据类型,提出有一系列的预算、对象以及所有的运算,只有通过这些运算才能对目标进行存取。这些论文中也对语言进行描述,说这是一个大概的框架、大致的架构。

为什么选择程序语言呢?讲到这样一种模块化,应该和虚拟数据类型结合起来的,人们需要了解里面的方法论。我觉得要走下一步其实是有必要原因的。首先编程语言就需要向程序员进行良好沟通,如果程序员不懂有什么意义呢?当时我们考虑到这一点,编程语言需要让编程员可以很好的了解,同时抽象数据类型是否真正的能够应用。想到一种想法怎么谈都行,但是讲到编程语言,把这个变成真正的实际使用。另一个原因,我希望对于这样一个概念,或者这样一个想法进行明确的定义,把这样一种想法具体的实施,因为我们这样一个想法本身是比较虚幻的,但是通过编程语言可以把这样的想法变成事实。

下面给大家讲讲设计流程。我想指出的是对于语言设计的目标其实和接口设计目标是一致的。我在这个项目之后也做了很多其他的项目,我始终把这些项目放在心上。一旦设计一个模块,或者大型、小型的界面、接口,必须考虑几点,首先考虑这样的模块是否能够考虑足够的表达能力。也就是说是否能够实现想要的目标。第二个原则是必须简单,如果你的程序员不了解这个程序如何编译,那么效率就很低了。同时它的绩效要比较高,而且使用起来很方便,否则是没有人愿意用这样的语言。对于任何的编程语言,这就是我们需要关注的四大目标。

我获得图灵奖以后,我的丈夫每天在网上找对我的赞誉,其实在我刚开始做研究的时候,没有人了解,但今天大家都知道了,这是主要的转变。现在在研究工作当中仍然有很多挑战,我起步非常早,但仍然有很多有趣的课题值得我们解决,对于下面的问题,我们需要更好的程序方法论,特别是在大规模并行计算的技术成为现实的时候。另外互联网本身也是一种计算机,我们如何来适应互联网时代的编程需要,也是我们有待解决的一个挑战。谢谢大家!

我们都应该认可抽象的力量,关键如何抽象的问题,抽象有时和主观臆想可能会一步之遥哦。

由此可见:抽象和个人背景经历有相当关系,如何摆脱这种个人影响而走向工程化呢?需要有一套大家都知晓的分析建模模式。

我个人认为:四色原型和领域建模DDD是一条实现如何抽象的共同模式,就象设计模式一样,如果大家都认同了,那么我们在需求分析领域因抽象产生歧义也许会消失。

抽象是把双刃剑,用不好反而可能让问题变得更难以理解,抽象必须是好的抽象才有必要采纳,衡量标准就是其是否提供更清晰、简洁的语义,帮助我们理解问题、解决问题。

从核心需求出发,根据需求制定各种具体的策略后,可以考虑使用OO和DDD进行表达或组织,如果需要的话。比如存在平时采用公平优先的策略,用电高峰期采用效率优先的策略的需求,就可用Strategy Pattern进行组织,根据需要切换策略。

电梯的软件模型可以通过按钮接收用户的请求(界面之控制器)并通过信号灯、声音等进行提示(界面之视图)。

电梯的软件模型可以保存自己的状态(当前的位置、运动方向/下一个位置、楼层的数目等),可以有自己的行为(上楼、下楼、开门、暂停、关门、停止等)。

这些行为比较单一,容易理解与实现。模型中还需要有一个队列(数据结构),该队列保存通过策略(算法)对用户的请求进行排队生成的序列,然后挨个执行各个序列值。

模型执行每个序列值的步骤:
1)从队列中取出一个值,如果是队列为空则停止。
2)根据当前位置与下一个位置的关系执行上楼或下楼;
3)当前位置与下一个位置相等时,暂停,开门一段时间,关门。
并重置当前位置。(界面可同时展示模型状态的变化。)
4)回到第1)步,重复执行。

公平与效率是核心需求,排队策略或算法需要去满足这个需求,其它的可以围绕这个中心进行组织或者由其驱动(策略及队列的结合相当于电梯的“心脏”)。这里领域的核心模型只有1个,即电梯,所以并不存在模型之间的交互行为(不考虑界面交互的话),DCI范式或者四色原型用不上,MVC范式足够用来组织代码了。

面向对象是对软件开发"抽象过程"的"形象化": 对非软件开发人员而言,面向对象比较容易"理解".oo技术同时也是functional programing的"形象化".oo和fp是"同构"的,但oo"形象化"的特征,导致oo永远比fp更容易被"非软件行业的人(包括很多ceo)理解".
楼主(二)呢???????????????
[该贴被axgle于2011-03-17 12:10修改过]

2011年03月17日 12:01 "axgle"的内容
对非软件开发人员而言,面向对象比较容易"理解" ...

还有一种可能,就是现在所谓专业软件开发人员实际不是真正软件专业,变成数学专业或算法专业,所以,OO对于他们来说不容易理解。

如果软件是用来解决人日常活动问题,那么软件越靠近人的日常思维,信息失真性就越小,这恐怕是个常识吧。

2011年03月17日 13:41 "banq"的内容
用来解决人日常活动问题 ...

我也这么认为,至于“导致OO永远比fp更容易被‘非软件行业的人(包括很多ceo)理解’”我觉得是更容易误解——以为OO就是分类别写代码。class和object并不是同一个单词,java上的object = new class,再看看javascript的object,明显看出动态语言上也有object。其实OO思维在各个地方都是相通的,只不过描述的方法不一样而已。而我一直只把OO当做思维而已(模块、边界思维),而不是具体的技术。

OO和FP是相容的,在思维上都是严谨逻辑的,但偏重点不同而已。OO起源于组件化、模块化思想,因为当时并没有十分强调动态(OO思维上是有动态的,只是java语言的表现力不足而已,语言和思维应该分开,所以有“别被语言误导了OO”一说),导致产生的语言缺乏动态。
[该贴被SpeedVan于2011-03-17 15:07修改过]

oo和fp和关系数据库,存在"同构"的地方.
比如自然语言: "我在写帖子."
我.写(帖子)//oo语言
fp的tuple表示,比如erlang: {我,写,帖子}
关系数据库表: 我_id 写_action_id 帖子_id
当你用自然语言表示业务逻辑的时候,oo语言可以很自然的表示业务逻辑(相对过程化语言).
关系数据库,和fp的tuple都可以很好的表示"业务关系".
本质而言,tuple是这一切的共同本质,即object is tuple.对象是元组的一种.oo是一种贴近自然语言的元祖表示.

所以,oo和关系数据库是一致的,不是矛盾的.当前以数据库为中心,好于以oo为中心.原因是:
因为数据库为中心,数据库相当于mediator,各种编程语言都通过这个mediator.如果你以某种oo的编程为中心表示业务逻辑,那么显然别的编程语言就不能(不方便)访问这种业务逻辑关系啦.

因为oo和关系数据库存在"同构",即本质为"tuple".因此,一切关于tuple的理论原则,全部可以套用在oo上面.所有的设计模式,oo设计原则,理论上全部可以用"关系理论"推演得出.

[该贴被axgle于2011-03-20 17:22修改过]
[该贴被axgle于2011-03-20 17:24修改过]