如果你在试用了28种开源框架和69种eclipse插件后仍不清楚自己眼前的垃圾代码该如何“重构”,那么,你也许需要抽出一些时间,补习一下你曾经极度蔑视的、看起来没有任何“用处”的基础知识了...
[ 查看本指南所提及的书籍 ]
再教育?没错。依个人愚见,大多数中国程序员都需要接受一次有关程序设计语言的再教育,而Michael L.Scott所著的《程序设计语言——实践之路》则可以成为这次再教育中的最好读本之一。
在现代汉语中,没有什么词比“急功近利”更能体现当代程序员对于程序设计语言的期望和要求了——我见过太多太多只学会
了“Hello,World ”就打算独立编写企业级应用的速成者,我也见过太多太多刚掌握了一门面向对象语言的语法就宣称自己是OO专家的神仙级人物;在他们眼中,一本名为《某某语言入门》的教科书应足以取代《数据结构》、《编译原理》、《离散数学》等所有“高深”而“无用”的课程,而一名能熟练使用Hibernate或 Spring的Java程序员就足以成为一家小型企业的J2EE首席架构师了。
更为有趣的是,这些急功近利的“语言万能论”者一方面会把某种最流行的语言或类库当作克敌制胜的惟一法宝,另一方面却又丝毫不理会那些经过数十年的积淀才成为现代程序设计语言精华的,贯穿于语法、语义和语用等三个层面的基本理念和基本特征;这种做法就像是把一部夏利引擎、麦凯伦外壳的赛车开上了F1赛道,难免会在残酷的现实面前落得个鼻青脸肿的结局。
很显然,如果你对自己在实际工作中总是无法提高编码效率、无法改进软件质量的事实困惑不已,如果你在试用了28种开源框架和69种 eclipse插件后仍不清楚自己眼前的垃圾代码该如何“重构”,那么,你也许需要抽出一些时间,补习一下你曾经极度蔑视的、看起来没有任何“用处”的基础知识了。对于那些没时间重温大学课程的上班族来说,这种补习最好从《程序设计语言——实践之路》开始。即便不能把这本八九百页的“大部头”全部读完,你也至少能在阅读过程中明白三个看似浅显、实则微妙的“大道理”:
其一,语言必须与环境相结合,才能发挥出最大的功用。这里所说的 “环境”通常包括编译环境、运行环境和应用环境三个方面。举例来说,如果你打算仿照着某些开源框架的做法,使用控制反转和依赖注入技术消除代码中某些让人生厌的依赖关系,你一定会认真研习实现类似技术的语法特征,但你未必会主动思考以下几个问题:在编译层面,使用了这些语法特征的代码是否会影响到最终生成的目标代码质量?在运行层面,该如何组织这些语法特征,才能让使用了相关技术的可执行程序在支持废料收集的并发环境下有不俗的表现?在应用层面,这些旨在消除依赖关系的技术会不会破坏新、旧模块间的平衡关系,以至于我们必须花上大量时间改写原有的代码或接口才能保证系统的平滑升级?全面思考这些与环境相关的问题并不一定会改变你的抉择,但它却可以帮助你找到效率、可靠性和可用性之间的最佳平衡点。在此方面,《程序设计语言——实践之路》一书所使用的,将程序设计语言与编译原理、面向对象等知识综合起来、融会贯通的做法不但可以节省我们分类学习的大量时间,还可以训练我们从整体出发、多角度思维的方式与方法,其价值不言而喻。
其二,程序设计语言本身所具有的多样性可以成为我们提高软件开发水平的最佳指南。说到这里,我又想起了那些充斥在各大技术网站的,题为“某某语言比某某语言更强大”或“某某语言已死,某某语言必胜”的帖子。发表这些帖子的帖主也许并不懂得,程序设计语言的世界本来就是一个多样化的、五彩缤纷的世界,每一种成功进入应用、教学或科研领域的程序设计语言都有它值得学习和借鉴的地方。如果仅仅根据个人的喜好或是响应时尚的号召,就盲目地吹捧某一种语言并贬低其他所有语言,这样的帖子和那些频繁出现在Fans网站上的“爱死某某某,恨死某某某”的帖子有什么本质的不同?更为重要的是,如果我们能够在《程序设计语言——实践之路》的指下,真正懂得了函数式语言、数据流语言、逻辑式语言、冯·诺伊曼语言、面向对象语言等不同的语言类型在语法设计、编译器设计和运行环境设计方面的异同,我们就会惊讶地发现:Scheme语言的lambda表达式可以在C 语言中优雅、高效地解决诸如面向契约设计之类的复杂问题;Ada95语言中提供的同步和保护机制可以为那些使用Java编写的多线程应用提供重要的参考; Smalltalk语言与编译和运行环境的紧密结合则可以为我们设计可扩展的JavaScript宿主提供最好的借鉴……从这个意义上说,学习一种语言的意义绝不在于为自己增添一种求职和谋生的手段——真正善于学习的人总能从每种语言的设计和实现中找到许多可用于提高编程水平的关键特征。
其三,使用特定语言编写出来的代码是否优雅、可靠,这主要取决于程序员对各种基本理念和基本原则的认知程度,而不取决于程序员记住了多少复杂的语法特征或学会了多少流行类库的用法。正如《程序设计语言——实践之路》所说的那样,“典型的C 程序员都极少使用联合、多重继承、变动个数的参数,或者. 运算符”,但是,如果你了解了隐藏在这些复杂语法特征背后的东西——如内存空间的分配和寻址方式,复本式继承和共享式继承之间的关系,参数传递和求值顺序,动态方法约束和成员查找,等等——你就可以在需要使用这些语法特征的时候满怀信心地告诉自己:“嘿,这不过是某某原则或某某技术在C 语言中的表现形式罢了,我能搞定它!”反之,如果你不晓得与数据结构和算法相关的代码在编译、运行时必然存在的各种均衡与折中问题,即便你把C 语言的标准文档背得滚瓜烂熟,即便你可以默写出System.Collections命名空间中的所有属性和方法,你也会在体验过自己开发的软件与成熟软件之间的差别后大发感慨:“同样是使用C 语言,为什么我写的程序总会从头到脚散发着‘业余’的气味儿呢?”
关于程序设计语言的本质,Michael L.Scott是这样说的:“就像自然语言限制着人们解释和论述的方式一样,程序设计语言也限定了什么可以表达,什么不能表达,并对程序员能够怎样思考问题有着深刻而微妙的影响。”既然如此,我们还犹豫什么呢?与其后悔在学校中虚度了光阴,还不如马上捧起《程序设计语言——实践之路》这本书,接受一次有关程序设计语言的再教育呢!