`

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

阅读更多
加个通道: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.
分享到:
评论
84 楼 hiblue 2010-07-21  
很赞同楼主的观点.
83 楼 phlsbg 2010-07-20  
面向对象基本上是被神化了

   
82 楼 Rambing 2010-07-20  
个人感觉这个问题楼主的出发点不是很好,面向对象的出现是取代面向过程设计中的不足的。而语言本身只是起到一个实现的目的。并不能说明什么问题。

所以如果从设计这个角度去理解的话,那么面向对象在一些很多地方对于面向过程的优势就体现出来了。尤其是在大型系统的应用上。

在面向过程方式中,通常是分模块,画数据流进行设计。
而在OO中却变成了 用例图,序列图,状态图等。
个人感觉这个和经济领域的计划和市场有点像。面向结构做设计的时候就像在做计划,可是实际上很难将所有过程都计划好。而面向对象重点在于将职责明确的分解到各个对象中去,用例图,序列图和状态图都可以明确看出某个职责的归属。(市场就是规定了职责权利后,自由发挥完成交易)

因为有了面向对象设计的优势,所以才出现了面向对象的语言。因为面向对象的语言对于实现面向对象的设计更加的直观方便。事实上使用C也可以实现面向对象的设计,但是这个实现比较有难度。
81 楼 phlsbg 2010-07-20  
就怕见到这种说思想的,思想怎么度量?怎么量化?
说OO思想的人能列出来么?怎么的有个123吧,而且要保证能能度量,量化

    好的程序高内聚,低耦合。相对可以复用。
在我看来这是符合好的标准最低要求,这个和面向对象有关系么?
具体来说我认为面向对象是语言的技术,要上升到思想层面似乎每个人的理解都不一样
如果不能度量、量化的东西我们还是离他远点。
80 楼 yangguo 2010-07-20  
呜呼哀哉,这样也能评良好。看来代表封建思想的PO时代其影响力还是根深蒂固,民智未开。
79 楼 ironsabre 2010-07-20  
mis98zb 写道
ipconfiger 写道
你从哪里得来面向过程将无法应付,最终导致系统的崩溃 的结果的,臆测居多吧,还是看着书上这么写你就这么说阿。Unix复杂不?面向对象了吗?Unix崩溃了吗?怕是windows崩溃得更加的常见吧


Unix主要得益于它的exe + sh风格吧。
提倡一个程序只做好一件事情,复杂事物由脚本驱动exe协作完成。

我觉得这个跟OO的思想还是有共通之处的。


这不是oo的思想,这只是一些做事的基本原则。
这些原则oo可守,po也可守,包括平时做事的时候也可守的。
不能把这些都放到oo的思想里去。
78 楼 mis98zb 2010-07-20  
ipconfiger 写道
你从哪里得来面向过程将无法应付,最终导致系统的崩溃 的结果的,臆测居多吧,还是看着书上这么写你就这么说阿。Unix复杂不?面向对象了吗?Unix崩溃了吗?怕是windows崩溃得更加的常见吧


Unix主要得益于它的exe + sh风格吧。
提倡一个程序只做好一件事情,复杂事物由脚本驱动exe协作完成。

我觉得这个跟OO的思想还是有共通之处的。
77 楼 mis98zb 2010-07-20  
ltian 写道
仅从编码的角度来比较面现象对象和面向过程,我感觉有些偏颇!
不妥之处,欢迎讨论!


严重同意。
76 楼 ironsabre 2010-07-20  
lyy3323 写道
ironsabre 写道
lyy3323 写道
楼主有避重就轻的嫌疑呀。
何为面向对象?
不得不说封装,继承,多态。
楼主把面向对象海面以下的代码拿出来与过程相比。。。
纠结。。。。
面向对象的大部分思想在面向过程中也能体现 
但面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃 。
再次纠结。。。。


扯淡,看看linux用什么写的。



这位哥,我想先问下你,你用过面对过程的语言开发过大型系统吗?
并不是说面向过程就肯定导致系统膨胀(良好的设计当然可以避免。)。
而是面对对象相比之下,突显了这个问题。
封装你懂吗?


1。 但面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃 。

2。 并不是说面向过程就肯定导致系统膨胀(良好的设计当然可以避免。)。

你已经前后矛盾了。
75 楼 lyy3323 2010-07-19  
ironsabre 写道
lyy3323 写道
楼主有避重就轻的嫌疑呀。
何为面向对象?
不得不说封装,继承,多态。
楼主把面向对象海面以下的代码拿出来与过程相比。。。
纠结。。。。
面向对象的大部分思想在面向过程中也能体现 
但面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃 。
再次纠结。。。。


扯淡,看看linux用什么写的。



这位哥,我想先问下你,你用过面对过程的语言开发过大型系统吗?
并不是说面向过程就肯定导致系统膨胀(良好的设计当然可以避免。)。
而是面对对象相比之下,突显了这个问题。
封装你懂吗?
74 楼 ltian 2010-07-19  
面向对象精髓在于继承和多态,楼主仅就封装性一个方面与面向过程进行比较,难怪得出如此结论。

面向对象的好处在与于对象的方式描述现实世界,也就是说面向对象提供将对现实世界映射为计算机中模型的一个良好的方法。

面向对象方式对世界的描述,可以使得将来计算机能够理解有特定语义的对象,并执行其行为,从而使人工智能得到发展。本体论就是指业务领域对象的形式化描述。如果没有业务领对象的概念,本体论就不会存在了,而本体论则是面向语义学的下一代智能万维网的基础之一。

所以,仅从编码的角度来比较面现象对象和面向过程,我感觉有些偏颇!
不妥之处,欢迎讨论!
73 楼 ilove2009 2010-07-19  
做一件事,OO和PO都可以,从这个角度看,OO和PO只是代码的不同组织方式而已。
72 楼 ipconfiger 2010-07-19  
lyy3323 写道
楼主有避重就轻的嫌疑呀。
何为面向对象?
不得不说封装,继承,多态。
楼主把面向对象海面以下的代码拿出来与过程相比。。。
纠结。。。。
面向对象的大部分思想在面向过程中也能体现 
但面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃 。
再次纠结。。。。


你从哪里得来面向过程将无法应付,最终导致系统的崩溃 的结果的,臆测居多吧,还是看着书上这么写你就这么说阿。Unix复杂不?面向对象了吗?Unix崩溃了吗?怕是windows崩溃得更加的常见吧
71 楼 ironsabre 2010-07-19  
lyy3323 写道
楼主有避重就轻的嫌疑呀。
何为面向对象?
不得不说封装,继承,多态。
楼主把面向对象海面以下的代码拿出来与过程相比。。。
纠结。。。。
面向对象的大部分思想在面向过程中也能体现 
但面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃 。
再次纠结。。。。


扯淡,看看linux用什么写的。
70 楼 lyy3323 2010-07-19  
楼主有避重就轻的嫌疑呀。
何为面向对象?
不得不说封装,继承,多态。
楼主把面向对象海面以下的代码拿出来与过程相比。。。
纠结。。。。
面向对象的大部分思想在面向过程中也能体现 
但面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃 。
再次纠结。。。。
69 楼 ray_linn 2010-07-19  
JE帐号 写道
我被很多人雷到了...
OO是一种认识问题的思想.他与实现技巧没什么关系.所以LZ举的回调函数的注册,包括某楼说的什么GO没有继承之类的,和OO无关.最多是和Java有关.而像有人举的C#的实现,更多的类似语法糖而已.
OO从来不是作为真理出现的,OO仅仅是我们使用程序去映射现实的一个比较好的实践.
所以你去讨论OO,应该是去讨论OO对处理哪些场景有很大帮助,哪些场景下却显得力不从心.而不是揪着个语言,说这不好那不好.




那任何高级语言还都是机器语的语法糖呢,语法糖才能让计算语言更像人类的自然语言,一颗语法糖,背后还多少伟大的工程师在编译器下做出多少功课。

本来举C#,就是告诉楼主,某种语言是有其特殊性的,尤其是以java这样进步缓慢的语言。
68 楼 agile_boy 2010-07-19  
  又是语言思想之争,显然我觉得否定或者肯定一个东西,不能靠几个例子,或者说显示某 些缺点的示例来说明,所谓尺有所长,寸有所短,如果用OO来开发底层或者嵌入式的系统,显然没有什么优势,但是如果用来C/S的GUI的开发,复杂业务系统的开发,优势还是显而易见的。
  中国传统的观点,“中庸”,我的个人理解,就是取得一个“平衡点”。
67 楼 xuby 2010-07-19  
OO 出现的时候,打的旗号是可以弥合现实世界和开发世界之间的裂缝。怎么弥合?按OO布道者的说法,非常简单:把现实世界的对象映射为开发世界的对象就行了。比如,现实世界的人,映射为程序里面的 Class Person。
但是,现在的OO程序里面,满目的×××Manager、×××Factory、×××Helper 类,和现实世界的什么对象做了对应?没有,只是和脑袋里的对象对应。
所以,OOA之类都是瞎扯,OO什么都提供不了,除了提供了一些新的解耦技巧。但相比OP,也不见得全面优越。只是在某些场合也许有用。
因此,不要迷信OO,OO只是技巧层面的东西,有用时拿来用就好了,开发时OO也行,OP也行,OO、OP混搭也行,只要合适。
66 楼 lonelybug 2010-07-18  
subwayline13 写道
lonelybug 写道


嗯,你是该好好看看design patterns原著的开篇介绍了!

好奇问问php那么灵活,请问如何实现singleton设计模式?

最后告诉你,设计模式跟Java没有直接关系,设计模式就是设计模式,就连design patterns这本书中的例子也很好用Java去做。

一帮做外包天天SSH的,发这么多口水帖子干啥,我很奇怪!


设计模式受到语言的影响,singleton对于PHP来说和JAVA不一样,因为请求结束后会回收所有的资源。书上有跟语言无关就真无关吗?尽信书不如无书。

写段PHP代码吧
class Class1 {
	private static $instance;
 
	private function Class1(){
		$ip = $_SERVER["REMOTE_ADDR"];
		$time = date("Y-m-d H:i:s", time());
		
		
		$myfile = 'F:/statistic.txt';
		$str = "ip='".$ip."' time='".$time."'\r\n";
		$file_pointer = fopen($myfile,"a");
		fwrite($file_pointer,$str);
		fclose($file_pointer);
	}
	
	public function test() {
		echo "Hello World!<br />";
	}
	
	public static function singleton()
	{ 
		if (!isset(self::$instance)) { 
			self::$instance = new Class1();
		}
		return self::$instance;
	} 
}

$class1 = Class1::singleton();
$class1->test();

$class2 = Class1::singleton();
$class2->test();

$class3 = Class1::singleton();
$class3->test();


刷新几下打开记事本看看
引用

ip='127.0.0.1' time='2010-07-18 21:33:38'
ip='127.0.0.1' time='2010-07-18 21:33:46'
ip='127.0.0.1' time='2010-07-18 21:34:58'
ip='127.0.0.1' time='2010-07-18 21:34:59'


为啥某些人抱怨PHP捏?以为singleton了,资源初始化一次就万事OK了,其实每次请求都初始化一遍。讨论这个又歪楼了。


哈哈哈,我服了,我没办法跟这么一帮糊涂蛋讨论明白人的事情。

所以,我决定退出这个讨论,在说话,我就是王八。


最后的最后说一下你这个php代码,我帮你简化一下,你这个部叫做singleton模式。你这个就叫做局部变量。
你运行,打开一个笔记本一样可以得到。

singleton就是指初始化一边,谁告诉你singleton每次都从新初始化一边了?你连最基本的内存指针都不知道么?我真不知道你们这帮人舔着脸在这里讨论什么呢?你要是去C S D N,我估计,你就该被前辈们活活骂死。

$ip = $_SERVER["REMOTE_ADDR"];
$time = date("Y-m-d H:i:s", time());

$myfile = 'F:/statistic.txt';

$time = date("Y-m-d H:i:s", time());
$str = $str."ip='".$ip."' time='".$time."'\r\n";

$time = date("Y-m-d H:i:s", time());
$str = $str."ip='".$ip."' time='".$time."'\r\n";

$time = date("Y-m-d H:i:s", time());
$str = $str."ip='".$ip."' time='".$time."'\r\n";

$file_pointer = fopen($myfile,"a");
fwrite($file_pointer,$str);
fclose($file_pointer);


65 楼 伊苏 2010-07-18  
PO里, 我们可以把一个对象吹嘘成一个过程
OOP里, 一个过程可以忽悠为一个对象

就像我们人, 是一堆过程组成的对象, 还是一堆对象组成的过程?
这个地球, 太阳早晚也是要灭亡,
这是一个过程? 还是一个对象?
这是一个过程! 也是一个对象!(觉得有点像佛理了...汗)

最后, 让面向过程还是面向对象见鬼去吧!
老子只是想活得痛快点而已

相关推荐

Global site tag (gtag.js) - Google Analytics