关于编程范式的分析与理解



随着编程(programming、偶不喜欢说程序设计)方法学和软件工程研究的深入,特别是OO思想的普及,范式(paradigm以及编程范式等术语渐渐出现在人们面前。

面向对象编程(OOP)常常被誉为是一种革命性的思想,正因为它不同于其他的各种编程范式;编程范式也许是学习任何一门编程语言时要理解的最重要的术语。

然而,在国内逐步了解“范式/编程范式”时,英文中该术语已经处于abuse的地步。

 

§1基本含义

 

      托马斯.库恩提出“科学的革命”的范式论之后,Robert Floyd1979年图灵奖的颁奖演说中使用了编程范式一词。编程范式一般包括三个方面,以OOP为例:

1.       学科的逻辑体系:如类/对象、继承、动态绑定、方法改写、对象替换等等机制。

2.       心理认知因素:按照面向对象编程之父Alan Kay的观点,“计算就是模拟”。OO范式极其重视隐喻(metaphor)的价值,通过拟人化,按照自然的方式模拟自然。

3.       自然观:强调程序的组织技术,视程序为松散耦合的对象/类的集合,以继承机制将类组织成一个层次结构,把程序运行视为相互服务的对象们之间的对话。

      简单的说,编程范式是程序员看待程序应该具有的观点。下面是常见的编程范式和常用的一些编程语言:

 编程范式与编程语言

编程范式与编程语言

 

      一般而言,编程语言的设计者常常让该语言支持某一特定的范式,如Java语言只支持面向对象的范式;但编程语言也可能支持多种范式,如C++语言支持面向对象的范式,同时也支持过程式范式。我们很小心的说一些语言支持某种编程范式,而不说它们实践或贯彻特定的编程范式,因为,程序员如何使用一种语言仅仅依赖于程序员。

      

      面向对象技术一方面借鉴了哲学、心理学、生物学的思考方式,另一方面,它是建立在其他编程技术之上的,是以前的编程思想的自然产物。

 

简单的说,编程范式是程序员看待程序应该具有的观点。

为了进一步加深对编程范式的认识,这里介绍几种最常见的编程范式。 

需要再次提醒注意的是:编程范式是编程语言的一种分类方式,它并不针对某种编程语言。就编程语言而言,一种编程语言也可以适用多种编程范式。 

过程化(命令式)编程 

过程化编程,也被称为命令式编程,应该是最原始的、也是我们最熟悉的一种传统的编程方式。从本质上讲,它是“冯.诺伊曼机“运行机制的抽象,它的编程思维方式源于计算机指令的顺序排列。

(也就是说:过程化语言模拟的是计算机机器的系统结构,而并不是基于语言的使用者的个人能力和倾向。这一点我们应该都很清楚,比如:我们最早曾经使用过的单片机的汇编语言。)

过程化编程的步骤是:

首先,我们必须将待解问题的解决方案抽象为一系列概念化的步骤。然后通过编程的方式将这些步骤转化为程序指令集(算法),而这些指令按照一定的顺序排列,用来说明如何执行一个任务或解决一个问题。这就意味着,程序员必须要知道程序要完成什么,并且告诉计算机如何来进行所需的计算工作,包括每个细节操作。简言之,就是将计算机看作一个善始善终服从命令的装置。

所以在过程化编程中,把待解问题规范化、抽象为某种算法是解决问题的关键步骤。其次,才是编写具体算法和完成相应的算法实现问题的正确解决。当然,程序员对待解问题的抽象能力也是非常重要的因素,但这本身已经与编程语言无关了。

 程序流程图是过程化语言进行程序编写的有效辅助手段。 

尽管现存的计算机编程语言很多,但是人们把所有支持过程化编程范式的编程语言都被归纳为过程化编程语言。例如机器语言、汇编语言、BASIC、COBOL、C 、FORTRAN、语言等等许多第三代编程语言都被归纳为过程化语言。 

过程化语言特别适合解决线性(或者说按部就班)的算法问题。它强调“自上而下(自顶向下)”“精益求精”的设计方式。这种方式非常类似我们的工作和生活方式,因为我们的日常活动都是按部就班的顺序进行的。 

 过程化语言趋向于开发运行较快且对系统资源利用率较高的程序。过程化语言非常的灵活并强大,同时有许多经典应用范例,这使得程序员可以用它来解决多种问题。 

过程化语言的不足之处就是它不适合某些种类问题的解决,例如那些非结构化的具有复杂算法的问题。问题出现在,过程化语言必须对一个算法加以详尽的说明,并且其中还要包括执行这些指令或语句的顺序。实际上,给那些非结构化的具有复杂算法的问题给出详尽的算法是极其困难的。 

广泛引起争议和讨论的地方是:无条件分支,或goto语句,它是大多数过程式编程语言的组成部分,反对者声称:goto语句可能被无限地滥用;它给程序设计提供了制造混 乱的机会。目前达成的共识是将它保留在大多数语言中,对于它所具有的危险性,应该通过程序设计的规定将其最小化。 

事件驱动编程 

其实,基于事件驱动的程序设计在图形用户界面(GUI)出现很久前就已经被应用于程序设计中,可是只有当图形用户界面广泛流行时,它才逐渐形演变为一种广泛使用的程序设计模式。 

在过程式的程序设计中,代码本身就给出了程序执行的顺序,尽管执行顺序可能会受到程序输入数据的影响。

在事件驱动的程序设计中,程序中的许多部分可能在完全不可预料的时刻被执行。往往这些程序的执行是由用户与正在执行的程序的互动激发所致。 

  • 事件。就是通知某个特定的事情已经发生(事件发生具有随机性)。 
  • 事件与轮询。轮询的行为是不断地观察和判断,是一种无休止的行为方式。而事件是静静地等待事情的发生。事实上,在Windows出现之前,采用鼠标输入字符模式的PC应用程序必须进行串行轮询,并以这种方式来查询和响应不同的用户操做。 
  • 事件处理器。是对事件做出响应时所执行的一段程序代码。事件处理器使得程序能够对于用户的行为做出反映。 

事件驱动常常用于用户与程序的交互,通过图形用户接口(鼠标、键盘、触摸板)进行交互式的互动。当然,也可以用于异常的处理和响应用户自定义的事件等等。

事件的异常处理比用户交互更复杂。 

事件驱动不仅仅局限在GUI编程应用。但是实现事件驱动我们还需要考虑更多的实际问题,如:事件定义、事件触发、事件转化、事件合并、事件排队、事件分派、事件处理、事 件连带等等。

其实,到目前为止,我们还没有找到有关纯事件驱动编程的语言和类似的开发环境。所有关于事件驱动的资料都是基于GUI事件的。 

属于事件驱动的编程语言有:VB、C#、Java(Java Swing的GUI)等。它们所涉及的事件绝大多数都是GUI事件。 

面向对象编程 

过程化范式要求程序员用按部就班的算法看待每个问题。很显然,并不是每个问题都适合这种过程化的思维方式。这也就导致了其它程序设计范式出现,包括我们现在介绍的面向对象的程序设计范式。 

面向对象的程序设计模式已经出现二十多年,经过这些年的发展,它的设计思想和设计模式已经稳定的进入编程语言的主流。来自TIOBE Programming Community2010年11月份编程语言排名的前三名Java、C、C++中,Java和C++都是面向对象的编程语言。 

面向对象的程序设计包括了三个基本概念:封装性、继承性、多态性。面向对象的程序语言通过类、方法、对象和消息传递,来支持面向对象的程序设计范式。 

1. 对象

世间万事万物都是对象。

面向对象的程序设计的抽象机制是将待解问题抽象为面向对象的程序中的对象。利用封装使每个对象都拥有个体的身份。程序便是成堆的对象,彼此通过消息的传递,请求其它对象 进行工作。 

2. 类

每个对象都是其类中的一个实体。

物以类聚——就是说明:类是相似对象的集合。类中的对象可以接受相同的消息。换句话说:类包含和描述了“具有共同特性(数据元素)和共同行为(功能)”的一组对象。

比如:苹果、梨、橘子等等对象都属于水果类。 

3. 封装

封装(有时也被称为信息隐藏)就是把数据和行为结合在一个包中,并对对象的使用者隐藏数据的实现过程。信息隐藏是面向对象编程的基本原则,而封装是实现这一原则的一种方 式。

封装使对象呈现出“黑盒子”特性,这是对象再利用和实现可靠性的关键步骤。 

4. 接口

每个对象都有接口。接口不是类,而是对符合接口需求的类所作的一套规范。接口说明类应该做什么但不指定如何作的方法。一个类可以有一个或多个接口。 

5. 方法

方法决定了某个对象究竟能够接受什么样的消息。面向对象的设计有时也会简单地归纳为“将消息发送给对象”。 

6. 继承

继承的思想就是允许在已存在类的基础上构建新的类。一个子类能够继承父类的所有成员,包括属性和方法。

继承的主要作用:通过实现继承完成代码重用;通过接口继承完成代码被重用。继承是一种规范的技巧,而不是一种实现的技巧。 

7. 多态

多态提供了“接口与实现分离”。多态不但能改善程序的组织架构及可读性,更利于开发出“可扩充”的程序。

继承是多态的基础。多态是继承的目的。

合理的运用基于类继承的多态、基于接口继承的多态和基于模版的多态,能增强程序的简洁性、灵活性、可维护性、可重用性和可扩展性。

面向对象技术一方面借鉴了哲学、心理学、生物学的思考方式,另一方面,它是建立在其他编程技术之上的,是以前的编程思想的自然产物。

如果说结构化软件设计是将函数式编程技术应用到命令式语言中进行程序设计,面向对象编程不过是将函数式模型应用到命令式程序中的另一途径,此时,模块进步为对象,过程龟缩到class的成员方法中。OOP的很多技术——抽象数据类型、信息隐藏、接口与实现分离、对象生成功能、消息传递机制等等,很多东西就是结构化软件设计所拥有的、或者在其他编程语言中单独出现。但只有在面向对象语言中,他们才共同出现,以一种独特的合作方式互相协作、互相补充。


    如果说结构化软件设计是将函数式编程技术应用到命令式语言中进行程序设计,面向对象编程不过是将函数式模型应用到命令式程序中的另一途径,此时,模块进步为对象,过程龟缩到class成员方法中。OOP的很多技术——抽象数据类型、信息隐藏、接口与实现分离、对象生成功能、消息传递机制等等,很多东西就是结构化软件设计所拥有的、或者在其他编程语言中单独出现。但只有在面向对象语言中,他们才共同出现,以一种独特的合作方式互相协作、互相补充。


“C++ 三人谈”中看到恶魔曾经指出C++ 的编程 范式可以分为ADT+PP,GP,OO三个方向。

1、 ADT+PP

ADT:abstract data type; 抽象数据类型
PP:procedure programme; 面向过程的编程范式
ADT+PP 就是说面向过程的编程范式+抽象数据类型,你可以理解为c++的前身:带类的C。

2、 GP
GP :泛型编程,GP(Generic Programming,泛型编程)号称编程思想的又一次革命。但是,在论述GP的资料中,一般都是以C++语言为基础来讨论。
泛型编程(Generic Programming, GP)是一种基于参数化(parameterization)的编程技巧:可以使用类型参数化另一种类型(例如,vector 的元素类型就是通过参数确定的);算法也可以参数化另一种算法(例如,使用比较函数参数化排序函数)。GP的目的是将有用的算法或者数据结构尽可能地一般化,并使其最优化。

GP 在某些方面比 OOP 要灵活得多。特别是,它不依赖于层级。例如,int 和 string 之间没有任何层级关系。总的来说,GP 的结构化程度更甚于 OOP。事实上,GP 常被称为“参数多态(parametric polymorphism)”;而 OOP 常被称为“ad hoc 多态”。就 C++ 而言,GP 于编译时就解析了所有名称;它不需要任何动态(运行时)调度。因此,GP 在对运行时效率要求很高的领域占据了主导地位。

请注意,GP 并非万灵丹。很多时候,程序并不需要参数化多态,而需要运行时调度(OOP)。

3、OO:面向对象的编程
面向对象(object oriented, OO),面向对象编程(object-oriented programming, OOP),以及面向对象编程语言(object-oriented programming languages, OOPL)的定义多种多样。想了解我对 OO 的详细看法,请阅读 C++ 为什么不仅仅是面向对象的语言 。我在那里写道,OOP 这种编程风格起源于 Simula(约 40 年以前!),它依赖于封装(encapsulation)、继承(inheritance)以及多态(polymorphism)。就 C++(及许多其它源于 Simula 的语言)而言,OOP 的意思是利用类层级(class hierarchies)及虚函数进行编程,从而可以通过精制的接口操作各种类型的对象,并且程序本身也可以通过派生(derivation)进行功能增量扩展。

请注意,OOP 并非万能药。不要简单地把“OOP”等同于“好”。如果你的问题的基本要素中没有与生俱来的层级关系,那么类层级和虚函数对你的代码不会有任何帮助。 OOP 的优势在于类层级可以有效地表达很多问题;OOP 的主要弱点在于太多人设法强行用层级模式解决问题。并非所有问题都应该面向对象。也可以考虑使用普通类 (plain class)、泛型编程 和独立的函数(就像数学、C,以及 Fortran 中那样)作为解决问题的方案。

多范型编程
多范型(multiparadigm)编程是“以多种风格编程,各尽所能”的花哨讲法。例如,当需要在运行时区分对象类型时用面向对象编程,而在需要静态类型安全性,并且追求执行效率的时候使用泛型编程。显然,多范型编程的主要威力体现在使用多种范型(编程风格)的程序中,要通过用多种支持不同范型的语言来创建同样效果的系统是很难的。多范型编程的最引人注目的效果是:如果使来自不同范型的技术紧密协作,就可以写出比用单范型的程序更精致、维护性更好的代码。

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2012-06/63880.htm

阅读更多
换一批

没有更多推荐了,返回首页