第17本:《代码的未来》
要去西南出差了,却从自己的书架上和Kindle中找不出感兴趣的书来,临出发前去老 SUN屋里寻摸一圈,选中了《代码的未来》这本书。选中它的原因有几条:Ruby之父写的书,作者是日本人,日本人写的书一般比较实用、也想了解一下 Ruby、翻目录时发现有Go、Dart、CoffeeScript、Lua几个新语言的对比分析、老SUN说网上对此书评价不错。
飞机上看了一路,一口气读了前2章,90多页,对各种语言中的关键特性分析得相当到位,对语言的发展历史有了概括性的了解。出差后白天忙工作,晚上 把剩下的部分快速读完了,后面三章的内容对我来说吸引力就不够了,可能是技术性太强了,我们不会研究到这么深,只会去用别人写好的现成的框架。
第一章 编程的时间和空间
一开始作者从编程的本质入手,编程就是创造出一种人类和计算机都能够理解的语言(编程语言),并通过这样的语言将人类的意图传达给计算机,这样的行为就叫做编程。自然语言的歧义性太强,将来的用户界面肯定是全面的语音输入应该没有问题,但用语音把问题全部说出来,交给计算机去实现,现在看来还是相当有难度,假如将来实现了,那么程序员是不是要下岗了?还是都转入到更底层的代码的编写中去?
编程是一项创造性的工作,能够按照自己的意愿来创造世界,正是编程的最大魅力所在。想起高中时录入的几行BASIC代码,能够完成繁琐的计算,就想着自己编写一个小游戏会是什么情况呢?从而爱上了编程这项工作而一发不可收拾。
计算机语言的发展与摩尔定律也有非常大的联系,但计算机的算法改变得并不大,特别是一些古老的基础算法仍在大量使用。摩尔定律现在基本还有效,但 CPU主频的提高已基本到了极限,将来多核技术、内存容量增大、硬盘向SSD转变将会成为主流。我们的程序和算法需要如何适应这些变化呢?
这时想起当孩子小的时候,我启蒙性地让她看了看LOGO语言,让她操纵小海龟在屏幕上画出奇妙的图案,她确实感觉非常神奇,但对动手创造新的世界并 无太大的乐趣,可能女孩子的天性并不喜欢这些东西吧,难怪女程序员如此之少。我也不想强行给孩子灌输什么编程技术,毕竟软件开发仍是一件非常辛苦的工作, 还是别让孩子整天面对代码过日子吧。
作者也大胆地对未来进行了预测,IT技术变化日新月益,5年就会发现很大的变化。价格下降、性能提高、容量增大、带宽增加,而且这些项都是按指数关 系发展的,这些构成了IT技术预测的基础。在这些增长方面,存储容量的增大好像更快,而数据传输速度增加并没有那么快,这些发展的不平衡也会左右我们的未 来。
编程人员的思路果然离不开编程,作者采用极限编程XP的思路来预测一下未来。当把几项指标都调到极大,世界会是什么样子?
计算机价格低得跟白菜一样,现在的智能家电已经看出一些趋势了。将来的世界肯定布满了芯片,物联网看来真是大势所趋。地板是智能地板、手表是智能手 表、灯是智能灯、杯子是智能杯子、智能箱子,这些都在出现,将来的术语肯定不再使用“智能”这么俗的字眼,默认就是带计算机芯片的设备,便地都是计算机 了,看来程序员事情更多了,任务更复杂了。
计算机性能非常强会发生什么?将来我的笔记本配置会是1024核?多核CPU并行编程肯定要有新的发展,如果哪项编程语言有这种特点,应该是需要重点关注的语言。可能作者把Go语言排在比较靠前就是这个原因吧。
容量非常大?我的笔记本电脑会配置1EB硬盘?不,硬盘已经没有了,内存与硬盘已经合2为1了,因为内存也已经是白菜价了,配置1TB内存?其它东 西都存在云端了,没必要管什么容量问题了,因为带宽不成问题,从网络上读写10G数据也是几秒的事情?malloc()你就尽情地分配个八维数组吧,别去 管什么内存溢出之类的异常,哈哈。现在以SSD为基础的数据库系统和大数据分析技术已经出来了。
网络带宽1Gbit/s?计算机刚问世时,那是一个中央集权的时代,一台大型计算机,周围只有一些终端。当人手可以有一台计算机时,出现了C/S系 统。当WWW浏览器在全世界普及时,B/S方式的中央集权开始复辟。现在JavaScript在浏览器上大行其道,实际上又是C/S换个马甲复活了。如果 B/S是趋势,那你配置那么强大的个人电脑又有什么用处呢?不,每台电脑本身也是网络云计算中的一个节点,你必须提供计算资源,才能访问别人的服务?
第二章 编程语言的过去、现在和未来
2.1编程语言的世界
这里提到了打孔纸带、巴贝奇的差分机、女程序员Ada、第一台计算机ENIAC,至于到底谁是真正的第一那是历史学家的事了。计算机语言主要介绍了FORTRAN、COBOL、LISP、SNOBOL语言,然后讲到了当前的主流语言。
100年后的编程语言会是什么样子?变化不大?使用编程语言来编程的这个行为已经不存在了?发明了更高抽象度写法的编程语言?反正俺是看不到了。
20年后的编程语言是什么样子?肯定会在多CPU协作和多机分布式处理方面更加强大。当前的线程编程模型实在太让程序员痛苦了。
2.2 DSL(特定领域语言)
外部DSL是由专用的语言引擎来实现的DSL,可以高度自由的定制,但学习成本比较高。 YAML、JSON、正则表达式都可以称为外部DSL。XML非常通用,但描述冗长,不适合阅读和程序编写,将来会如何改进?
内部DSL则寄宿在某一编程语言的基础上,这样就不需要再学一门新的语言,宿主语言的语法等都可以拿来使用,节约了大量的程序开发时间。
实际上设计一堆API的过程,就是一种设计DSL的过程。
我也曾经想把工区底图和剖面程序DSL化,核心程序员开发好组件库,其他程序员只需要这样写就行了:
a = Basemap.New
a.AddImage(image, 0, 0, 1, 1)
a.AddSurvey(...)
survey.Hide
SeismicLine.Show zxcVolume inline 200
......
可惜在C#里实现内部DSL还是相当辛苦,只能暂时用API了。
作者认为Lisp、Smalltalk和Ruby适合用作内部DSL的语言,这可能与它们的元语言编程特性有关吧。
DSL 设计的构成要素:上下文、语句、单位、词汇、层次结构,这些概念我还暂时领会不了。
2.3 元编程
用程序来编写程序就是元编程Metaprogramming。这时又想到了数字油田中整天都说到的元数据,存储这些元数据固然重要,但脱离应用的元 数据肯定收集不上来,必无生存之地。如果元数据和元编程都实现了,程序员获取数据的逻辑应该就是像well1.GetWellLog(“AC”)这样?你 既不需要写SQL,也不需要写ORM映射关系,也不需要写实体类,写起来是方便了,但好像学习起来难度更大了。
在Java和C#中主要都是通过反射Reflection来获取和变更程序本身的信息,而Ruby的元编程相当强大,可以用几行代码生成100个方法,而在Java和C#中就只能通过编写专门的代码生成器了。
Lisp中的程序是用S表达式来表示的,其程序和数据是完全等同的, 所以元编程已经深深融入到Lisp中了。
元编程很强大,但也不能用得太多,否则理解源代码就很困难。
2.4 内存管理
垃圾收集GC的三种方式:标记清除、复制收集、引用计数。引用计数方式的原理和实现虽然简单,但缺点也很多,因此最近基本上不再使用。想想Qt中的内存管理也是采用引用计数,让程序员去决定何时增1、减1真是一种痛苦。
新的垃圾收集算法有:分代回收、增量回收、并行回收。
还有一位IBM的学者将物理学上的大统一理论(Grand Unified Theory,简称GUT)用于垃圾收集,统一为跟踪回收和引用计数。
2.5 异常处理
现在的高级语言都有异常处理机制,让程序员可以更方便地处理异常。传统的用特殊返回值的方法,容易让原来正常的程序被错误处理代码所埋没。
Java 的检查型异常强制让编译器检查异常,有时确实不方便。异常之所以被称为异常,本来就因为它很难事先预料到。明知如此,还非要在代码中强制性事先对异常做好声明,以避免产生编译错误,这实在是太痛苦了。
Ruby中的ensure、rescue和retry参考了Eiffel语言的保留字。
2.6 闭包
学Haskell语言时,我以前认为闭包Closure就是指高阶函数,可以把函数当参数传递给函数。
C语言中函数指针的最大弱点是无法实现对外部局部变量的访问。能够对外部变量进行访问(引用、更新),是闭包的构成要件之一。
第三章 编程语言的新潮流
在这一章中作者主要介绍四种编程语言Go、Dart、CoffeeScript和Lua。看到这里我打开了TIOBE关于软件编程语言的排行榜(截止到2014年11月),Go语言排名在20名之外(排名46),Dart排名22,CoffeeScript没看见,可能合并在JavaScript中了,Lua排名41。
Java稳居第2,JavaScript跃居第7,Ruby有点下降,处于第18名,而发展最快的R和Swift没有出现在作者的书中。
3.1 语言的设计
静态类型的语言编译期间就能发现更多的BUG,更容易阅读和理解。而动态类型语言的优点在于其简洁性和灵活性。
鸭子类型Duck Typing:如果像鸭子一样走路,像鸭子一样呱呱叫,则它一定是一只鸭子。
3.2 Go(排名46)
可以称之为现代版的C语言。声称为New(新的)、Experimental(实验性的)、Concurrent(并发的)、Garbage- collected(带垃圾回收的)、Systems(系统级)的语言。作者最看好它,可能主要是因为它内置支持并发编程,再就是它系出名门吧。
3.3 Dart(排名22)
Dart想取代JavaScript,但后者已经拥有了大量用户,看来Dart的前途并不光明。
3.4 CoffeeScript
JavaScript被投入了大量资金进行不断发展,其速度已经越来越快。既然JavaScript地位越来越重要,能不能既不抛弃 JavaScript,又克服其缺点呢?CoffeeScript就是这种思路,它的编译器实现上就是JS写成的,CoffeeScript程序会完全编 译为JS代码去执行,其发展值得期待。
3.5 Lua(排名41)
Lua重点在嵌入式领域,以轻量、高速和响应快为特色。
第四章 云计算时代的编程
从这一章开始,读起来兴趣不大了,简单了解几个概念吧。
4.1 可扩展性
从简单的二分法查找,讲到散列表和布隆过滤器,又讲到了分布环境中的DHT(分布式散列表)、Roma(键值存储数据库)和MapReduce。
4.2 C10K 问题
C10K是Client 10000 Problem的缩写,指“在同时连接到服务器的客户端数量超过10000个的环境中,即使硬件性能足够,依然无法正常提供服务”。epoll、libev和EventMachine,这些就不明白了。
4.3 HashFold
不感兴趣。
4.4 进程间通信
看Ruby 实现的网络服务器代码是相当的简洁,以后有机会可以一试。
4.5 Rack 与Unicorn
不感兴趣。
第五章 支撑大数据的数据存储技术
这章已经超出了我的理解范围,列几个术语吧,CAP、NoSQL、MongoDB、OD Mapper、VoltDB、memcached、Redis。
第六章 多核时代的编程
这章中提到了UNIX中的管道功能,真是相当的优美和强大,相比之下,Windows中的管道却是通过临时文件模拟实现的,相当的垃圾。
其它关于非阻塞I/O、node.js 、EventMachine的内容暂时在我的兴趣之外。
关于进程间通信,作者提到了ZeroMQ,是一种为分布式应用程序开发提供进程间通信功能的库。有机会可以一试。