从过去编程语言的历史中,我们可以看出编程语言是在不断试错的过程中发展起来的。有很多编程语言已经消亡,仅仅在历史中留下了它们的名字,但其中所包含的思想,却被后来的语言以不同的形式吸取和借鉴。
例如,SNOBOL的字符串处理功能,可以说是现代脚本语言基本功能的祖先。此外,20世纪70年代由美国麻省理工学院开发的一种名为CLU的语言中迭代器的概念,也被Ruby以代码块的形式继承了下来。
从编程语言的进化过程来看,一个显著的关键词就是“抽象化”。抽象化就是提供一个抽象的概念,使用者即便不具备关于其内部详细情况的知识,也能够对其进行运用。由于不必了解其内部的情况,因此也被称为“黑箱化”。
一些古老的编程语言,例如BASIC就没有实现充分的抽象化。虽然它提供了用于过程共享的子程序这个概念,但是子程序只能通过编号来调用,而且不能传递参数。由于“赋予名称”是抽象化的重要部分,所以说它的抽象化是不充分的。近代的编程语言中,都可以为一系列过程赋予相应的名称。
然而,仅仅将过程进行抽象化还远远不够。几乎所有的过程都需要进行一定的输入输出操作,而并不是与数据无关的。因此,在下一个阶段中,对数据进行黑箱化就显得非常重要。刚才我们提到的CLU,就是数据抽象化出现早期的一种语言。
在数据抽象化的延长线上,就自然而然产生了面向对象编程的概念。所谓对象,就是抽象化的数据本身,因此面向对象和数据抽象化之间仅仅隔了薄薄的一张纸。在现在的21世纪编程语言中,面向对象已经是常识了,最近几乎所有的语言都或多或少地提供了面向对象的能力。当然,其中也有一些语言故意不提供对面向对象的支持。
随着抽象化的不断深入,程序员即便不去关心内部的详细情况,也可以编写出程序。人类一次所能掌握的概念数量是有限的,有说法称,大部分人一次只能驾驭7±2个左右的概念。这样一来,如果能够让问题的处理方式更加抽象,也就可以解决更复杂的问题。
受摩尔定律的影响,社会对于软件也提出了越来越高的要求。人类社会越来越依赖计算机,因此就需要开发出更多更可靠、更便宜的软件。
在讲述软件开发的一本名著《人月神话》中,作者弗雷德里克·布鲁克斯写道:
无论使用什么编程语言,生产一条基本语句所需要的工数几乎是一定的。
也就是说,如果要描述同样的算法,A语言需要1000行,B语言只需要10行的话,只要采用B语言生产效率就可以提高100倍。
可能有人会觉得“这太扯了吧”。打个比方,用Java和Ruby描述同样的算法,语句行数相差2倍多也不稀奇,如果是汇编语言和Ruby相比的话,也许能产生100倍甚至1000倍的差距。
能产生这样的生产效率差异,正是抽象化的力量。抽象度高的编程语言不必描述详细过程,从而可以用简短的代码达到目的。和抽象化程度的差异相比,变量名称、有没有指定数据类型之类的都只能算是误差级别的差异而已。