已锁定 主题:Why OO sucks
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-08-20
原文: http://www.sics.se/~joe/bluetail/vol1/v1_oo.html 作者:Joe Armstrong 当我第一次知道OOP的概念时,我非常疑惑,但是不知道为啥——它仅仅在感觉上“不对”。 在OOP问世之后变得粉流行(稍后解释为什么),而批评OOP就像“在教堂里咒骂”。 OO成为了每个受尊敬的语言必须具备的一部分。 而当Erlang变得越来越流行时,我们经常问一个问题“Erlang是OO的吗?” 当然正确的答案是“当然不是”——但是我们没有大肆宣扬——我们只是换了种精心设计的说法,Erlang是某种OO但不是真的是。 这时我想起在法国巴黎时IBM的老板在7th IEEE逻辑编程大会上的演讲。 IBM prolog添加了许多OO扩展,当人们问起时他说:“我们的客户想要OO的prolog,所以我们构建了OO的prolog” 我想到了“多么简单,没有良心的疑虑,没有灵魂的搜索,没有‘这是正确的事情’的问题。。。” 为什么OO很恶心 我对OOP的反对原则源自一些基本的概念,我将概述其中一些反对意见。 反对之一——数据类型和方法应该绑定在一起 对象将方法和数据结构绑定在一起成为不可分割的单元。我认为这是基本的错误,因为方法和数据结构属于完全不同的世界。为啥哩? 1,方法做事情。它们是输入和输出。输入和输出的是方法所改变的数据结构。 在大部分编程语言里,方法由命令式语句顺序构建:“做这件事然后那件事。。。” 理解方法首先得理解做事情的顺序(在懒惰函数编程语言和逻辑语言中这个限制被放宽了) 2,数据结构是结构。它们不做任何事情。它们本质上是声明。“理解”数据结构比“理解”方法简单多了。 方法作为黑盒子来转换输入和输出。如果我理解输入和输出,这样我就理解了方法。这并不意味着我可以写这个方法。 方法通常理解为在一个计算系统里用来将数据结构T1转换为数据结构T2的东西。 既然方法和数据结构是完全不同类型的动物,那么将它们锁在一个笼子里就是完全错误的。 2,反对之二——任何东西都必须为对象 考虑“时间”。在OO语言里“时间”也必须是对象。但是在非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()}. ... 注意这些定义不属于任何特殊的对象。它们很普遍,并且数据结构表示的时间可以被系统中的任何方法处理。 没有相关联的方法。 反对之三——在一个OOP语言里数据类型定义散布到任意位置 在OOP语言里数据类型定义属于对象。 这样我就不能在一个地方找到所有的数据类型定义。 在Erlang或者C里我可以在一个单独的include文件或数据字典里定义我所有的数据类型。 在一个OOP语言里我不能——数据类型定义散布到任意位置。 让我举一个例子。假设我想定义一个通用的数据结构。通用数据类型是一个数据类型,它在系统中的任意位置出现。 lisp程序员知道,拥有一个较小数量的通用数据类型和在它上面的大量的小方法会更好。 通用数据类型就比如linked list,或者一个array或者一个hash table或者更高级的对象如time或者date或者filename。 在一个OOP语言里我不得不选择一些base对象来在里面定义通用的数据结构,所有其他想使用这些数据结构的对象必须继承该对象。 假设现在我想创建一些“time”对象,那么它应该属于哪个对象呢。。。 反对之四——对象拥有私有状态 状态是所有罪恶的根源。特别是有副作用的方法应该避免。 在编程语言里状态是令人讨厌的,而真实世界里状态却千奇百怪的存在着。 我对我的银行账户的状态很感兴趣,当我从我的账户存钱或取钱时我希望我的银行账户状态成功更新。 既然状态在真实世界里存在,那么编程语言应该提供什么能力来处理状态呢? 1,OOP语言说“将状态隐藏”。状态仅仅通过访问方法来隐藏和可见。 2,传统编程语言(C,Pascal)说状态的可见度由语言的scope规则来决定。 3,纯声明式语言说没有状态。系统的全局状态转移到方法里然后从方法里出来。 类似于monad(函数式编程语言)和DCG(逻辑语言)等机制被用来隐藏状态,这样它们可以像“有没有状态无所谓”一样来编程,但是对系统状态的完全访问是必需的。 OOP语言所选择的“隐藏状态”可能是最坏的选择。 它们不是将状态显示出来并寻找减少状态的坏处的方式,而是将状态隐藏起来。 为什么OO粉流行? 1,原因1——它被认为很容易学 2,原因2——它被认为让代码更易重用 3,原因3——它被大肆宣传 4,原因4——它创建了一个新的软件工业 我看不到原因1和原因2的证据。原因看起来像是技术背后的驱动力。 如果一个编程语言技术如此之差,然后它创建了一个新的工业来解决它自己本身的问题,则它会成为想从中牟利的人的好工具。 这就是OOP背后真正的驱动力。 以及一篇回复:Why "Why OO Sucks" Sucks 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-08-21
那篇回复感觉言之无物 反驳得无力
|
|
返回顶楼 | |
发表时间:2008-08-21
J教.主的这篇文章可比埃蒙斯04年的射击,精准,有力,呼啸而过,但是脱靶了
|
|
返回顶楼 | |
发表时间:2008-08-21
引用 为什么OO粉流行? 我认为一个重要原因是更贴近自然语言。 把数据类型和方法绑定在一起,你可以写出这样几乎和自然语言一致的代码: 3.days.ago user.destroy unless user.is_admin |
|
返回顶楼 | |
发表时间:2008-08-21
期待老庄...
|
|
返回顶楼 | |
发表时间:2008-08-21
既然大行其道,那自然是not sucks,that's why "why oo sucks" sucks
|
|
返回顶楼 | |
发表时间:2008-08-21
Quake Wang 写道 引用 为什么OO粉流行?
我认为一个重要原因是更贴近自然语言。 把数据类型和方法绑定在一起,你可以写出这样几乎和自然语言一致的代码: 3.days.ago user.destroy unless user.is_admin 是不是自然,不过是有没有中缀操作符的问题 .操作看起来自然,是因为它是一个中缀操作符. OO粉流行完全是因为屁股决定了脑袋,而不是相反. 所以,我说J教.主的文章给狠抽脑袋,却给屁股挠痒. |
|
返回顶楼 | |
发表时间:2008-08-21
terranhao 写道 既然大行其道,那自然是not sucks,that's why "why oo sucks" sucks
套用坛子里某位仁兄的话说,实然不能证明应然.比如说大便是客观,普遍存在的,但是"大便客观,普遍的存在"与"大便的味道很香"之间没有任何逻辑关系. |
|
返回顶楼 | |
发表时间:2008-08-21
基本上(因为对阿隆左的函数演算系统不了解!),不能同意这篇文章的观点。
函数式编程的演算系统和我们现在的图灵机的演算系统是不同的。 尽管他们具有相同的演算能力。 对象是人类自身认知和描述现实世界的方式(想想你自己是如何向其他人描述今天的所见所闻!)。 面向对象程序语言只是提供了方便的描述语法罢了。 所以使用面向对象感觉会更加自然些。 |
|
返回顶楼 | |
发表时间:2008-08-21
近来读了一下 SICP,我感觉 oo 和 fp 本质上是同一的,一个对象实际上就是一个闭包。怎么说呢,
class A{ String name == 'John'; void speek(){ System.out.println(name); } } 和 function a(method){ var name = 'John'; // 相当于 lisp 的 (let name 'John'),以下均有相当的代码 if(method == 'speek'){ return function(){ alert(name); } } } // call a('speek')(); 两者在语义上是等价的。 而 fp 的闭包概念,在 java 里对应的是匿名类,既然 oo 能做出闭包的效果,fp 的那些东西其实也不在话下。只是 java 是静态语言,需要 scheme 声明,如 interface,但 oo 也不必然静态,不能说是 oo 的固有缺陷。 我认为 oo 是在以一种半普遍的方式定义闭包,将 fp 的范围框定在一组函数(0..*)和一组数据(0..*)结合的场景,这个设定对于处理现实问题具有相对普遍的意义。从这个角度来看,鄙视 oo 实际上没有什么意义,大家都是相通的东西。 班门弄斧一下,这里写了一篇在回调上,oo 和 fp 的对比。 http://blog.csdn.net/inshua/archive/2008/08/04/2767958.aspx |
|
返回顶楼 | |