为什么OO是糟糕的?

有Erlang的创建者 Joe Armstrong发表的一篇可能比较极端的文章:Why OO Sucks

下面意译一下:
当我第一次引入到面向对象的想法,我是持怀疑态度,但不知道为什么 - 它只是觉得“错误”。当OOP开始流行时,更喜欢批评OOP,而不是在教堂里发誓那样虔诚。

Erlang是OO吗?不完全不是。下面列出反对理由:

反对1.数据结构和函数绑定在一起。
数据结构和函数行为属于不同世界。

函数Functions是做事情,他们有输入输出,输入输出是数据结构,获得由函数发生的变化,在大部分语言中函数风格是:: "做这个然后在做那个...",为了理解函数,你得理解他们执行的顺序。

数据结构不是做事情,它们是事物本质描述,理解一个数据结构比较容易理解函数。

函数是作为一个黑盒子去理解,有输入输出,如果我懂得了输入输出,我就了解了这个函数,这并不意味着我曾经写过这个函数。

函数是通过观察来理解的,他们是实现数据结构T1到T2转换的工作。

因为函数和数据结构完全不同,所以不能把他们强行锁定在一个对象边界内。

反对2:每件事情都是对象:

看看时间time这个概念,它是对象吗?在非OO中,时间只是一个数据类型,在Erlang中,时间不属于任何特定的对象。他们是无处不在的数据结构,由任何函数可以操作的数据结构而已。

这些时间没有对应的方法行为。

-deftype day() = 1..31.
-deftype month() = 1..12.
-deftype year() = int().
-deftype hour() = 1..24.
-deftype minute() = 1..60.
-deftype second() = 1..60.
-deftype abstime() = {abstime, year(), month(), day(), hour(), min(), sec()}.
-deftype hms() = {hms, hour(), min(), sec()}.
...


在另外一篇不,OO并不糟糕的反驳文章中对上述观点进行了反驳。

其实在很多语言中,类代表数据类型,数据类型哦实例是对象,a class is a data type, so an object is an instance of a data type.

所以,时间是一个数据类型,也就是一个类。
Armstrong 反对的可能是将所有行为放入一个对象中的做法,也就是所谓“富模型”充血模型等。


反对3:数据类型散落得到处都是:

在一个OOPL中,数据类型定义是属于对象的,这样,就不能在一个地方发现所有的数据类型(banq注:对象边界划分是按照业务划拨,如果不了解业务,想很快了解一个系统,经常需要打开多个对象,而不能在一个地方查看所有的数据类型,这确实不便,关键你是从业务角度理解,还是从纯粹计算机角度去理解?)。

在Erlang或C中,我们可以将所有数据类型定义在一个文件或数据字典中,但是在OOP语言中不行,数据类型散落得到处都是。

我要定义一个无处不在的数据类型,它意味着这个数据类型在系统的每个角落都存在。(banq注:传说中的全局变量概念吧?在OOP语言没有全局变量,每个都是对象,对象是有生命周期的,不可能永存的对象,当然可以和系统同样生命周期的对象,称为Application,还有Session级别或request级别。)

作为一个lisp程序员,我们已经知道这个常理:小规模数量的无处不在的数据类型和大批量围绕其工作的函数方法,好过大量数据类型和少量围绕其工作的函数方法。

一个无处不在的数据结构有点像一个linked list,或者一个数组或者一个hash table,甚至是更进一步如时间 日期或文件名。

在OOP语言中,我们必须选择一个对象来在其中定义一个无处不在的数据结构,所有要使用这个数据结构的对象必须继承这个对象(banq注:这是一种误读,不是必须继承才能使用,通过服务Service来使用只有数据结构的对象VO已经成为JavaEE中常态,现代方法有Mixin或者DCI或者事件驱动). 想想如果我要建立一个代表时间的对象,它应该属于哪个对象呢?

(banq注:继承并不是OO的核心概念,见另外一篇新的OO定义)


反对4:对象有自己的私有状态:

状态根本上是邪恶(banq注:这是一种极端观点,如果你无法处理它,就宣布你的世界里没有它,并且冠以邪恶为名驱逐,回避,而好的哲学方式是接纳容纳一切邪恶然后控制它的邪恶方面),如果没有状态,就没有副作用或边界影响。

编程语言中状态是不可取的,但是现实世界中状态到处都是,比如我非常感兴趣于我的银行账户状态,每次我划拨或存取钞票时,我都希望我的银行账户能够正确更新。

问题是:现实中状态到处存在,是否程序语言就应该提供对应的状态处理设施呢?

OOPLs认为将状态对程序员隐藏,状态的隐藏和显现是通过访问其方法实现的。

常规语言如(C, Pascal)认为状态可见性是由语言的scope规则控制的。
纯声明式语言declarative languages则认为没有状态,系统的全局状态是被切分到所有函数方法中。....

将状态对程序员隐藏是OOPLs面向对象语言们最坏的一种选择, 还不如充分暴露状态,这样才能找到干扰状态的途径。

(banq注:DDD将实体定义为一种有状态对象,其实也就是显式重点突出了状态,分析一个业务首先找出聚合根,我们将业务对象分为可变的实体和不可变的值对象,重点围追堵截可变的状态,缺省的变成适合计算机处理的不可变模式,见:不变性immutablity设计无堵塞的并发编程 2006年一篇文章状态对象:数据库的替代者)

[该贴被banq于2012-07-18 15:26修改过]

我算是明白了为啥高中的时候我看《法制报》,班主任告诉我“你们现在不要看这些东西”。

oo都还没掌握透彻,就迎来了各种批判oo的观点以及oo自身的进化。到最后我到底要怎么去敲代码呢?

摘录
我要定义一个无处不在的数据类型,它意味着这个数据类型在系统的每个角落都存在。

只是数据类型为全局可见吧, 没说变量要全局. Java中有些类只在某个包内使用.

@lostalien : 你想的太多了~ 各种语言都是有其好处的。

重新审视OO才会接受OO,要以类来批判OO,更觉得是OO被类绑架了,没有类就没有对象吗?至少我认为不是

2012-07-18 10:57 "@banq"的内容
有Erlang的创建者 Joe Armstrong发表的一篇可能比较极端的文章:Why OO Sucks。

下面意译一下:
当我第一次引入到面向对象的想法,我是持怀疑态度,但不知道为什么 - 它只是觉得“错误”。当OOP开始流行时,更喜欢 ...

我觉得还是先彻底理解面向对象再说吧,您总是用面向过程的思想想问题,自然觉得面向对象那都不对劲! 首先理解两种方式的语言 然后再跳出来,用局外人的眼光才能做出客观、正确的评价吧!同志!