`

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

阅读更多
加个通道: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.
分享到:
评论
4 楼 ray_linn 2010-07-15  
恩,Java不是OO语言的全部吧。回调函数在C#里就很处理并不尴尬,(当然用C++搞就更不尴尬了),从楼主的例子上看,只能说Java太固步自封了,在C#出来之前一直没有进步。

class A
{
      public event ProcessDelegate ProcessEvent;
}      

var a =new A(); 
a.ProcessEvent += new ProcessDelegate(t_ProcessEvent);


也可以这样搞
        class A<T>
        {
            public void MethodA(Func<T> fun)
            {
                fun.Invoke();
            }
        }


第二个问题就更简单了,C#中有扩展方法,我们给A,B做个伪接口
interface Fake{}
Class A :Fake{}
Class B :Fake{}
static Class Ext
{
   TypeA MehtodA(this Fake ojb, ParamA){}
   TypeB MethodB(this Fake obj, ParamB){}
}

调用时
A.MethodA(...) A.MethodB(...), B.MethodA(...),B.MethodB(...); 如果问题再具体点,还有更多有趣的方法。


3 楼 jasongreen 2010-07-15  
dennis_zane 写道
说的还是状态保存在哪里的问题,OO将状态保存在对象里,PO将状态保存在方法参数之中,PO的方法更容易做到没有副作用,组合起来当然更容易。而OO要处理状态,状态的组合却不是那么容易,要处理覆盖、同名、别名等情况,并且OO将类型信息也附加于对象之上,处理起来更是麻烦了。

嗯,是的,这是导致“面向对象的代码在重构和重用上没有面向过程的灵活”的主要原因。
2 楼 yuan 2010-07-15  
引用
浮在海上的冰山,大部分的内容在海面以下。海面以上的用OO来表现会更美,海面以下的用PO来表现会更合适。
对最后的这个结论有点感觉,不过没仔细研究过。但是我觉得lz举的例子不足以推出这个结论。

1、首先Java似乎算不上典型的面向对象语言。然后说这个static,Ruby中对应Java的静态方法有类方法,但Ruby的类是个对象,所以类方法也是对象的方法。只是这个对象比较特别,生命周期比较长,作用域相对广些吧……看起来只是个概念定义的问题。对于“我们需要全局性的变量、全局性的函数”,我也觉得是这样

2、Java中事件监听似乎多用匿名类,相对麻烦些,这个似乎只是因为Java中的方法不是一个对象,不能直接当参数传递给某个方法。JavaScript中的function、Ruby里的proc都是一个对象。从你的代码结合我对python粗浅了解过的一丁点印象中,好像python的function也是个对象。

3、不懂python……仔细看看像是给同一个函数传递不同类型的参数,这是强类型和弱类型的问题,也应该算不上OO和PO的问题吧。

引用
我们经常说MVC,数据、逻辑、视图分离。

MVC是视图、逻辑分离,中间搭个控制器。数据和业务逻辑再分离出去是大部分SSHer的做法,就是传说中的贫血模型吧。陶文同学介绍了个qi4j似乎是一剂良药,但那之后俺钻到Ruby中去就没了解了。

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

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

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

这后半段内容在以前我会不以为然,不过学了一段时间JavaScript之后挺同意的。
关于前半段,那个包的概念跟Java的package是不是同一回事?如果是的话,那好像也只能说PO比OO少了些东西……作用域的控制上还是OO可控性好些吧。
1 楼 dennis_zane 2010-07-14  
说的还是状态保存在哪里的问题,OO将状态保存在对象里,PO将状态保存在方法参数之中,PO的方法更容易做到没有副作用,组合起来当然更容易。而OO要处理状态,状态的组合却不是那么容易,要处理覆盖、同名、别名等情况,并且OO将类型信息也附加于对象之上,处理起来更是麻烦了。

相关推荐

    面向对象和面向过程的区别

    面向对象编程(Object-Oriented Programming, OOP)和面向过程编程(Procedural Programming)是两种不同的编程范式,它们在解决问题的方式上有着本质的区别。 面向过程编程是一种自底向上的编程思想,它关注的是...

    面向对象软件开发过程

    面向对象软件开发过程 面向对象软件开发过程是当前主要应用的一种技术,它和面向过程形成了鲜明的对比。面向对象的软件开发就是将面向对象的思想应用于软件开发过程中的各个阶段,其主要过程为:首先从实际问题触发...

    面向对象 面向对象 面向对象

    7. **面向对象与面向过程对比**:面向对象编程与传统的面向过程编程相比,更注重数据和操作数据的方式,而非步骤的执行顺序。面向对象强调模块化和组件化,更适合处理复杂系统的构建。 8. **案例分析**:在实际开发...

    面向对象的思考过程(英文版).zip

    这个压缩包文件《面向对象的思考过程(英文版)》很可能提供了一个深入探讨面向对象设计原则、概念和技术的详细指南。 1. **对象与类**:对象是OOP中的核心单元,它包含属性(也称为成员变量或字段)和方法(成员函数...

    面向对象分析与设计UML2.0(PDF)

    详细介绍了面向对象的分析与设计,全面探讨了面向对象概念、软件开发过程、UML和多层技术。本书使用最常见的技术和方法,通过一个贯穿全书的案例分析,对面向对象的软件开发过程和使用面向对象技术的编程过程进行了...

    Python面向对象之类和对象实例详解

    本文实例讲述了Python面向对象之类和对象。分享给大家供大家参考,具体如下: 类和对象(1) 对象是什么? 对象=属性(静态)+方法(动态); 属性一般是一个个变量;方法是一个个函数; #类的属性 就是 类变量 #...

    面向过程与面向对象的区别

    面向过程和面向对象是两种不同的编程范式,它们在解决问题的方式和代码结构上有显著的差异。面向过程编程(Procedure-Oriented Programming)是一种基于步骤的编程思维,它侧重于将一个问题分解为一系列有序的函数或...

    面向对象编程与非面向对象编程

    非面向对象编程,也称为面向过程编程或面向数据编程,它的核心是通过函数或过程来组织代码,程序的执行流程主要由控制结构决定,数据和行为通常是分离的。非OOP的特点包括: - **函数/过程中心**:程序的主要构成...

    面向对象与面向过程的程序设计方法比较.pdf

    根据给定文件的信息,本文将深入探讨面向对象与面向过程这两种程序设计方法,并对比分析两者的特点及适用场景。 ### 面向过程的程序设计 面向过程的程序设计方法是传统编程模式的基础,它强调按照一定的顺序来组织...

    实用面向对象软件工程教程

    4. 面向对象分析过程:介绍需求获取、问题域建模和分析模型验证的方法。 5. 面向对象设计原则:讲解OOD的基本原则,并提供实际案例展示如何遵循这些原则进行设计。 6. 质量保证和测试:讨论面向对象系统如何进行单元...

    Java用面向对象和面向过程方法解求100内素数并输出素数之和

    无论是面向过程还是面向对象,每种编程范式都有其适用场景和优缺点。对于简单的任务,如本例中的素数查找,面向过程的方法可能更为直接有效;而对于复杂系统,面向对象提供了更好的结构化和模块化支持。理解和掌握...

    面向对象葵花宝典-电子版

    面向对象是目前最流行的一种程序设计和实现思想,无论你是从事企业级开发、互联网应用开发,还是手 机软件开发,都会使用到面向对象的技术;主流的编程语言中,C++,Java,C#,PHP,Python等都是支持 面向对象的语言;...

    Python 3面向对象编程

    Python 是一种面向对象的解释型语言,面向对象是其非常重要的特性。《Python 3面向对象编程》通过Python 的数据结构、语法、设计模式,从简单到复杂,从初级到高级,一步步通过例子来展示了Python 中面向对象的概念...

    什么是面向对象?什么是面向过程?

    这是对面向过程和面向对象的解释,个人参考一些文章后做的小总结。

    漫画面向对象编程 Java

    借助于漫画展示的形式,面向对象的简、由类创建一个对象的方法、类的编写与对象的创建、类的构造函数、类的方法、修饰符、Java中的封装/继承/多态等特征、Java中的线程、用Java创建一个小世界、多线程共享数据,以及...

    面向对象分析与设计1

    国外计算机科学经典教材-面向对象分析与设计(UML 2.0版) 简介:本书详细介绍了面向对象的分析与设计,全面探讨了面向对象概念、软件开发过程、UML和多层技术。 本书使用最常见的技术和方法,通过一个贯穿全书的...

    浅谈面向过程与面向对象编程思想_以五子棋小游戏开发为例

    面向过程与面向对象是两种不同的编程范式,它们在计算机科学中被广泛应用,并在五子棋小游戏的开发中体现得尤为明显。 首先,让我们来探讨面向过程的编程思想。面向过程的编程方法注重于算法的实现,将程序分解为一...

Global site tag (gtag.js) - Google Analytics