`
hideto
  • 浏览: 2686965 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Why OO sucks

阅读更多
为什么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
分享到:
评论
33 楼 Trustno1 2008-08-21  
引用
不自量力的提醒一下 T1 兄,OCaml 为 OO 的 Caml,可见 fp 和 oo 是可以兼容的。

赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。


我没有说OO和FP不能兼容.
但是OO的在什么条件下能呈现他的好处?这是问题的关键所在.在我看来,以目前的趋势来看,这种条件会越来越弱.

赋值语句的确和机器环境有关系,换而言之,目前的计算机模型带给我们带来的不是更多的便利而是更加坚固的枷锁.几乎所有的并发编程的困难都由此而来,因此针对这个根子我们从理论上来说就需要从新选择计算模型,在实践上来讲就需要在目前的计算机上构建一个对应的模拟环境.

32 楼 buaawhl 2008-08-21  
Trustno1 写道
引用
无状态虽然在线程调度上是优点。在编程便利性上是缺点。


状态是不是便于编程,与是否有线程没多大关系,Event driven 上我看不出状态有利在那里.很多人恐怕从没有想到过的是,赋值语句实则上就是一种IO(为什么呢?可以仔细的想一想).但凡IO,必定是并发的.这才是OO或者说是命令语言的根子所在.


赋值语句,可能会改变状态(第二次以上赋值的时候)。不过,赋值不应该是I/O。
I/O应该是指:访问本进程内存之外的设备。赋值还是在本进程内存中发生,为什么是I/O呢?

你的意思是说。能够赋值(第二次以上),从而“有状态、有I/O、有副作用”,才是命令语言(包括OO)的本质?
31 楼 inshua 2008-08-21  
Trustno1 写道
引用
无状态虽然在线程调度上是优点。在编程便利性上是缺点。


状态是不是便于编程,与是否有线程没多大关系,Event driven 上我看不出状态有利在那里.很多人恐怕从没有想到过的是,赋值语句实则上就是一种IO(为什么呢?可以仔细的想一想).但凡IO,必定是并发的.这才是OO或者说是命令语言的根子所在.


不自量力的提醒一下 T1 兄,OCaml 为 OO 的 Caml,可见 fp 和 oo 是可以兼容的。

赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。
30 楼 Trustno1 2008-08-21  
引用
无状态虽然在线程调度上是优点。在编程便利性上是缺点。


状态是不是便于编程,与是否有线程没多大关系,Event driven 上我看不出状态有利在那里.很多人恐怕从没有想到过的是,赋值语句实则上就是一种IO(为什么呢?可以仔细的想一想).但凡IO,必定是并发的.这才是OO或者说是命令语言的根子所在.
29 楼 terranhao 2008-08-21  
Trustno1 写道
引用
都不容易理解。
OO在可读性方面优势并不大。

select name from person

这个才比较容易理解。

容不容易理解,这都是人的主观因素.你从小学汉语长大,英语说得再溜也不会比老美觉得自然亲切.
所以讨论语言设计问题,扯到容不容易理解,是不是方便上就毫无意义.
要深挖狠批OO,就需要从根子上找问题,要找到那种无论你是不是觉得语法容易理解,都必须接受的理由.

我要求不太高,请你用机器语言给我写个tomcat.
你要实在觉得机器语言不好理解,用汇编也可以.
我可以肯定得告诉你,即使你从小就用机器语言写程序.你也不会觉得机器语言比你只用了一年的C玩得溜
28 楼 terranhao 2008-08-21  
其实我只是想问一下
joe armstrong是不是在炒作他的erlang,我其实真的最关心这个问题
27 楼 inshua 2008-08-21  
Trustno1 写道
引用
都不容易理解。
OO在可读性方面优势并不大。

select name from person

这个才比较容易理解。

容不容易理解,这都是人的主观因素.你从小学汉语长大,英语说得再溜也不会比老美觉得自然亲切.
所以讨论语言设计问题,扯到容不容易理解,是不是方便上就毫无意义.
要深挖狠批OO,就需要从根子上找问题,要找到那种无论你是不是觉得语法容易理解,都必须接受的理由.


热烈欢迎 T1 兄对 oo “深挖狠批”
26 楼 terranhao 2008-08-21  
buaawhl 写道
Trustno1 写道
引用
都不容易理解。
OO在可读性方面优势并不大。

select name from person

这个才比较容易理解。

容不容易理解,这都是人的主观因素.你从小学汉语长大,英语说得再溜也不会比老美觉得自然亲切.
所以讨论语言设计问题,扯到容不容易理解,是不是方便上就毫无意义.
要深挖狠批OO,就需要从根子上找问题,要找到那种无论你是不是觉得语法容易理解,都必须接受的理由.


根子就是VTable。
我写了一个Interface,然后几个Class实现这个interface。
程序运行的时候,会动态调用对应的实现方法。

这个“多态”能力,FP行吗?C行吗?都不行。这是OO唯一特殊的地方。

当然,这个不是FP的主要弱点。FP的主要弱点还是在于无状态。无状态虽然在线程调度上是优点。在编程便利性上是缺点。

这个承认,相对于语法来说,继承,多态确实是OO和FP的本质区别.
25 楼 Trustno1 2008-08-21  
引用
根子就是VTable。
我写了一个Interface,然后几个Class实现这个interface。
程序运行的时候,会动态调用对应的实现方法。

这个“多态”能力,FP行吗?C行吗?都不行。这是OO唯一特殊的地方。

当然,这个不是FP的主要弱点。FP的主要弱点还是在于无状态。无状态虽然在线程调度上是优点。在编程便利性上是缺点。

一个自行车爱好者,看见一汽车说,你Y连踏脚都没有能跑?
24 楼 inshua 2008-08-21  
buaawhl 写道

OO 的本质能有啥?就是一个VTable而已。(或者一个Hashtable而已。like in javascirpt)
当然,如果把OO上升到一种思想和宗教,OO就不只是一个VTable,而是一种宇宙能量。

前面举的例子,是说状态的优势。OO或者C等语言,都是FP的对立面,都是有状态的。而FP通常是无状态的(当然,有些FP是有状态的)。无状态有线程安全的好处,但是编程上就多了很多限制,非常不方便。



我倒,你一会儿有状态一会儿无状态,到底想表达啥。不如别弄什么这些玄虚,实际上 oo 就是 fp,fp 也是 oo,这就好比 schema 是 lisp 的一个方言,一幅多么和谐的画面啊。

你要无状态,可以啊,无状态对象嘛,我们以前用 dcom 的时候就有了。你要有状态,更简单,oo 本来就有状态。

亲爱的 fp-er ,你们似乎找错敌人了,真正的敌人应该是 c 以及 c 的同党,不是 oo。

前面已经指出,oo 作为 oop 的语言来说,和 fp 相当。

作为 ooa 的设计来说,它只是一种程序设计模型,erlang 也好,lisp 也好,实际上都可以按 oo 的方式来用。

兄弟们,去找 c 语言决斗吧,加油。
23 楼 buaawhl 2008-08-21  
Trustno1 写道
引用
都不容易理解。
OO在可读性方面优势并不大。

select name from person

这个才比较容易理解。

容不容易理解,这都是人的主观因素.你从小学汉语长大,英语说得再溜也不会比老美觉得自然亲切.
所以讨论语言设计问题,扯到容不容易理解,是不是方便上就毫无意义.
要深挖狠批OO,就需要从根子上找问题,要找到那种无论你是不是觉得语法容易理解,都必须接受的理由.


根子就是VTable。
我写了一个Interface,然后几个Class实现这个interface。
程序运行的时候,会动态调用对应的实现方法。

这个“多态”能力,FP行吗?C行吗?都不行。这是OO唯一特殊的地方。

当然,这个不是FP的主要弱点。FP的主要弱点还是在于无状态。无状态虽然在线程调度上是优点。在编程便利性上是缺点。



22 楼 buaawhl 2008-08-21  

OO 的本质能有啥?就是一个VTable而已。(或者一个Hashtable而已。like in javascirpt)
当然,如果把OO上升到一种思想和宗教,OO就不只是一个VTable,而是一种宇宙能量。

前面举的例子,是说状态的优势。OO或者C等语言,都是FP的对立面,都是有状态的。而FP通常是无状态的(当然,有些FP是有状态的)。无状态有线程安全的好处,但是编程上就多了很多限制,非常不方便。

21 楼 Trustno1 2008-08-21  
引用
都不容易理解。
OO在可读性方面优势并不大。

select name from person

这个才比较容易理解。

容不容易理解,这都是人的主观因素.你从小学汉语长大,英语说得再溜也不会比老美觉得自然亲切.
所以讨论语言设计问题,扯到容不容易理解,是不是方便上就毫无意义.
要深挖狠批OO,就需要从根子上找问题,要找到那种无论你是不是觉得语法容易理解,都必须接受的理由.
20 楼 hideto 2008-08-21  
贴近自然语言不一定就好啊
如果一行DSL就能搞定你用OO写的500行代码,你说哪个好?
Quake Wang 写道
引用
为什么OO粉流行?

我认为一个重要原因是更贴近自然语言。
把数据类型和方法绑定在一起,你可以写出这样几乎和自然语言一致的代码:
3.days.ago
user.destroy unless user.is_admin

19 楼 inshua 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 的本质问题。
18 楼 buaawhl 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 = ...]






17 楼 ye_jian_hui 2008-08-21  
OO不是一文不值,只是OO过于泛滥了,很多地方不该OO的都要OO,搞得好像没有OO就不行了似的,我想Joe老大是看不惯这点才这么说的。
16 楼 terranhao 2008-08-21  
Trustno1 写道
terranhao 写道
既然大行其道,那自然是not sucks,that's why "why oo sucks" sucks

套用坛子里某位仁兄的话说,实然不能证明应然.比如说大便是客观,普遍存在的,但是"大便客观,普遍的存在"与"大便的味道很香"之间没有任何逻辑关系.

在如此多的技术竞争下OO大行其道.和你举的狗屁不通的例子是完全没有可比性的.
如果人类能进化出不拉大便的能力,我不相信有人选择继续蹲坑.
这也能叫做类比,那我也算服了那位仁兄了,然而你这位仁兄居然能把那位仁兄的话引用得乐此不疲,深以为然,确实是令我敬佩.
从机器语言到汇编再到C再到c++/java/c#
程序语言的演变过程就是向着人类认知世界的方式演变。如果你不认同这点,我们没有必要多讨论,如果你认同这点,那我请问你。person.writeName()是不是比write(char* personName)容易被人理解?
15 楼 inshua 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 从语义上可以理解为将上面那段匿名类的定义模板化和,,有名化。
14 楼 Trustno1 2008-08-21  
引用
没道理。数据类型、属性和方法绑定在一起。是为了方便。怎么方便怎么来。这是OO最伟大的亮点。FP拍马都赶不上。
在FP里面,只能用蹩脚的closure闭包来模拟对象的效果。

所谓的方便,肯定要有具体的场景.对于摩托车自行车来说,链条肯定比齿轮杠杆方便,但是要是轿车,你拿链条试试看.

相关推荐

    大师品软件_Why Software Sucks

    《大师品软件_Why Software Sucks》是一本深入探讨软件设计缺陷和用户体验问题的书籍,由David S. Platt撰写。这本书旨在揭示为什么某些软件在使用过程中让人感到困扰,并提出改善软件设计的策略。作者Platt是一位...

    Why.Software.Sucks

    Any book is the product of a team effort. In this one, I've had an out- standing supporting cast. Everyone at Addison-Wesley understood and got behind the concept of a book for the users of ...

    itsucks-0.4.1开源爬虫

    【itsucks-0.4.1开源爬虫】是一个针对初学者友好的网络爬虫工具,它的出现使得没有编程背景的用户也能轻松进行数据抓取。这个最新版本的itsucks,不仅提供了完整的爬虫功能,还引入了一个简洁的图形化用户界面(GUI...

    itsucks-0.4.1.zip

    【itsucks-0.4.1.zip】是一个包含开源Java Web Spider项目的压缩包,这个项目被称为itSucks。itSucks的设计目标是帮助用户轻松构建网络爬虫,它使用了Web机器人技术,允许用户通过定义下载规则来抓取网页内容。项目...

    itsucks开源代码

    爬虫源码,开源 java 很好 强大 可扩展

    信息安全_数据安全_Why_the_role_of_CISO_sucks_and_w.pdf

    信息安全_数据安全_Why_the_role_of_CISO_sucks_and_w 信息安全研究 金融安全 安全人才 安全对抗 法律法规

    why-your-test-suite-sucks

    标题“why-your-test-suite-sucks”暗示了我们讨论的主题是关于测试套件存在的问题以及如何改进它们。测试套件是软件开发过程中的重要组成部分,它确保代码的质量、稳定性和可靠性。然而,当测试套件出现问题时,...

    Atc Sucks-crx插件

    【Atc Sucks-crx插件】是一款针对英文用户的浏览器扩展程序,主要目的是表达用户对“ATC”(可能是某个网站、服务或功能的缩写)的不满情绪。这款插件由开发者创建,用于向用户展示ATC存在的问题,或者提供某种方式...

    Smooth Scroll Sucks-crx插件

    因此,【Smooth Scroll Sucks-crx插件】致力于让浏览器的滚动条重获自由,释放用户在浏览时可能遇到的困扰。它通过禁用页面上的平滑滚动特效,使鼠标滚轮和触摸板的操作更加直接,使浏览体验更接近传统习惯。 现代...

    Vegandale Sucks-crx插件

    【Vegandale Sucks-crx插件】是一款专为英文用户设计的浏览器扩展程序,主要功能是替换网络上关于“Vegandale”的相关信息,将其转化为“Gentrified Parkdale”。这款插件针对的是那些可能对“Vegandale”这一名称...

    itsucks:http

    ItSucks 网络爬虫 描述 这个项目是一个具有下载(和恢复)文件能力的java网络蜘蛛(网络爬虫)。 它还可以使用正则表达式和下载模板进行高度定制。 所有后端功能也可在单独的库中使用。 官网 执照 本地开发使用 将 ...

    IE Sucks-crx插件

    IE SUCKS这么糟糕,实际上是有趣的观看失败! IE样式信息条在页面中的障碍码时发光。 无广告! Internet Explorer是一个浏览器的F ****笑话,并字面上持有进步! 在逐步淘汰之前庆祝最终几天,用IE吸收插件。 每当...

    rabbit sucks!-crx插件

    【标题】:“rabbit sucks!-crx插件”是一个针对特定网站或应用的浏览器扩展,其主要功能是优化用户界面,提供更加个性化的浏览体验。这个插件的名称可能具有一定的幽默感,暗示它可以帮助用户摆脱某些他们不喜欢的...

    DuPont Sucks FTP-开源

    DuPont Sucks FTP(DPS-FTP)是一个开源的FTP客户端工具,专为用户提供便捷的文件传输服务。这个项目的名称“DuPont Sucks FTP”可能源于一种幽默或反讽的表达,暗示它并非由杜邦公司开发,而是由社区驱动的独立项目...

    kevingreen.sucks

    【标题】"kevingreen.sucks" 是一个网站项目,基于 "Simple Next App" 构建,主要用于表达对个人或事物的不满或者批评。在互联网上,".sucks" 域名通常被用来创建一个平台,让人们可以公开讨论他们认为有问题的事物...

    IE吸盘「IE Sucks」-crx插件

    使用IE Sucks插件庆祝淘汰前的最后几天。 每当遇到旨在帮助Internet Explorer像老人一样上楼的代码时,我们都会像过去一样发出经典的IE信息栏。 您知道,这意味着您只有更多无用的废话可以破坏您的浏览器,除非这次...

    sucks:用python制作的小CRUD

    标题中的“sucks:用python制作的小CRUD”表明这是一个使用Python编程语言开发的简单创建、读取、更新和删除(Create, Read, Update, Delete,简称CRUD)应用程序。CRUD是数据库操作的基础,是任何数据管理系统的基石...

    your-band-sucks-v2:通过不良专辑封面分享音乐

    【标题解析】:“your-band-sucks-v2”很可能是一个音乐相关的项目或应用,可能是由开发者创建的一个幽默或者讽刺性的音乐分享平台。"v2"表示这是项目的第二个版本,通常意味着在原有基础上进行了改进和优化。 ...

    Moments Sucks-crx插件

    如果您确实讨厌Twitter内的Moments标签,并且在尝试查看通知时始终单击此处,则只需安装此… 如果您确实讨厌Twitter内的Moments选项卡,并且在尝试查看通知时始终单击此处,则只需安装此轻量级扩展程序即可将其发送...

Global site tag (gtag.js) - Google Analytics