`

面向对象之弊,面向过程之优

阅读更多
加个通道:G A E - R P R O X Y, http://www.iteye.com/topic/717232

没想到写了这么多。本文并不是要否定OO,而是要给PO更多的肯定。这篇文字不像想象中那么长,只是些一看便知的代码占了些篇幅,请大家花3分钟看完,这将会是个很有意义的讨论。为了方便大家阅读,我把提纲先列在上面。
1。 我们需要全局变量和函数。
2。 我们需要Callback函数。
3。面向对象的代码在重构和重用上没有面向过程的灵活
引申:数据与逻辑的绑定还是分离?
引申:面向对象曾经辉煌但已褪色的光辉
引申:面向对象最有魅力的地方在哪?
尾声:什么时候用OO,什么时候用PO?

回复ray_linn的C#代码:
http://www.iteye.com/topic/712942?page=2#1580812
---------------------
面向对象在过去的十多年里一直被广泛的宣传,现在已经成为世所公认的比面向过程更优秀的编程模式,但是——过犹不及。

[del]Java将被作为面向对象编程语言的典型来做说明,Python将被作为面向过程的语言来说明,虽然Python也面向对象。[/del]
有人说我是在说Java语言的问题,而不是说OO的问题,所以我把OO的代码也改成了python实现。


1。 我们需要全局变量和函数。

java作为一个典型的面向对象的编程语言,为什么要设static关键字。这从侧面说明,面向对象不是万能的。我们需要全局性的变量、全局性的函数(方法)。

单例的设计模式,是试图用面向对象的方法来做全局性的函数。因为对象只会被创建一次,那该对象的方法事实上就是一个全局函数。即便单例可以用面向对象的方法来解决了全局函数的问题,但要获取单例的实例,我们依然无法避免使用static变量来hold这个实例,无法避免使用static函数来获取这个实例。

2。 我们需要Callback函数。

面向过程的语言会有类似这样的代码:

def some_function(param...)
   //my codes...

addListener('some_event',some_function)

而试图完全对象化的Java语言有一个很尴尬的做法
class MyCallbackImpl:
   def myCallbackMethod(MyParam param,...):
     //My codes...

someObj.addListener('some_event',MyCallbackImpl());

我们可以看出,为了这个回调,我们定义了接口,定义了实现类,并且构造了 MyCallbackImpl的对象,并且降低了代码的可读性。我见过许多对回调很晕的同学,我想不是他们的理解能力问题,而是面向对象的这种做法本身的问题。

3。面向对象的代码在重构和重用上没有面向过程的灵活

比如这样的一段代码:
class MyClassA:
  def methodA(self,ParamA){
    //根据ParamA,this.someField得出返回值

class MyClassB:
  def methodB(self,ParamB):
     //根据ParamA,this.someField得出返回值
...
objA = MyClassA();
objA.methodA(paramA)
objB = MyClassB();
objB.methodB(paramB)


methodA只与paramAmethodA被限定在MyClassA的对象中调用,methodB被限定在MyClassB的对象中调用,这两个方法由于业务范畴的原因被归入相应的Class。让我们来看看这样的代码用面向过程的方式会如何写:
def methodA(paramA,paramField):
   //根据ParamA,paramField得出返回值
def methodB(paramB,paramField):
   //根据ParamB,paramField得出返回值

class MyClassA:
  #..
class MyClassB:
  #..
...
objA = MyClassA()
objB = MyClassB()
methodA(paramA,objA.someField)
methodB(paramB,objB.someField)

这里的面向过程的代码中出现了MyClassA和MyClassB,但这两个类完全是空的,你可以只理解为是一个数据结构而已。

现在需求发生了改变,MyClassA需要实现类似methodB的功能,MyClassB要实现类似methodA的功能。
我们先看看,面向过程的代码要做什么修改:
def methodA(paramA,paramField):
   //根据ParamA,paramField得出返回值
def methodB(paramB,paramField):
   //根据ParamB,paramField得出返回值

class MyClassA:
  #..
class MyClassB:
  #..
...
objA = MyClassA()
objB = MyClassB()
methodA(paramA,objA.someField)
methodB(paramB,objB.someField)
#增加下面的两句
methodB(paramA,objA.someField)
methodA(paramB,objB.someField)

可是面向对象的代码呢?等待他的将是代码的重构,也许他可以选择的重构方式是static函数————本质上是一种面向过程的方式。

==================================================================

引申:数据与逻辑的绑定还是分离?
面向对象编程在代码逻辑上是意味着什么?个人认为面向对象在代码逻辑上意味着数据与逻辑的绑定。可以想象成 C的Structure和C的function结合成了Cpp的Class。
面向过程在代码逻辑上意味着什么?个人认为面向过程在代码逻辑上意味着数据与逻辑的分离。
我们经常说MVC,数据、逻辑、视图分离。那么我们在最基本的代码上就不需要这种分离了吗?
程序=数据结构+算法 ,对象也可以理解为数据结构和算法的绑定, 对象更加的接近一个程序的完整结构,而过程则更像一个代码段。
从这个角度看,很难说这是优点或缺点。

引申:面向对象曾经辉煌但已褪色的光辉

面向对象出现之初,还是c语言时代,充满了无层次结构的函数,面向对象给函数带来了归属地,让函数可以被更好的整理。而如今,面向过程的语言,也可以通过包的概念来整理函数的归属。

此外,OO带来访问控制的一些概念,private,protected,public,这些访问控制的确令人眼前一亮,但很难说他还有吸引力。对于访问控制,在编译原理上面向过程的语言同样可以实现,但更重要的还是一个好的编码习惯,比如python的 __ 前缀函数,开发者会自然的规避调用它。

引申:面向对象最有魅力的地方在哪?

个人认为,面向对象最大的吸引力在于他的表现力。看这样一段代码:
class Fish{
  def swim(){
   //the fish swimming

fish=Fish()
fish.swim()

来看面向过程的实现
def swim(fish):
  //the fish swimming

fish = Fish()
swim(fish)

面向对象的代码,我们很直观的看到 fish.swim() 是鱼游泳。而面向过程的代码则是 swim(fish),游泳这条鱼,函数定义也许改做 make_fish_swim(fish) 更合适。

尾声:什么时候用OO,什么时候用PO?

浮在海上的冰山,大部分的内容在海面以下。海面以上的用OO来表现会更美,海面以下的用PO来表现会更合适。

Use OO as data-structure more than design patterns, more static utility functions.
分享到:
评论
44 楼 slaser 2010-07-16  
恩,等待LZ用PO实现工作流系统。
43 楼 jasongreen 2010-07-16  
靠,要被新手了~~~,在javaeye想说两句话还真难
42 楼 clojurer 2010-07-16  
推荐楼主看看clojure吧!
41 楼 xuby 2010-07-16  
piao_bo_yi 写道
xuby 写道
piao_bo_yi 写道
xuby 写道
楼上这些同学(包括楼主自己)都在讨论OO或PO具体语法的对比。但楼主所提问题。从范畴上讲,显然远超具体语法这个层面。

所以这事儿不能细说,只能从实际应用效果来判断。到目前为止,OO 最成功的应用就是在 UI 上应用,其他领域似乎没有明显表现出相对 PO 的优势。

不少牛人,比如Linux之父,都是强烈反 OO 的
现在Google最新推出的 Go 语言,OO特性已经不明显(只有不支持继承的类,实际上跟c语言的struct差不多)。Go语言的作者也都是计算机领域的资深牛人,Go语言的语法显然是经过深思熟虑的。

老大,你这句完全是误传,他批评的是C++的语言模型...不是反对OO。

并非误传,你自己可以google相关中英文信息。

原帖找不到了,有个译文:http://blog.csdn.net/turingbook/archive/2007/09/07/1775488.aspx

请看下面这个原帖,Linus Torvalds是如何痛批 OO 的:
http://www.realworldtech.com/forums/index.cfm?action=detail&id=110699&threadid=110549&roomid=2
不想看原文的,我摘抄了一些中文介绍:
引用
此外,Linus还在另一个帖子里痛批了面向对象语言。他认为面向对象语言以对象为核心,加一些相关联的方法,简直是呓语。重要的东西应该是数据结构,对象本身有啥重要?真正有意思的,是在不同类型的不同对象交互而且有锁规则的时候。但是,即使是这时候,封装什么“对象接口”也绝对错误,因为不再是单一对象的问题了。他的结论是,面向对象解决的都是一些小问题。

40 楼 piao_bo_yi 2010-07-16  
xuby 写道
piao_bo_yi 写道
xuby 写道
楼上这些同学(包括楼主自己)都在讨论OO或PO具体语法的对比。但楼主所提问题。从范畴上讲,显然远超具体语法这个层面。

所以这事儿不能细说,只能从实际应用效果来判断。到目前为止,OO 最成功的应用就是在 UI 上应用,其他领域似乎没有明显表现出相对 PO 的优势。

不少牛人,比如Linux之父,都是强烈反 OO 的
现在Google最新推出的 Go 语言,OO特性已经不明显(只有不支持继承的类,实际上跟c语言的struct差不多)。Go语言的作者也都是计算机领域的资深牛人,Go语言的语法显然是经过深思熟虑的。

老大,你这句完全是误传,他批评的是C++的语言模型...不是反对OO。

并非误传,你自己可以google相关中英文信息。

原帖找不到了,有个译文:http://blog.csdn.net/turingbook/archive/2007/09/07/1775488.aspx
39 楼 xuby 2010-07-16  
piao_bo_yi 写道
xuby 写道
楼上这些同学(包括楼主自己)都在讨论OO或PO具体语法的对比。但楼主所提问题。从范畴上讲,显然远超具体语法这个层面。

所以这事儿不能细说,只能从实际应用效果来判断。到目前为止,OO 最成功的应用就是在 UI 上应用,其他领域似乎没有明显表现出相对 PO 的优势。

不少牛人,比如Linux之父,都是强烈反 OO 的
现在Google最新推出的 Go 语言,OO特性已经不明显(只有不支持继承的类,实际上跟c语言的struct差不多)。Go语言的作者也都是计算机领域的资深牛人,Go语言的语法显然是经过深思熟虑的。

老大,你这句完全是误传,他批评的是C++的语言模型...不是反对OO。

并非误传,你自己可以google相关中英文信息。
38 楼 truekbcl 2010-07-16  
piao_bo_yi 写道
truekbcl 写道
piao_bo_yi 写道
truekbcl 写道
抛开比较累人的原生类型,c++完美的结合了这些范式。还是用c++吧:D

结合的特性太多,就导致了一门混乱的语言。当你有天发现,其实只有一小部分特性是你需要的时候,你一定经历过非常痛苦的过程。有时候太多的选择和没有选择一样,都是很糟糕的选择。

特性多并不是导致混乱的根源,感觉混乱一般是因为自己不理解。特性的增加是依据程序设计需求而提出的,现在程序设计所需要的特性越来越多,并不是一小部分特性就够了。当然,具体到个人,有可能只需要一小部分就够了。所以简单语言复杂语言都有存在的道理。最后,多选择是必然的,远不是单一选择能比的,代价就是必须得付出更多的努力。我倒是认为单一选择就是没选择。

难道你希望我们都得有数十年经验才能很好的编程?

难道你认为几年就能很好的编程?
37 楼 piao_bo_yi 2010-07-16  
truekbcl 写道
piao_bo_yi 写道
truekbcl 写道
抛开比较累人的原生类型,c++完美的结合了这些范式。还是用c++吧:D

结合的特性太多,就导致了一门混乱的语言。当你有天发现,其实只有一小部分特性是你需要的时候,你一定经历过非常痛苦的过程。有时候太多的选择和没有选择一样,都是很糟糕的选择。

特性多并不是导致混乱的根源,感觉混乱一般是因为自己不理解。特性的增加是依据程序设计需求而提出的,现在程序设计所需要的特性越来越多,并不是一小部分特性就够了。当然,具体到个人,有可能只需要一小部分就够了。所以简单语言复杂语言都有存在的道理。最后,多选择是必然的,远不是单一选择能比的,代价就是必须得付出更多的努力。我倒是认为单一选择就是没选择。

难道你希望我们都得有数十年经验才能很好的编程?
36 楼 piao_bo_yi 2010-07-16  
xuby 写道
楼上这些同学(包括楼主自己)都在讨论OO或PO具体语法的对比。但楼主所提问题。从范畴上讲,显然远超具体语法这个层面。

所以这事儿不能细说,只能从实际应用效果来判断。到目前为止,OO 最成功的应用就是在 UI 上应用,其他领域似乎没有明显表现出相对 PO 的优势。

不少牛人,比如Linux之父,都是强烈反 OO 的
现在Google最新推出的 Go 语言,OO特性已经不明显(只有不支持继承的类,实际上跟c语言的struct差不多)。Go语言的作者也都是计算机领域的资深牛人,Go语言的语法显然是经过深思熟虑的。

老大,你这句完全是误传,他批评的是C++的语言模型...不是反对OO。
35 楼 y3320987 2010-07-16  
想想,用对象来组成一个过程....
34 楼 truekbcl 2010-07-16  
piao_bo_yi 写道
truekbcl 写道
抛开比较累人的原生类型,c++完美的结合了这些范式。还是用c++吧:D

结合的特性太多,就导致了一门混乱的语言。当你有天发现,其实只有一小部分特性是你需要的时候,你一定经历过非常痛苦的过程。有时候太多的选择和没有选择一样,都是很糟糕的选择。

特性多并不是导致混乱的根源,感觉混乱一般是因为自己不理解。特性的增加是依据程序设计需求而提出的,现在程序设计所需要的特性越来越多,并不是一小部分特性就够了。当然,具体到个人,有可能只需要一小部分就够了。所以简单语言复杂语言都有存在的道理。最后,多选择是必然的,远不是单一选择能比的,代价就是必须得付出更多的努力。我倒是认为单一选择就是没选择。
33 楼 liudun 2010-07-16  
我想多看看优秀的开源代码是有益于理解OOP的。

工作中接触的同事们,很多都有搞C、C++经历的,所以它们写的java代码都是贫血对象——就是说领域对象本省总是没有任何逻辑,逻辑都放到**Manager、**Service里面去了。这没办法,‘一切皆对象’的思想并没有普及。到处都是面向过程的java代码。
32 楼 liudun 2010-07-16  
我不认同你关于static的观点。假设Person类的所有实例都有eat()方法,难道Person类本身不可以有?你可以不仅仅把Person的实例当做对象,Person类型本身也是对象,只不过不是语言层面可以实例化的对象。所以static可以看做是该类型对象固有的属性或行为。

static的东西,可以看做是共性,而不需要各实例去分别实现。比如Collections类,它集中了所有collection的特征,所以它就应该有个static的reverse()方法。

我认为OO是个见仁见智的东西,看你怎么理解。我的看法是并非只有可以new出来的才叫对象,Person类的实例p1是个对象,Person也可以看做是对象。
31 楼 xuby 2010-07-16  
楼上这些同学(包括楼主自己)都在讨论OO或PO具体语法的对比。但楼主所提问题。从范畴上讲,显然远超具体语法这个层面。

所以这事儿不能细说,只能从实际应用效果来判断。到目前为止,OO 最成功的应用就是在 UI 上应用,其他领域似乎没有明显表现出相对 PO 的优势。

不少牛人,比如Linux之父,都是强烈反 OO 的。
现在Google最新推出的 Go 语言,OO特性已经不明显(只有不支持继承的类,实际上跟c语言的struct差不多)。Go语言的作者也都是计算机领域的资深牛人,Go语言的语法显然是经过深思熟虑的。
30 楼 piao_bo_yi 2010-07-16  
truekbcl 写道
抛开比较累人的原生类型,c++完美的结合了这些范式。还是用c++吧:D

结合的特性太多,就导致了一门混乱的语言。当你有天发现,其实只有一小部分特性是你需要的时候,你一定经历过非常痛苦的过程。有时候太多的选择和没有选择一样,都是很糟糕的选择。
29 楼 truekbcl 2010-07-16  
抛开比较累人的原生类型,c++完美的结合了这些范式。还是用c++吧:D
28 楼 chenxin130 2010-07-15  
支持一下lz

我很喜欢用C写PO那种畅快的感觉,这是用java难以体会的。

PO更容易去表达处理的流程,比如图像处理的算法等等
而OO编程有点像搭积木,设计模式是积木排列的一些经典结构。
27 楼 tedeyang 2010-07-15  
数据离行为更远绝对不是好事。
把你的灵魂抽离肉体,看你还能独立发贴不?
26 楼 cleanerje 2010-07-15  
OO是擅长解决实际生活中的业务问题。
PO是擅长解决机器的问题。
两个东西擅长的领域不同。不能比较谁好谁坏好坏。
如果是ERP系统,肯定要用OO,如果是算法那当然用PO
另外,只要是冯诺依曼体系,不管是面向方面、面向对象、模块化都是过程化编写出来的。
25 楼 piao_bo_yi 2010-07-15  
LZ把思维方式(OO PO)和语言模型搞得有些混乱啊。不过这种高难度问题,一般人也搞不明白,可以理解,我们都停留在背背概念的基础上。

相关推荐

Global site tag (gtag.js) - Google Analytics