已锁定 主题:Why OO sucks
该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-08-21
zengsun 写道 基本上(因为对阿隆左的函数演算系统不了解!),不能同意这篇文章的观点。
函数式编程的演算系统和我们现在的图灵机的演算系统是不同的。 尽管他们具有相同的演算能力。 既然是相等价的,当然就是相同的. OO是不是Sucks,与这两个问题没有太大的关系,或者换一种方式说oo大部分设施不是构建在这两个系统上面的. 引用 对象是人类自身认知和描述现实世界的方式(想想你自己是如何向其他人描述今天的所见所闻!)。
肉眼去观察的天空,与望远镜观察的天空有区别吗? |
|
返回顶楼 | |
发表时间:2008-08-21
hideto 写道 反对之一——数据类型和方法应该绑定在一起 貌似是should not be ... |
|
返回顶楼 | |
发表时间:2008-08-21
windedge 写道 hideto 写道 反对之一——数据类型和方法应该绑定在一起 貌似是should not be ... 不想绑就别绑,数据和方法都是 0 - * 的,你可以做无状态对象,也可以做纯数据 bean,犯不着跟它较劲。 |
|
返回顶楼 | |
发表时间:2008-08-21
hideto 写道 为什么OO很恶心
原文: 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 感觉上,第一枪,第三枪打偏了,第二枪,第四枪都很有道理。 2,反对之二——任何东西都必须为对象 很有道理。所有对象都从Object继承,结果几乎没有共享任何公用的interface.只有getClass等可有可无的公用成员方法。完全可以用更通用的 typeof 来代替。任何(或者大部分)东西都为对象,是没有必要的。 反对之四——对象拥有私有状态 这玩意儿好像叫做封装。是比较恶心。还美其名曰“隔离”。隔离谁啊?隔离调用该对象的其他程序员?有毛病啊。这种暗箱操作是逆潮流而动的。数据要公开,要透明。 ---------------------- 反对之一——数据类型和方法应该绑定在一起 没道理。数据类型、属性和方法绑定在一起。是为了方便。怎么方便怎么来。这是OO最伟大的亮点。FP拍马都赶不上。 在FP里面,只能用蹩脚的closure闭包来模拟对象的效果。 反对之三——在一个OOP语言里数据类型定义散布到任意位置 没道理。Include Header也是很蹩脚的。OO能够在任何地方自由定义类型,太方便了。 老罗 写道 拉斯维加斯……大家都开着车排队去离婚,以至于你慢一点儿后面的人都不愿意:"快点快点!还TMD让不让人离婚了?!"老俞去了之后两眼直放光嘴角流着哈拉子说:“太方便了!太方便了!”。 |
|
返回顶楼 | |
发表时间:2008-08-21
引用 没道理。数据类型、属性和方法绑定在一起。是为了方便。怎么方便怎么来。这是OO最伟大的亮点。FP拍马都赶不上。
在FP里面,只能用蹩脚的closure闭包来模拟对象的效果。 所谓的方便,肯定要有具体的场景.对于摩托车自行车来说,链条肯定比齿轮杠杆方便,但是要是轿车,你拿链条试试看. |
|
返回顶楼 | |
发表时间:2008-08-21
这个例子可能揭示的更明白些:
class Test{ public static void Main(String args[]){ Object o = new Object(){ String name = "John"; public void speek (){ System.out.println(name); } } o.speek(); // 我用的是 dynamic-Java,简称 DJ,嘿嘿 } } 和 var o = function (method){ var name = 'John'; // 相当于 lisp 的 (let name 'John'),以下均有相当的代码 if(method == 'speek'){ return function(){ alert(name); } } } o('speek')(); 相当。 而 class 从语义上可以理解为将上面那段匿名类的定义模板化和,,有名化。 |
|
返回顶楼 | |
发表时间:2008-08-21
Trustno1 写道 terranhao 写道 既然大行其道,那自然是not sucks,that's why "why oo sucks" sucks
套用坛子里某位仁兄的话说,实然不能证明应然.比如说大便是客观,普遍存在的,但是"大便客观,普遍的存在"与"大便的味道很香"之间没有任何逻辑关系. 在如此多的技术竞争下OO大行其道.和你举的狗屁不通的例子是完全没有可比性的. 如果人类能进化出不拉大便的能力,我不相信有人选择继续蹲坑. 这也能叫做类比,那我也算服了那位仁兄了,然而你这位仁兄居然能把那位仁兄的话引用得乐此不疲,深以为然,确实是令我敬佩. 从机器语言到汇编再到C再到c++/java/c# 程序语言的演变过程就是向着人类认知世界的方式演变。如果你不认同这点,我们没有必要多讨论,如果你认同这点,那我请问你。person.writeName()是不是比write(char* personName)容易被人理解? |
|
返回顶楼 | |
发表时间:2008-08-21
OO不是一文不值,只是OO过于泛滥了,很多地方不该OO的都要OO,搞得好像没有OO就不行了似的,我想Joe老大是看不惯这点才这么说的。
|
|
返回顶楼 | |
发表时间:2008-08-21
terranhao 写道 person.writeName()是不是比write(char* personName)容易被人理解?
都不容易理解。 OO在可读性方面优势并不大。 select name from person 这个才比较容易理解。 -------------------------- OO的优势在于能够把乱七八糟的东西(数据、方法之类的)凑成一堆。 而且可以多个对象之间可以组合起来,成为更加复杂的对象。 更妙的是,组装的过程可以一步步分开来顺序写。 想什么时候写,就什么时候写。 想怎么写,就怎么写。 太方便了。这就是有状态的好处。状态这东西虽然线程安全性很差,但是还真是少不了。尤其是我这种脑筋迟钝一下子想不了太多事情的人。 a.name = ... b.email = .... a.address = ... ErLang等FP里面就不行,需要一次把问题考虑清楚,一行写完。 a = [name = ..., address = ...] |
|
返回顶楼 | |
发表时间:2008-08-21
buaawhl 写道 terranhao 写道 person.writeName()是不是比write(char* personName)容易被人理解?
都不容易理解。 OO在可读性方面优势并不大。 select name from person 这个才比较容易理解。 -------------------------- OO的优势在于能够把乱七八糟的东西(数据、方法之类的)凑成一堆。 而且可以多个对象之间可以组合起来,成为更加复杂的对象。 更妙的是,组装的过程可以一步步分开来顺序写。 想什么时候写,就什么时候写。 想怎么写,就怎么写。 太方便了。这就是有状态的好处。状态这东西虽然线程安全性很差,但是还真是少不了。尤其是我这种脑筋迟钝一下子想不了太多事情的人。 a.name = ... b.email = .... a.address = ... ErLang等FP里面就不行,需要一次把问题考虑清楚,一行写完。 a = [name = ..., address = ...] 这只是表达方式而已,和 oo 有啥关系,没有任何关系。例如你说的 a.setName(); a.setEmail(),在 java 里,只要你设计成 continuouse 形式,就可以 a.setName().setEmail().setAddress 了,且 ide 都有提示。又比如在 c# 里有对象构造语法,var t = new Person(){Name = 'John', ...}。 这个不是 oo 的本质问题。 |
|
返回顶楼 | |