越过编程语言这道坎 ——《冒号课堂》读书报告
编程的世界里不乏很多技术上的牛人,但机器终究是为了人而存在的。读罢《冒号课堂:编程范式与OOP思想》,其中的细枝末节没有记住,但是这本书却引导我去思考怎样去驾驭自己的程序。现在的编程世界里“武功”百花齐放,让人应接不暇,但也许这些纷繁之后,他们的产生与发展乃至繁荣,都是世界上一些再最自然,最淳朴的一些道理。
1. 编程语言——舍本逐末
如果是编程范式是一种文化,那么编程语言更像是一种宗教——尽管它本不该是。每种流行的玉雅都有大批忠实的信徒,随时可能与其他的信徒发生宗教战争。
很多时候都会听到有人在争论编程语言的优劣,认为自己所崇拜的语言鹤立鸡群,但其实,过分拔高一种语言与磨砂语言之间的差别都是极端的观点,编程语言的发展从来都是一个不断完善,不断在满足人类抽象思维与机器理解能力之间平衡改进的过程。一门语言只有得到了大家的认可,才会有人使用,才会有人想到改进;一门语言,只有接受批判,才能催生更适合的语言。编程语言是在批判与赞美中逐步发展起来的。Stroustrup认为Simula太慢,BCPL又太底层,于是发明了C++;Gosling觉得C++用的不爽,于是发梦了Java;微软恼恨JAVA,于是请Hejlsberg发明了C#;Matsumoto用了两年多C++仍不顺手,于是发明了Ruby,在不断的批判中,我们的编程语言才变得五彩缤纷。但同时,C++之于C,Java之于C++,C#之于Java,都继承了前者的优点,是对前者的一种承认,一种赞美。我相信语言不是通过受欢迎度来衡量的,而是它能不能够满足需求。今天的编程语言排行榜上已经很难关注到汇编语言,但是在嵌入式开发中,如果要充分发挥硬件性能,还是会有很多人选择汇编。
任何语言都有独到之处和不足,对待一门语言,与其抱怨争执,不如扬长避短。编程语言不过是人驾驭机器的一把利器,而不应该是人围着语言团团转。
2. OOP生存之道
一个公司的成长,刚开始的时候可能只有最初的几个创建者,各自分工明确,公司运营也很健壮。随着业务的扩大,公司不断招募新的员工,原来的散兵游勇式的管理方式不再适用,于是公司会成立新的部分,安排管理人员。公司规模达到一定程度以后,管理者会发现需要一套完整的规则来保证公司的正常运转。一个健康的公司各部门一定是各司其职,相互协助,每个部门内部又继续分支。从管理结构上,公司就好像一颗枝干繁茂的大树,处在上一层节点的人不需要关心最底层的情况,只需要将任务分派到几个“孩子节点”就可以了。
其实现在流行的面向对象的编程模式与公司模型十分类似,或者说,面向对象的产生式编程模式发展的必然结果。每一个对象都可以比作一个部门,外界关心的只是对象的接口而不是内部实现,而对象内部为了实现复杂的接口又会出现功能上的差异,于是为了高效运作,为了节约成本,做了进一步的分工,出现了抽象,出现了继承、多态。
OOP是在命令式的基础上发展起来的,是对命令式的一次改进,它以数据为中心组织逻辑,将系统视为相互作用的对象集合,并利用继承与多态来增强可维护性、可扩展性和可重用性。
a. 抽象
同样类比到公司模型中,由于公司规模扩大,业务繁杂,因此需要一套高效率的管理模式。于是出现了产品部,销售部,人事部,后勤部等等,这种划分本身就是对事务属性的一种抽象,将他们归属到一个类里面,由这个类统筹管理,公司高层只要管好这几个类就可以了。抽象就是要去粗取精以化繁为简,由表及里以异中求同,软件设计者利用抽象来完成现实世界到虚拟世界的多对一映射。
抽象只能说是将任务做了一个分类,问题还是没有解决。在每一个部门,会有自己的软硬件设施等公共资源,部门内部如果事务比较复杂还会分成小组,各个小组公用这些资源,但完成不同的任务。其实真正完成的任务的是这些小组,但是现在他们有了能够实际管理他们运作的组织,而且可以共享资源,节约成本。在编程的时候,类的泛化,也就是类的继承其实就是完成了这样一个过程,子类继承了父类的接口或者实现等共享资源,同时也要完成自己的特定任务。
另外,现在的机器虽然性能十分彪悍,但是依然还是一个没有思想的机器,不知变通,静态语言都有严格的语法限制来保证机器的算法的正常执行,但是有些时候可能只是参数类型的变化就导致大量重复代码,有些时候我们需要完成的任务在有多种解决方案,需要根据特定的环境来选择。机器可以不知变通,但人可以。面向对象编程的另外一个重要特征——多态也就自然而然的出现了,不管是参数多态还是包含多态,都是让我们的静态语言能够虚实相生,静中有动。
佛语有云:一花开五叶,结果自然成。我想面向对象的编程并不是什么特别新奇的事务,而是在某个特定的时刻发现,当下最主要的矛盾不是人类日益增长的计算需求和落后的硬件性能之间的矛盾,而是繁杂的事件模型和落后的编程模式以及笨拙的机器之间的矛盾,在这种情况下,面向对象的产生也就不足为奇了。
3. 范式——驾驭代码的心态
学习编程如同练武,外练招法,内练心法。空有招式而无心法,则不能活学活用,不知变通,空有心法不会招式,只能是纸上谈兵。招法重形,心法重意。得形而忘意,无异舍本逐末;得意而忘形,方能游刃有余。很多初学编程的人会十分在意编程语言,掌握一门好的语言固然是一把利器,但仅仅掌握语言最多只能让学习者成为一个优秀的码农。
现在主流的编程语言多是命令式的,就是人告诉机器一个有序的指令集,这样的编程模式更符合机器的习惯而不是人的习惯,因此代码的执行非常的直接,但同时要求编程者以机器的思维来解决问题。但实际上,人是目标导向型的生物,人类思考的习惯往往不会像机器一样关注到算法的每一步。命令式编程算法是显性而目标是隐形的;声明式编程模拟人脑的思维,算法是隐形目标是显性的。由于现在的机器以冯诺依曼机为主,导致命令式编程几乎等同了机器编程模式。
在命令式范式发展的过程中,过去人们广泛采用了面向过程的编程模式,分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。,经典C语言就是这种模式,但是这种编程模式在任务比较复杂时对程序员的要求很高,于是人们发现了面向对象的编程模式。
但是,这并不等于二者之间有优劣之分,面向过程的代码执行起来更直接,更高效,面向对象解决问题的思路更清晰,更直观。当然二者也是相互渗透的,面向过程的编程中会引入结构化编程,相信它的对OOP的诞生也起到了巨大的启迪作用。同样,在面向对象的编程中,我们需要全局变量(static 关键字),需要回调函数来高效直接的解决问题,这些都是面向对象本身所欠缺的。
4. 让代码具有生命
这里援引“冒号”的一段话作为结束:
编程之时,你便进入自己创造的世界之中。这是你的世界,只有注入你的思想力,创造力和激情,它才又勃勃生机。你编写的岂止是代码,分明还有乐曲;你敲击的岂止是键盘,分明还有琴键;你运行的岂止是程序,分明还有世界。当优美的旋律奏起,整个世界都随之翩然起舞,一种莫可名状的满足是否会充溢你全身?
(Yue Wu,Oct. 20th, 2011, MC Group)