编程与哲学.docx

上传人:b****8 文档编号:10154419 上传时间:2023-02-08 格式:DOCX 页数:28 大小:306.50KB
下载 相关 举报
编程与哲学.docx_第1页
第1页 / 共28页
编程与哲学.docx_第2页
第2页 / 共28页
编程与哲学.docx_第3页
第3页 / 共28页
编程与哲学.docx_第4页
第4页 / 共28页
编程与哲学.docx_第5页
第5页 / 共28页
点击查看更多>>
下载资源
资源描述

编程与哲学.docx

《编程与哲学.docx》由会员分享,可在线阅读,更多相关《编程与哲学.docx(28页珍藏版)》请在冰豆网上搜索。

编程与哲学.docx

编程与哲学

目录Catelog

                      目录Catelog

                      序言Perface

                      真经第一章:

世界Waltanschauung

                      真经第二章:

抽象Abstraction

                      真经第三章:

层次Arrangement

                      真经第四章:

继承Inheritance

                      真经第五章:

耦合Couple

                      真经第六章:

运作Moving

                      真经第七章:

建造Build

                      真经第八章:

刻画Delineate

                      真经第九章:

模式Pattern

                      真经第十章:

悟道Doctrine

                      后记Afterword

                      参考文献Reference

序言Perface

     “佛曰:

苦海无涯,回头是岸。

——佛教用语”

     面向对象(Object-Oriented),这是一条令无数开发人员魂牵梦绕的短语。

几乎每个软件分析师、设计师和程序员都时刻将它铭记于心,对它顶礼膜拜。

然而,对大多数人来说,它又像是天边的霞光,可望而不可及,无数次伸出双手,总是抓不住这虚无缥缈的圣物。

于是,我们依然每天将面向对象高高供其,却始终无法悟得其道,更不要谈娴熟运用其道法了。

     面向对象像一滩苦海,无数人游弋其中,却久久不得其要领;类、对象、继承、多态、接口、UML、设计模式……无数概念看得我们眼花缭乱,却也悟不透其真谛。

佛教有云:

苦海无涯,回头是岸。

如果置身苦海中无法脱离,那么,我们是否应该提高一个层面去看这片苦海:

从哲学及科学的角度,去审视面向对象。

     曾有人说:

艺术的极致是科学,科学的极致是哲学。

此话不无道理,牛顿、爱因斯坦等科学界泰斗,在其后期都不约而同地转向哲学研究。

当然,这里本人无意更不敢将自己与上面两位大师相提并论,而且本人也不奢求此文能成为一篇颇有思想的佳作。

只不过,本人在平时的实践和思考中,略有小得,于是,在这里拿出,和大家一起分享讨论。

虽然肤浅,但希望本文能成为一丝波纹,为各位脱离苦海提供一点点的推动作用。

真经第一章——世界Weltanschauung

     “世界观(德文:

Weltanschauung)意为‘着眼世界之上’,是人们对世界的总的根本的看法。

任何哲学问题的探讨,归其出发点和本源,都是世界观的问题。

什么样的世界观决定了什么样的哲学观点。

——马克思”

1.1、看世界

     我们知道,哲学领域中,最根本的对立是唯物主义和唯心主义的对立,而附属其下,又有许多对立,如形而上学和辩证法的对立、可知论和不可知论的对立等等。

这些对立形成了哲学的基本体系、派别和出发点。

实际上,这些对立,都是世界观的对立。

世界观,简而言之即如何看待这个世界。

世界观是一切哲学问题的本源和出发点。

     同样,在程序世界里,也有着不同的世界观。

而这其中最根本的对立便是过程论和对象论的对立,这个对立,衍生出了面向过程和面向对象两种方法论。

于是,要真正理解面向过程和面相对象,我们就不得不先深究一下程序世界中这两种世界观。

     首先要提到的是,不论是过程论还是对象论,都承认一点,那就是程序世界本质上只有两种东西——数据和逻辑。

数据天性喜静,构成了程序世界的本体和状态;逻辑天性好动,作用于数据,推动程序世界的演进和发展。

尽管上述观点是统一的,但是在数据和逻辑的存在形式和演进形式上,过程论和对象论的观点截然不同。

     过程论认为:

数据和逻辑是分离的、独立的,各自形成程序世界的一个方面(Aspect)。

所谓世界的演变,是在逻辑作用下,数据做改变的一个过程。

这种过程有明确的开始、结束、输入、输出,每个步骤有着严格的因果关系。

过程是相对稳定的、明确的和预定义的,小过程组合成大过程,大过程还可以组合成更大的过程。

所以,程序世界本质是过程,数据作为过程处理对象,逻辑作为过程的形式定义,世界就是各个过程不断进行的总体。

     对象论认为:

数据和逻辑不是分离的,而是相互依存的。

相关的数据和逻辑形成个体,这些个体叫做对象(Object),世界就是由一个个对象组成的。

对象具有相对独立性,对外提供一定的服务。

所谓世界的演进,是在某个“初始作用力”作用下,对象间通过相互调用而完成的交互;在没有初始作用力下,对象保持静止。

这些交互并不是完全预定义的,不一定有严格的因果关系,对象间交互是“偶然的”,对象间联系是“暂时的”。

世界就是由各色对象组成,然后在初始作用力下,对象间的交互完成了世界的演进。

1.2、一道智力题引发的思考

     上面的描述也许有些不够直观,那么,下面我们通过一个实际的例子,直观感受一下在两种世界观下,对同一件事物是怎么看的。

     大家都听过这么个智力题吧:

     说有甲、乙、丙三人住店,一间房30。

于是每人10元,共计给店老板30元住进一间房。

后来店老板发现弄错了,房价应该是25元,于是给小二5元让小二退给房客。

小二黑心,贪污了2元,退给甲乙丙每人1元。

这样房客每人付了10-1=9元,三九27,加上小二贪污的2元,共29元,问那1元哪里去了?

     不知各位聪明的看官是否已经参透其中玄机。

不过参不透也没有关系,这不是重点,重点是,我们现在来分别用过程论和对象论分析一下这件事。

     首先,我们来看看过程论是怎么看这件事情的。

图1.1、过程论看世界

     如图1.1所示,这就是过程论下看这件事的样子。

左边是过程的各个步骤,而右边红字表示在每个过程步骤的数据情况,这种数据情况反映了世界当前的状态。

为简单起见,我们只考虑在这个过程中参与分配的数据。

     初始时甲乙丙各10元,老板和小二没有钱,这可以认为是这个过程的初始状态,这些数据是输入。

随着各个步骤的进行,数据不断更新,而在每个步骤,数据如何更新、更新多少,都是由步骤严格确定的。

经历五个步骤后,数据变为甲乙丙各1元,老板25元,小二2元,这就是终止状态,也是这个过程的输出。

     下面,再来看看对象论下如何看这件事。

图1.2、对象论看世界

     对象论眼中,世界是由各种对象组成的,每个对象有自己的数据和逻辑,如图1.2所示。

在这件事里,有五个基本对象:

甲、乙、丙、小二和老板(注意,这里我们还没有提到类和抽象等概念,所以不要让固有思维跳出来,在这里要只认识对象,不认识类等概念。

现在我们只讨论世界观的基本问题:

程序世界的本质,至于更具体的问题,留待后面讨论)。

每个对象有自己的一系列数据和逻辑,这里只列出了我们关心的部分。

     然后呢?

没有然后了。

没错,在对象论眼里,这就是这件事的本质模样,这件事所涉及的东西就是这么几个对象,本来它们各自独立,老死不相往来。

只不过在“住店”这个外部驱动力下,几个对象“偶然”、“暂时”互相联系,利用其他对象提供的公开服务,完成了一些交互。

在交互中,各自的数据可能会发生一些变化,但对象的本质没有变。

这里也要注意,这种交互虽然在一定程度上由既定逻辑预定义,但不像过程论认为“万事万物都已注定”,在对象论下,对象间的交互是“偶然的”、“暂时的”,这次五个人因为住店这个外部驱动力交互了一次。

但下次如果魏国和蜀国交战变为驱动力,他们间的交互就不是拿钱给钱了,而是刀兵相见。

所以,对象论不认为“一切都已注定”。

1.3、总结

     通过上面一个例子,不知各位是否已经明白程序世界中两种世界观看事物的不同。

下面,有一些问题还要明确一下。

     I.过程论和对象论是两种看世界的观点,没有孰对孰错、孰好孰坏之分。

     II.过程论和对象论不是一种你死我活的绝对对立,而是一种辩证统一的对立,两者相互渗透、在一定情况下可以相互转化,是一种“你中有我、我中有你”的对立。

如果将对象论中的所有交互提取出来而撇开对象,就变成了过程论,而如果对过程论中的数据和逻辑分类封装并建立交互关系,就变成了对象论。

     III.过程论相对确定,有利于明晰演进的方向,但当事物过于庞大繁杂,将很难理清思路。

因为过程繁多、过程中又有子过程,容易将整个世界看成一个纷繁交错的过程网,让人无法看清。

     IV.对象论相对不确定,但是因为以对象为基本元素,即使很庞大的事物,也可以很好地分离关注,在研究一个对象的交互时,只需要关系与其相关的少数几个对象,不用总是关注整个流程和世界。

但是,对象论也有困难。

例如,如何划分对象才合理?

对于同一个驱动力,为什么不同情况下参与对象和交互流程不一样?

如何确定?

其实,这些困难也正是面向对象技术中的困难。

     综上,我们知道在程序世界中,存在着过程论和对象论两种对立的世界观,并且其各有千秋,无法定夺孰好孰坏。

但是,对象论似乎更有助于分析规模较大的事物。

本文是探讨面向对象的,所以,在下文中,都会选择对象论作为世界观。

这种以对象为本的世界观,也是本文后续一切的基础和出发点。

真经第二章——抽象Abstraction

     “金、木、水、火、土元素,构成宇宙万物,并作为各种自然现象变化之基础——五行说”

2.1、导言

     上文探讨了世界观问题。

我们知道,要想真正理解面向对象,首先要用对象论去审视世界。

而在对象论中,万事万物的本源是对象,对象是组成世界的基本元素。

但是,要真正看透一个世界,只有基本元素是不行的。

     中国古代的朴素唯物主义哲学中,比较有代表性的是五行说。

五行说认为,世界的基本元素是“金、木、水、火、土”,但若说世界只有“金、木、水、火、土”,也是不成的,所以后续有云:

五行相生相克,相互交织结合,组成了大千世界。

虽然从现代科学角度看,五行说并不完全准确,但其有一点事非常正确的,那就是世界首先有基本元素,然后基本元素还要衍生出各种其它东西。

     在第一章中,我们说了在对象论中,对象是组成世界的基本元素,但这还不能构成真正的世界。

下面,我们来看看对象是如何构成和衍生出其它事物的。

2.2、类是怎么来的

     和真实世界中构成和衍生方式不同,程序世界中,最重要的衍生方式是抽象。

例如,众所周知的类(Class),就是从对象上首先抽象出来的概念。

下面我们看一看类是怎么来的。

     从哲学角度说,先有对象,然后才有类,类和对象是“一般和特殊”这一哲学原理在程序世界中的具体体现。

这可能和很多人的直觉不同,因为在具体写程序时,是先定义类,然后才能实例化对象。

在这里,我们是从哲学层面进行探讨,所以,对象是本源,类的概念是衍生。

为什么?

因为从认识论来说,首先有具体认知能力,才能有抽象认知能力,抽象认知能力是一种高层的,人类特有的认知能力,它使我们可以从大量具体认知中,舍弃个别的、非本质的属性,提取出共同的、本质的属性,是形成概念的必要手段。

     还是以住店的故事为例吧。

在我们的世界观中,那个故事涉及了五个对象,刚开始我们没有抽象的概念,而只是从具体认知角度对这五个对象进行认知:

首先是甲,他有头、有身子、有胳膊有腿,头上有眼睛鼻子耳朵,他还有个名字叫刘备,有个身份是顾客……除了这些数据,这个对象还可以做一些事情,可以吃饭、呼吸、喝水,还能给钱和拿钱……好的,一通认知后,我们对甲这个对象有具体认知了;然后,我们对乙进行认知:

他有头、有身子、有胳膊有腿,头上有眼睛鼻子耳朵,他还有个名字叫关羽,有个身份是顾客……除了这些数据,这个对象还可以做一些事情,可以吃饭、呼吸、喝水,还能给钱和拿钱……认知完了,接着是丙、小二和老板……当具体认知足够多后,我们发现一件事情:

这几个对象很相似啊,有相似的数据(但具体值可能不同),有相同的逻辑,于是,我们的抽象认知能力告诉我们,这五个对象很相似,可以看做一类东西,于是,我们给出一个类,叫“人”,并且认为这五个对象都是“人”这个类的具体例子,我们叫其为实例。

以后遇到类似的对象,我们都可以知道,这个对象属于“人”类。

 图2.1、“人”类的由来

     所以,类其实是抽象认知能力作用于程序世界的基本元素——对象后所衍生出来的抽象概念,是抽象思维在程序世界中物化后的产物。

当然,现实世界中每个对象都有无数的数据和逻辑,但在具体到程序世界时,我们往往只关心具体场景中相关的数据和逻辑。

例如,在住店场景中我们关心现金这则数据,至于这个人力气大不大无所谓;而如果上战场打仗,我们就关心攻击力和力量,现金就不重要了。

2.3、为什么要有类

     知道了类是怎么来的,那么类的作用是什么,我们为什么需要类呢?

     类可以帮助我们方便地认识和定义世界中的对象。

这个作用是显而易见的。

例如当今世界有60几亿人,如果不会抽象思维,我们每遇到一个人,都要认知一遍:

啊!

这个对象有眼睛,有耳朵,有鼻子有嘴,有胳膊有腿……要是真这样,世界也太疯狂了。

有了类的概念,我们就可以只记类的数据和逻辑,而对于具体对象,只要知道它属于什么“类”,一切就都知道了,所需要区分的只是不同对象的数据具有不同值而已。

     其实,这不仅仅是类的作用,我们进行抽象思维,就是为了这个目的。

2.4、总结

     这一章叙述了类的哲学本质、衍生过程和作用。

要记住,抽象是形成和衍生概念的基本方法,不只是类,后面的很多概念,都是通过抽象形成的。

所以,我们可以说:

上天只给了这个世界各种对象,但我们用抽象去更好地认识世界。

真经第三章——层次Arrangement

     “道生一,一生二,二生三,三生万物——老子”

3.1、导言

     上文提到,在对象论中,抽象是衍生概念的基本方法。

但是你有没有一个疑问?

所谓抽象,是对许多对象撇开个性,抽出共性,这样,抽象过程就不是确定的、唯一的。

例如,我们在看过很多对象后,发现有一类对象有四个轮子、有发动机、可以驾驶、是可以被意识反映的客观实在。

我们抽象出一个叫“汽车”的类。

这次抽象中,我们将有四个轮子看做了共性,但是,如果撇开这条性质,仅看后三条,摩托车、轮船、飞机都符合,于是,我们又可以抽象出“机动交通工具”类。

再把有发动机撇掉,自行车、脚踏三轮车,甚至马都符合,所以,又得出个“代步工具”类,最后,把可以驾驶也撇掉,只剩下“是可以被意识反映的客观实在”,如果这样,所有物质都符合,这样,就得出一个“物质”类。

     这下子困难就来了,你说我家的奔驰应该归到哪一类呢?

我家的奔驰和一只是不是一类东西呢?

如果从前三类看,当然不是,但是从最后一个“物质”类看,又确实是一类东西。

那到底哪一个对?

事情究竟是怎样的?

其实答案很简单:

归到哪一类都正确。

至于后一个问题,无法回答,因为这个问题单独问根本没有意义。

为什么?

     关键在于:

抽象是有层次的。

3.2、世界是一棵树

     上文说到,对象是基本,我们从对象上抽象出类。

但是,世界可并不是一层对象一层类那么简单,对象抽象出类,在类的基础上可以再进行抽象,抽象出更高层次的类。

所以经过抽象的对象论世界,形成了一个树状结构。

图3.1、抽象层次树示例

     图3.1展示了一棵抽象层次树的示例。

不要怀疑,在对象论中,经过初步抽象思维加工后的世界就是这样样子。

本来,世界只有各个具体对象(最底下紫色文字表示的层次),这是第0层,是一切抽象的本源和起始,然后,抽象思维作用其上,抽象出初步的类,然后在既有类和对象的基础上可以再进行抽象……如此归纳下去,最终整个世界归结于树的根节点:

本体。

所谓本体,即万物之源、万物之本,是哲学层面上最高层次的抽象。

在这里,我们将其看成是一个特殊的类,作为抽象层次树的根。

     千万不要小看了这棵抽象层次树,如果能参透其中的奥秘,就能明白很多面向对象中的玄机,而且很多问题就都迎刃而解了。

这种抽象层次树理论也是后续诸多内容的理论基础。

例如,OO中重要的概念——继承(Inheritance)和多态(Polymiorphism),如若探究其哲学本源,就是从这里来的。

     下面,对这棵树做一些必要的说明。

     I.这是一棵单根树,最顶层“本体”为唯一的根,最下层叶子节点为基本对象。

一切中间节点都为类。

     II.越往上的类抽象层次越高,具体度越低,其内涵越小,外延越大;越往下的类抽象层次越低,具体度越高,其内涵越大,外延越小。

说明一下,所谓类的内涵,是指类对属于自己的对象的说明力度,而外延是指类能包含的具体对象的总和。

例如,家用电器这个类,其内涵是使用电作为能源并完成特定功能的家用器具,各个电冰箱、洗衣机、电磁炉、游戏机、DVD机等都在其外延之内;而娱乐家用电器这个类,作为比家用电器更低层次的类,其内涵除了“使用电作为能源并完成特定功能的家用器具”外,还要是具有娱乐功能,其内涵明显大了,但外延却缩小了,只包括了各个游戏机、DVD机等对象。

     III.抽象层次树不是从根部向下长的,而是从叶子节点向上归纳生成的。

     IV.某一个叶子节点所代表的对象可以归入所有其祖先结点所代表的类

     V.直接问两个叶子节点属不属于一个类没有意义,而要指定抽象层次才有意义。

例如在较低层,一辆宝马属于汽车,而一只苍蝇属于昆虫,不是一类。

但如果指定在较高层比较,两个都属于具体物质,属于一个类。

     VI.我们定义,如果一个节点CNode非叶子节点也非根节点,那么在哲学意义上,这个节点继承于其父节点PNode,并且说PNode是CNode的泛化。

     VII.我们定义,如果一个节点CNode非叶子节点也非根节点,如果强行将它看成其任何一个祖先节点ANode,并当做ANode使用,那么在哲学意义上,叫做多态性。

3.3、总结

     先说明这么多了,随着后续内容的深入,还会有更多丰富的内容进来。

例如,后面会看到,所谓的“里氏代换原则(LSP)”,在哲学本质上不过是在这棵树上所加的一条限制规则,而“面向接口编程”、“低耦合、高内聚”、“依赖倒置”等一系列耳熟能详的短语,归结到哲学上也只是这棵树的一些精化。

     另外,看了上面的理论,我想本章开头留下的疑问也已经烟消云散了吧。

     再提示一遍,这棵树非常重要,得其精髓,就能理解诸多OO中概念、原则和方法的本质。

后续讨论中,抽象层次树理论将作为重要的理论基础。

真经第四章——继承Inheritance

     “子类型必须能够替代掉其父类型——BarbaraLiskov”

4.1、原来是先有儿子才有父亲

     这一章我们讨论继承(Inheritance)。

     我们先看一看继承在哲学意义上时怎么来的。

对象论的世界观认为,世界的基本元素是对象,我们将抽象思维作用于对象,形成了类的概念,而抽象的层次性形成了抽象层次树的概念。

接着,我们就可以定义:

在抽象层次树上,除根节点和叶子节点外,任一节点CNode非严格继承其所有祖先节点所组成的集合中的任一元素,而CNode严格继承其父节点PNode。

     继承概念,看似简单,若深入思考,却隐藏众多玄机。

首先,继承描述的实际是抽象层次树上祖先节点与子孙节点的关系,但我个人一直不赞成使用继承(Inheritance)一词来描述这种关系,而推荐使用泛化(Generalization)一词。

为什么呢?

因为我们已经知道,从哲学和认识论角度来说,是先有对象,然后有类;先有子类,然后有父类,是一种自底向上形成的体系。

而继承一词,明显带有自顶向下的暗示,因为往往是先有爷爷、有父亲继承爷爷、然后才能有儿子继承父亲。

这样,就容易让人误解成是先有父类才有子类。

所以,为了更好的体现继承的哲学本质,我更倾向于使用“泛化”代替“继承”。

当然,由于继承一词已经被普遍使用和接受,接下来我还是会沿用继承一词,只不过希望各位时刻牢记,其实是先有了子类,才从子类泛化出父类。

     当然,当父类被抽象出来后,可能还会有新的子类加进来。

但是,当初父类一定是从某些子类中泛化出来的,而不会是凭空突然出现的。

4.2、继承的作用

     探讨了继承的本质,然后我们来探讨继承存在的意义。

一切存在的东西都是有意义的,否则就不可能存在。

注意,这里的“意义”是中性词,指事物存在的原由,不要理解成褒义。

     我们需要继承这个概念,本质上是因为对象论中世界的运作往往是在某一抽象层次上进行的,而不是在最低的基本对象层次上。

举个例子,某人发烧了,对其他人说:

我生病了,要去医院看医生。

这句简短的话中有一个代词“我”和三个名词“病”、“医院”、“医生”。

这四个具有名词性的词语中,除了“我”是运作在世界的最底层——基本对象层外,其他三个都运作在抽象层次,在这个语境中,“病”、“医院”、“医生”都是抽象的,他并没有在医院里拉着某个医生对别人说:

我生了这个,需要去这里看这个。

但是,本质上他确实是生了一个具体的病,要去一个具体的医院看一个具体的医生,那么在哲学上要如何映射这种抽象和具体呢?

就是靠继承,拿医生来说吧,所有继承自“医生”类的类所指的所有具体对象都可以替换掉这里具体的医生,这都不影响这句话语义的正确性。

     所以,继承的哲学作用就是:

规定了抽象与具体之间的可映射性。

形式化一点说:

设G(c1,c2)意为c1非严格泛化自c2,I(c,o)意为对象o属于c的外延,其中c1,c2,c均为类,o为对象。

那么,c可在哲学语义上映射成o,当且仅当o∈{o|I(c,o)}∪{o|I(c’,o)且G(c,c’)}

4.3、开放-关闭

     如果你讨厌看形式化的东西,那么上面蓝色文字不看也罢,但是,有一条原则你一定很感兴趣,那就是著名的开放-关闭原则(OCP)。

     开放-关闭原则(OCP):

软件实体应该可以扩展,但不可以修改。

     为什么忽然扯到OCP呢?

因为,OCP正是上文讨论的哲学原理在程序世界的具体表述。

我们来对比看一下,到底OCP是个什么意思。

     还是上面看病那个例子,什么叫可以扩展?

就是说,因为在某个抽象层次是进行表述,就不能把话说死了,不能全是这个、那个的把每个对象都指派明白。

如,那句话改成“我的右脚扭到了,要去北京航空航天大学医院去看胡青牛医生”,这句话就没有扩展性可言了,所有话都说死了,你如果去的是北医三院或临沂市人民医院,那么语义就不对了,而如果找的不是胡青牛而是华佗或扁鹊,语义也不对了。

为什么无法扩展?

因为所有点都指定了具体的对象。

     而原话“我生病了,要去医院看医生”则扩展性很大,因为只要不违反可映射性定义,映射到任何符合条件的对象都正确。

扩展性和灵活性大大提高了。

所以,“可以扩展”四字从哲学上其实是要我们在设计和开发软件时提高抽象层次,不要总在具体对象层面上进行处理。

这下,你明白为什么说OCP可以提高软件的可扩展性和灵活性了吧。

     再来说说“不可以修改”,因为如果随便乱改,那就天下大乱了。

还是医院那个例子,“医院”这个类所映射到的对象,一定是治病的地方。

如果这东西随便改,例如明天“医院”和“食堂”的概念对换了,那麻烦了,我们所有人都要改,要把两个概念从脑子中对换过来,全世界的书、报纸、Internet……凡是依赖这两者进行表述的地方都要改,那不是天下大乱么?

软件世界中也会发生这种牵一发而动全身的问题。

所以我们提倡设计好的类一定要“对修改关闭”。

     以

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 英语考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1