编程的未来

有一句话,我觉得对程序员是至理名言:编程未来的趋势是库,动态的脚本语言和虚拟机。这句话我一听就觉得很对,可是对它的领会(尤其是后半句话)却花了很久,现在也还在半路上。

我一直很喜欢C++的一个基本的设计思想,就是有些事情是语言该做的,更多的事情却应该交给库去实现。正是这种思想,使得C++可以应用于各种领域。语言应该给程序员足够的自由,从最底到最高层,从最机器的层面到最贴近现实的层面,然后,用这种语言,我们再来写库,用于各专有的领域。C++成为了工业标准,它写成的库可以被各种语言使用、绑定,它被用来写各种语言。任何宣传C++的没落的言论都是窄视的,它没有看到C++是今天的许多事情的一个基石。C++ 是静态语言所达到的一种极致。

C++与C的兼容以及对其规范化的推动,现在看来是做得再聪明不过的一件事情。时至今日,许多库依然用C 写成。C的生命力是C++成功的最重要的基石。在领略C++的无数美妙之处的过程中,我曾经以为C已经没落了,后来却在实践和更多的对源码(gcc和 Linux内核)的阅读中重新意识到C的永不消逝的价值。看到C里的OOP甚至 AOP的种种实现,正如看到SICP中用Scheme做的编译器时一样,我意识到,更轻小更简单的语言,却能允许人类智力的最完全的发挥,也在一定程度上明白了为什么Linus会说“C++ to C is lang cancer to lang”。很多C++里的东西,现在看来都很语法糖衣。然而,它最可贵的价值之一就在于,用一种语言,使我们学会了OO、多态和泛型的思维,同时也提供了一种对这些思维的描述。C++是设计模式最好的描述语言,我看到许多书用Java这种先天不足的语言来描述设计模式,就觉得别扭。

是的,我恨Java,这种感情与日俱增。虽然我一直都在关注和学习它的技术,包括EJB,Struts,Hibernate和Spring,并且《J2EE Development without EJB》一书使我对这门语言背后的技术有了更大的好感,再加上最近看到一篇文章尖锐地指出Java并不慢,但是,刨去了所有没有根据的偏见,使我憎恨这门语言的核心理由却无法被撼动。不记得谁说过,Java是他第一次学习一门新语言没有感到任何新的惊喜,没有发现新的思想。我还要加上后半句:“反而感觉到一下子丢了好多东西”。Java使OO的一切都变得不再美妙,使一切变得麻烦,这就是我们为所谓的简化付出的代价。C++庞大而精深,任何一个怕难的人都可以栖居于这个语言的简单部分,而让写库的人去充分使用这个语言的其他层面。有了编写良好的智能指针库和对其恰当、适度的使用,所谓的用一种语言来 “把程序员从内存管理的泥潭中解放出来”就相当可笑。程序员的不自律和不善用库没有任何借口。程序员之所以爱好编程,就是喜欢那种一切都可以做到,一切都可以掌控的感觉。静态语言不能丢失指针,不能丢失引用,程序员不应该对const &厌烦。为什么除了栈我们还需要堆?在你离开作用域的时候,栈会严格地帮你回收利用你用过的东西,但你却带不走自己用过的东西。有了堆,你可以带走了,你可以在应该回收的时候再放手。托管却使你完全失去了对一切的控制力,你不得不把东西丢得满地都是,等待机器人来捡你的餐巾。而且Java写的程序就使用的时候感觉,也常有内存释放的问题,也会崩溃。那么,当初何必呢?静态语言不应当放弃自己对内存的管理,自己束缚自己手脚。

Java 的流行的关键是,它对类库的相对统一的捆绑,它的用虚拟机跨平台,它的集成了多线程,它在Web方面和嵌入式方面采用的先进的技术和框架。这些构成了它的生命力,有人说它会消亡,那是不可能的。我不是看不到它的生命力,而是我一直宁可这些概念和技术是基于一门不那么丑陋的语言,尤其不能容忍喝 Java咖啡的人不知天高地厚地耻笑C++,而且对那些把Java称为初恋的程序员感到极度恶心。我无法相信,发明Java的人会是真正资深的C++程序员,他们应该是在早年C++艰苦创业时受了苦的程序员。顺便说一下,我相当明白为什么大家会把这些技术堆到Java身上,Java语言自身的简易(从编译实现的角度)和内存托管功不可没。一切都是时机和真实的历史进程惹的祸。

在看了D&E之后,我对Stroustrup相当佩服,我佩服他在各种程序员的口味面前坚持住了自己设计语言的哲学,保持了语言的纯洁,使得C++的扩充并没有使自己走形,这不是任何人能做到的。举两个我最欣赏的例子:纯虚函数=0的语法,和后缀++重载的方式(operator++(int))。不过也可能有人对这个最不以为然。讲讲我最喜欢C++的一些地方吧:尽量保持少的关键字,善用运算符,有运算符重载(可惜还不够充分自由,要是有自定义操作符的功能就好了),有同名函数重载,有枚举,精心设计的构造和析构体系(就像栈一样让人放心),类的定义和实现分离,模板以及相应的泛型编程,有作用域的typedef以及traits技术,保留了强大的C预处理宏(学C++先要学会不用宏,然后学会善用宏,可惜define间较难相互利用),有指针和引用,有各种const,有名称空间,进行强类型检查却又保有隐式类型转换,有完全可以善用的多重继承,有精心设计的虚函数多态体系以及可爱的->,很多东西交给了库而不是捆绑入语言,这使得我们可以有较多选择。这里太多太多东西Java没有了,而以上每一样技术都是程序员的好朋友。C++自己的问题在于编译器的实现还不够完美。

应该说,没有使用过多个库/类库(尤其是开源库)的C++程序员不算C++程序员。各种通用用途或专有用途的库对于程序员的成长是非常有帮助的,它会培养程序员搭建编程环境,靠文档和例子迅速上手,用Hack解决各种Bug、移植性或依赖性问题,对库进行定制的能力,这些可是保持程序员在不断涌现的新技术面前屹立不倒的能力啊。由于库通常有各种语言的绑定,库也使程序员能迅速摆脱语言的束缚,只要有库,程序员的能力就不受限制。剩下的就是人月神话的问题了。我一直都在涉猎各种类库,他们的源代码就如同经卷,如果有足够的时间,好想像玄奘一样坐下来汲取它们的精华。

在C++之前,(从小学起)我用过 Logo,GWBasic,C, VB。在C++之后,很少再有什么语言能给我真正的惊喜,直到我大范围接触动态脚本语言。Bash是最初的关于脚本的惊喜,但现在看来,它太不脚本了,不够动态。后来用过或学习过,汇编(x86,一点PowerPC,现在正在学MMIX), Make, LaTeX, Matlab, ActionScript, JavaScript, Lex/Yacc, CSS/XPath, XML/JSON/YAML, Grapghiz, Metapost,Scheme,Squiril,PHP,Python,Ruby,Lua,Erlang 等语言,应该说各色语法都见过了,都有一段使用的时间,有些比较钟爱的语言还是在多个时期分别使用过,有反复的咀嚼和重新发现。

最近一段时间做了个网站(DHTML/CSS+LAMP+Ajax),加上对Prototype源代码的阅读,使得我对JavaScript有了重新的发现,同期的Ruby学习也令我惊喜不断,我向所有人推荐这两门语言,这两门动态语言,最适合打破C++给程序员的静态思维,PHP也不错,除了用它做网站后端,用来做零活也不错。相比之下,我还是不那么喜欢Python,有待将来重新发现它了。JavaScript对于函数的内部变量的处理方式(挂为函数的一个属性)和把函数当做普通变量的做法,使得它的函数既能当Lamda函数用,又能当(一个可以不断扩展的)类用,甚至可以当包用,相当伟大的设计。 JavaScript甚至发展出JSON作为数据共享格式,比XML好多了,我相信它将在分布式应用中发挥相当重要的角色。JavaScript和 Java根本是两种完全不同的语言,完全不同的两种思维范式,我从前对它有太多误解。由于JavaScript和C很像,所以掌握其使用不难,但Ruby 则将要求你习惯另外一种思考问题和书写语句的方式。Ruby中的迭代器是它最大的亮点之一,它对前一语句的返回值与{}块进行了相当具有启发性的使用。另外一个特别需要适应的思维是,这里没有强类型检查,只有duck-typing,即如果我们只需要一个对象像鸭子一样叫,只要这个对象能够像鸭子一样叫,我们就接受它是鸭子,不管它事实上是什么。我原先对动态语言的无类型一直不适应,这次使用时才充分意识到它的威力。Ruby很有更多美妙的地方,这里就不提了。

若干年前,有书推荐说,学了C/C++后,Java是相当合适的第二门语言。现在才知道大错特错。程序员的第二门语言应该是一门脚本语言,用来快速完成一些零活,也用于使程序员的思维灵活化。脚本语言的设计思路绝不能像静态语言一样,让语言更纯粹,事情让库做。脚本语言要内嵌许多常用的功能,不仅是通过核心库来提供这些功能,更是要在语言层面支持更方便的调用。正则表达式就是其中最起码的一个,数据库的访问、多线程也是相当重要的(且看Ruby的mutex.synchronize{})。

动态语言还有一个妙处在于eval(),我们可以动态地用脚本生成脚本的字符串,然后执行,这也是Bash当初令我惊喜的原因之一。自然,可以像访问一个关联数组一样访问创建过的变量、函数、类和Symbol,更是动态语言给程序员的最大自由。这两个功能,前者使我们能使用使用语言构筑的语言,后者使我们能够进入语言的元层面。前者建起来,后者挖下去。这样我们得以超出语言提供给我们的单一平面,有了第三个维度。

在文章的最后,简单地说说虚拟机吧。

从使用VMWare在各平台上调试程序,到使用各种模拟器玩游戏,再到使用模拟器进行嵌入式开发,虚拟机的重要性不言而喻。始终希望Fusion或者seamless的技术能够发展得更成熟——有了这种技术,我们可以在一个操作系统上无缝地使用另外一个操作系统上的程序。我可以装个真正的双系统,以其中一个操作系统为主操作系统,需要时不用重启可以调用另外一个操作系统中的程序,最关键的,是这个程序的运行环境,是真正基于那另外一个操作系统的,这样不会有Wine的尴尬,不会有VM的慢。在多核的情况下,可以有多个操作系统来分别使用一个核。这样的技术是可以实现的!只是还没有。如果有足够的内存,这样的技术就可以足速运行。现在的情况是,软件的开发跟不上硬件的发展,即使具备了相应的计算能力,却不能享受到这种便利。一种可能的设想是,不要把虚拟机建在应用层或者内核层之上,而是在内核下面,在BIOS和Booter之间,并像VMWare Tools一样,在应用层也有呼应,两相配合。Intel和AMD已经在CPU里对虚拟机做了支持,然而就使用它的KVM的性能表现来看,我还是比较失望的,可能是我没有恰当使用,或者KVM还在刚起步的发展阶段吧。还有Knuth的结合了各种计算机架构优势的MMIX芯片,目前还只有虚拟机,我希望这样的虚拟机能够硬件化,然而这样的事情,却要等待真实的历史进程了。

然而其实那句话所说的虚拟机,应该不是指这种虚拟机,而是指语言实现用的虚拟机。Chrome所用的JavaScript引擎V8,以及Mozilla的SpiderMonkey引擎,它们也是一种虚拟机,然而是属于动态语言的虚拟机,解释语言的虚拟机。这又涉及到自动状态机……对这些方面了解不多,就此打住吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章