Smalltalk 与面向对象编程

Smalltalk 与面向对象编程

在读书时我们专业有一门课程叫做《面向对象程序设计》,时隔多年,我已经记不清具体的内容了,只记得整个课程都是再教 C++ 编程语言的各种特性,在考试时有一道题目是问面向对象编程的三个特性,当时看到这道题非常兴奋,因为我已经背了很多遍了 —— 封装、继承、多态。

后来做 iOS 开发,接触到了 Objective-C 编程语言,刚看到「消息发送」这个概念时感觉非常别扭,不就是方法调用嘛,为什么非要说成是消息发送呢?后来了解到了更多的 Objective-C 的一些特性,比如 Runtime 的动态机制、Meta Class 等,当时也只是感觉这门语言设计的非常优雅、自洽,但是还是不理解「消息发送」与「方法调用」的区别。

从去年开始公司就一直在酝酿 SaaS 业务,春节期间对 SaaS 技术架构做了解时看到很多人在谈 Less Code 以及 Low Code 这些概念,为了弄明白这些东西就去了解了一下软件开发的历史,在查阅资料时看到很多人都提到了 Alan Kay, 于是找了一些 Alan Kay 发的论文,才意识到面向对象编程这个概念的起源及其重要性。当然,也终于明白了为什么 Objective-C 设计了「消息发送」机制。

很庆幸有这段经历,因为这段经历重塑了我对计算机以及编程的理解。

一、Smalltalk 的诞生

要了解 Smalltalk,必须从计算机说起,因为软件都是运行在计算机上的。软件在计算机上是怎样执行的?为什么需要编程语言?当然,即使弄不明白这些一样是可以编程的,但是如果能弄明白,则可以以一个更全局的视角审视那些看起来理所当然的事情,并从中开拓出新的思路,进而创造出更有价值的事物。

计算机 —— 用作计算的工具

计算机是对 computer 一词的翻译,其实在计算机这种机器出现之前,computer 所指的是「计算员」这个职业,尤指是那些受雇于天文台、勘测等领域进行计算的人。在 18 世纪初,数学用表的出现极大地提高了计算的效率,在数学用表没出现之前,计算是一件非常困难的事情,有了对数表、三角函数表这种通用数学用表则大大加快了计算乘、除、开方、角度以及面积等的计算。在 18 世纪后期出现的用于各个领域的专用表,比如海员的航海用表、天文学家的星表、建筑师的土木工程表,对经济的发展起到了巨大的作用。而这些表,都是由「计算员」编制而成。

但是计算员手工制表这种方式比较容易出错,而且枯燥乏味,英国一位叫 Babbage 的数学家发现了这个问题,并先后设计了差分机和分析机,这样就可以用机器进行复杂的数学计算了,但是由于制造这些机器投入成本过高,英国政府没有提供足够的支持,所以 Babbage 所设计的机器并没有真正的被制造出来。后来 Babbage 的儿子将差分机残片捐给了哈佛大学,20 世纪初期在哈佛读博士的 Aiken 在做论文时需要求解一组非线性微分方程,于是提议制造大型数字计算机,后来在实验室里看到了差分机的残片,让 Aiken 产生了浓厚的兴趣,将自己视为 Babbage 在 20 世纪的继承者。在 Babbage 的名为《一个哲学家的生命历程》的自传有这样一段话:

如果有人没有被我的经历吓倒,而且可以基于不同的原则或更简单的机械方法,成功制造出能体现完整数学分析执行过程的机器,那么我将自己点的名誉留给他又有何妨?因为只有他才能完全领悟我努力的本质以及结果的价值。

这个理念可以贯穿计算机发展的整个历程。

后来由 IBM 提供资金,Aiken 和 IBM 的工程师制造出了名为「哈佛马克一号」的顺序控制计算机,并开始为美国海军舰船局提供服务,成为计算机史上的里程碑。但是在二战期间,对计算的需求大幅提升,现有的模拟设备以及机械计算机都无法满足战争的需求,当时一个经验丰富的百人规模的计算团队需要工作一个月才能编制出包含 3000 条弹道数据的射表,由于缺乏有效的计算,大量新研制的武器无法有效部署。直到后来,在宾夕法尼亚大学摩尔电气工程学院担任助理教授的 John William Mauchly 提议制造一种电子计算机来解决这个问题,开始 ENIAC 项目,并在后期邀请到了 John von Neumann, 也就有了一直沿用至今的冯诺依曼体系结构。

至此,计算机的主要作用都是作为一个数学工具提供数学计算。

个人电脑 —— 智力放大器

如前文所说,在二战结束之前计算机一直都是一个计算工具,主要的用户是具备一定专业知识的工程师和科学家。而有那么一波另类打破了这一点,他们认为计算机可以帮助所有人提升智识,应该是一个人人都可以使用的工具。

给这个理念提供最原始灵感的是 Vannevar Bush —— 一位工程师、发明家、计算机技术的先驱,在二战期间负责美国的科学研究与发展办公室(Office of Scientific Research and Development)。二战结束之后,Vannevar Bush 写了一篇叫做 "As We May Think" 的文章,发布之后引起了很大的反响。

在文章的开头 Vannevar Bush 提到孟德尔的生物进化法则有几代之久都不为人所知,只是因为他的书没能被能够掌握并发展它的人看到,大量真正有意义的成果由于没有后续积累而丧失了,出版物已经大大超出了人们使用它们的能力,所以应该有更好的方式对知识进行记录、存储以及检索。Vannevar Bush 认为在严格的数学逻辑基础之上,将能开发用于日常事务的逻辑应用,这绝对是一个开创性的想法,要知道那时候还是用打孔卡作为输入方式让计算机执行计算的时代。最后,Vannevar Bush 提出来了 MEMEX 的设想,MEMEX 是一个机械化的个人图书馆,采用缩微胶片进行资料的存储,通过代码进行索引,在键盘上敲一下代码就会自动的将对应的资料投影到桌面上,另外还提出了「索引」的概念(超文本的原型),这样任何资料都可以随意的选出来,并且可以快速地找到相关资料,可以比较有效的扩展人类的记忆。

MEMEX

Vannevar Bush 并没有制造出来 MEMEX,但是正如 Babbage 的差分机一样,为其他研究者和思想家提供了灵感。其中一个就是 Ivan Sutherland, Ivan Sutherland 在读博士期间开发出了 Sketchpad —— 一个绘图程序,也是今天我们所熟知的 CAD 以及图形用户界面的原型。在这之前还只能通过打孔卡和计算机进行交互,Ivan Sutherland 的 Sketchpad 开创了人机交互、计算机图形学领域。

Sketchpad 还只是用于绘图,远没有发挥出交互式计算机的价值,但是在那个科学技术蓬勃发展、嬉皮士文化兴起的时代,先驱们在政府的资助下把计算机推向一个又一个高峰。其中影响最大的是 Douglas Engelbart, 在 "As We May Think" 和 Sketchpad 的影响下,Engelbart 构想出计算机可以作为全新的信息工具,并在斯坦福成立了增智研究所(Augment Research Center),带领团队研发出 oN-Line System, 这个系统直接促使了个人电脑的出现,因为这个系统的所有设计在日后都成为了今天个人电脑的基本组件,如鼠标、图形界面、位图显示、文本编辑、超文本,在 1968 年被称为 The Mother of All Demos 的演示中,面对仍然依靠打孔卡和打印机终端并依旧把计算机当做数据处理器的旧世界,Engelbart 在身后大屏上演示了只在科幻小说中才存在的新系统,并且超前的使用了类似今天的视频会议这种协作方式。

The Mother of All Demos

Engelbart 的 oN-Line System 演示虽然很成功,但是并没有得到大规模的使用,一个原因是 Engelbart 是个伟大的计算机专家,但并不是一个好的管理者,团队核心人才不断的离开,导致无法持续的进行开发;第二个原因是 oN-Line System 是构建在分时系统上的,分时系统指的是多人共用一台计算机,一台计算机可以连接多个终端,不同的用户通过终端来使用计算机,因为那时候计算机成本很高,但是这样无法让用户获得最好的体验;第三个原因是 oN-Line System 的使用门槛比较高,Engelbart 对工具的高效使用有自己独到的见解,因为工具的使用会影响人的行为和思想,而这些高效使用的方法是有一定的门槛的,但是 Engelbart 认为为了能够高效的使用工具,付出一定的代价去学习如何使用工具是值得的。

和分时系统计算机阵营对立的是个人电脑阵营,在个人电脑阵营里最知名的是 Alan Kay, 他认为每个人都应该有一台属于自己的计算机,也就是个人电脑。虽然 Alan Kay 很欣赏 Douglas Engelbart 的发明,但是 Kay 其实和 Engelbart 具有不一样的世界观。Kay 认为 Engelbart 的发明是一个动态的工具,在 Kay 看来这和 IBM 所制造的官僚气十足、非人性化的大型机系统没有本质的区别。而 Kay 认为应该是创建一个动态「媒介」,这个动态的媒介可以是一个编程以及解决问题的工具,也可以是一个交互式的数据存储工具,也可以是一个文本编辑器,也可以是一个通过绘画、制作动画和音乐的媒介,这个动态媒介可以成为其他所有媒介的「元媒介」,有了这个「元媒介」,任何人都可以通过 Smalltalk 来创造出新的工具,比如音乐生成工具、绘画工具、医院管理系统,成为新的媒介,和官僚气十足的工具相比,Kay 的理念被称为「思想的自行车」,可以随意骑到任何地方,没有任何轨道的限制,基于这样的理念,Kay 和团队制作出了 ALTO.

Kay 认为,个人电脑应该是人类的智力放大器,而 Smalltalk 则是这个放大器的软件系统。

二、面向对象编程的 Smalltalk 系统

在继续阅读之前最好先忘掉你现在所知道的操作系统、软件以及编程语言。

Smalltalk 是什么

Smalltalk 是什么?大部分人对这个问题的回答是「Smalltalk 是一个编程语言」,这其实是一个大大的误解,Smalltalk 远不只是编程语言。前面提到了 Alan Kay 对个人电脑的看法,基于这样的愿景,Kay 所在的 LRG(Learning Research Group) 设计了 Dynabook —— 一个类似 iPad 的手持设备,这个设备包括一个高分辨率的显示器、支持视觉和音频沟通的输入输出设备、共享信息的网络连接以及 Smalltalk 系统,所以 Smalltalk 是 Dynabook 的软件部分。用我们现在对电脑组件的理解,Smalltalk 对应的是操作系统,但是跟我们现在所认识的操作系统又不太一样,Smalltalk 允许用户自定义这个系统。而这个「自定义」跟我们现在常见的对系统进行自定义又不一样,现在我们一般所说的自定义指的是装个软件、换个主题,这里所说的自定义指的是由内而外的对系统进行自定义,不只是自定义外在表现,还可以自定义内部逻辑。

LRG 的目标是让用户创造性的使用 Dynabook,如前文所说的对「元媒介」的解释,任何人都可以通过这个「元媒介」创造出新的媒介。一般的软件开发环境是:编程语言的作者创造一个编程的环境,程序员通过这个环境进行编程,开发出应用给非程序员用户使用。而 Smalltalk 远不只是这样,Smalltalk 的思想是即使是非程序员也能够将程序员开发出的应用或者组件加以修改或者组合起来,从而创造出符合自己需求的应用,另外任何人都可以直接修改 Smalltalk 系统的代码对整个系统进行自定义,系统的所有逻辑都是直接暴露给用户的。

在没了解这些历史之前,我无法想象得到 Smalltalk 和个人电脑之间是有关系的。了解后才知道,正是在 Alan Kay 对个人电脑的愿景下才设计出了 Smalltalk.

Smalltalk 编程环境

在介绍 Smalltalk 语言特性之前,我们先来看下 Smalltalk 的编程环境是什么样的,因为和现在的开发工具相比,Smalltalk 最独特的是它的编程环境。前面说 Smalltalk 类似我们现在所认识的操作系统,这个说法只是为了让方便大家理解,但是实际上和操作系统的定位还是不一样的。

Smalltalk 更准确的定位应该是一个工作台,这个工作台首先有一个「台子」,也就是我们今天所看到的 GUI, 用户在这个台子上可以使用基本的工具,如果觉着这些工具不好用就可以自己调整一下,也自己制作工具,甚至可以改装一下这个台子。

在这个工作台里面最基础的工具是编辑器,没有编辑器就无法使用 Smalltalk, 因为 Smalltalk 是一个可交互的实时系统,什么是可交互的实时系统?这个概念是和批处理系统相对应的,前面有提到在计算机刚出现时是专门用来做计算的,其工作模式是启动之后通过操作按钮、纸带或者打孔卡将要执行的计算输入到计算机,然后计算机开始执行,开始执行之后就无法对计算机做的事情进行调整了,除非停下来,这个过程有可能需要几天的时间。

打孔卡

而在可交互的实时系统里,计算机所执行的操作是可以随时根据输入指令执行相应的操作的,在 Smalltalk 编程环境内,可以随时用编辑器打开代码进行编辑,编辑完之后可以立即执行编辑后的代码。

相比其他的开发工具,Smalltalk 编程环境最大的特点就是「无模式」。用过 VIM 的应该都知道,用 VIM 打开一个文件后,如果像要进行编辑需要先输入字母 i 进入编辑模式,对于 VIM 来说只有两个模式,使用起来还比较方便的,但是在那个时代出现的编辑器模式是非常多的,所以用起来很麻烦。除此之外,在 Smalltalk 出现之前,打开一个应用就只能做一件事情,想要做其他事情就得退出去打开另一个应用,所以如果想要实现在操作一个应用时调起文件浏览器选择一个文件是无法实现的,Alan Kay 在 Smalltalk 中设计了重叠窗口的方式解决了这个问题,也就是我们今天所看到的,可以同时打开不同应用的多个窗口,这些窗口相互重叠,可以根据需要激活对应的窗口,而且在切换的过程中不会丢失任何信息。所以虽然 GUI 并不是 Alan Kay 发明的,但是 Kay 结合了前人的设计思路,设计出了现代化的 GUI.

Smalltalk 窗口结构

关于无模式不只是体现在 UI, 还体现在更底层的设计思想上,在更底层的设计里,使用 Smalltalk 和用 Smalltalk 进行编程是没有区别的,也就是说,使用工具和创造工具是一样的,所以也不存在编程模式和使用模式之间的区别。这个思想体现在很多细节之处,比如无论在什么地方,只要选择一段文字,点击鼠标右键就可以弹出一个菜单,菜单里面其中一个按钮是 'do it', 点击之后就会执行所选中的文字,另外,也可以随时查看任何一个对象的状态。所以用 Smalltalk 进行编程是一种探索式的编程方式,任何时候都可以对内部状态进行查看,任何时候都可以修改任何一个对象的状态。

关于这一点,有个非常具有历史意义的事件可以证明,当年 Steve Jobs 带着 Apple 的同事一块去 PARC 参观,Larry Tesler 和 Dan Ingalls 演示他们做的成果,Jobs 看了后说不太喜欢一块块的滚动,并提议能否改成平滑的连续滚动的方式,Dan Ingalls 想了一分钟,然后改了下代码,系统就变成了平滑的连续滚动,震惊了 Apple 来的这些参观者。

Smalltalk 的 doit 按钮

这样设计的思想是将 UI 的目标从「使用功能」转变为「边做边学的环境」,「边做边学」是一种教育思想,强调的是通过实践来学习,Alan Kay 在设计个人电脑时一直将让儿童可以使用并且可以作为儿童的教育工具作为首要考虑的因素,在 Kay 看来,如果一个儿童本来就是使用电脑进行学习,那也没必要再去教他该如何使用电脑了。Kay 所设想的是不管是儿童还是成人,在使用个人电脑时就是在使用 Smalltalk 这个集成环境了,所以也根本就没必要通过教用户学习编程语言、算法之后来教用户编程。

Smalltalk 和面向对象编程

在编程领域和「面向对象编程的本质是封装、继承、多态」一样流行的另一个说法是「程序等于数据结构加算法」,而 Smalltalk 编程语言的设计思想恰恰相反。「程序等于数据结构加算法」这个说法的问题在于数据和处理数据的过程是相互独立的,而以这种思路设计大型系统会让系统的复杂度大大提升。在 Alan Kay 设计 Smalltalk 时首先考虑的是如何降低系统的复杂度,为了达到这个目的,Alan Kay 发明了面向对象编程。

其实真正第一个实现了面向对象特性的编程语言并不是 Smalltalk, 而是一个叫做 Simula 的编程语言,但是是 Alan Kay 发明了「面向对象编程」这个概念。这个概念的起源是在 1967 年有人问 Alan Kay 在做什么时Alan Kay 回答说「这是面向对象编程」。

Smalltalk 编程语言的设计思想是所有我们可以描述的事情都可以通过「行为构造块」递归组合来表示,这些行为构造块将其状态和处理过程隐藏在内部,并且通过消息传递进行通信。这里所说的「行为构造块」就是「对象」,也可以将对象理解为一个个微型电脑,每个微型电脑都有各自的职责,由无数个微型电脑组合为一个大型电脑,就像无数个细胞组成一个生物体,并且不管这个「电脑」有多大,其基本思想都是一样的,而如果将程序分为数据和算法,则每一部分都不是完整的,所以这种递归组合的设计思想有很强的适用性。

类似「对象」的设计思想其实早在 Ivan Sutherland 开发 Sketchpad 时就已经在使用了,在 Sketchpad 中每一个图形都是由一个对象来表示,这个对象里包含这个图形的所有数据和操作方法。

instances generic block

另一个采用了类似思想的是当时美国空军设计的 Burroughs 220 文件系统,当时需要在机器间复制文件,但是那时候还没有我们现在所说的操作系统和文件系统的概念,所以设计了将文件分为三部分的方案,第三部分是是实际的数据记录,第二部分是包含了知道如何获取数据记录并进行复制的指令,第一部分则是指向第二部分中指令的指针。

B220 file system

这两个设计都对 Alan Kay 产生了一定的影响。

到这里我们可以看出面向对象编程的两个最基本的特性:封装和消息传递。除此之外还有一个基本特性,那就是「延迟绑定」。 在一封邮件里 Alan Kay 也解释了自己对面向对象编程的看法:

OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.

延迟绑定指的是对象内部的实现可以在运行时进行修改,而且不会破坏整个系统的其他部分。这个特性其实是和封装直接相关的,在面向对象编程中被封装的对象之间是相互隔离的,在极端情况下,即使对象内部 crash 了也不会影响整个系统。另一个极端的设想是系统中的对象可以被另一台电脑所接管,而不影响系统的运行。其实实现了 actor 模型的 Erlang 就是这样设计的,所以其实真正的面向对象编程语言是 Smalltalk 和 Erlang 这类,而不是我们现在普遍使用的 Java 或者 C++.

三、Smalltalk 的衰落

即使 Smalltalk 有诸多有意义的创新,而且有很多一直影响到现在的设计思想,但是在现实场景中已经很少可以看到 Smalltalk 的踪影了,ECMAScript 标准的作者之一 Allen Wirfs Brock 在文章 The Rise and Fall of Commercial Smalltalk 里面总结了自己的看法,以下是对这篇文章中结论的翻译:

1. Smalltalk 不只是一个编程语言,它是一个完整的个人计算平台。但是当一般人能够支付得起的能运行 Smalltalk 的个人计算硬件出现的时候,其他对硬件要求更低的平台已经主导了个人计算生态。
2. Xerox Smalltalk 是用来做试验的,没有严肃到可以被广泛使用或者可靠的应用部署。
3.在生产环境使用 Smalltalk 需要很大的工程团队,在 1980 年代后期没有财大气粗的大公司愿意做这种投资,除了 HP 和 IBM,这种本来可以帮助 Smalltalk 在生产环境使用的大型计算公司,选择了另外一条路。
4. 那些希望将 Smalltalk 变得更强的小公司需要找到一个商业模式来支持这么大的工程努力,最明显的是企业应用开发市场。
5. 要想打开这个市场,需要为客户的一个重要问题提供一个解决方案,这些企业没弄懂的一个问题是如何从「绿屏幕」迁移到具有时尚外观的富客户端应用。
6. 有一些公司曾经相当成功的将 Smalltalk 引入企业市场,但是那些苛刻又变化无常的客户和 Smalltalk 公司高度的聚焦在他们对富客户端的承诺。
7. 因为这种聚焦,这些 Smalltak 公司在 1996 年对 web 浏览器的突然出现以及其在企业中的使用完全没有任何准备。在这时,Sun 作为一个比这些 Smalltalk 技术驱动的公司大非常多的公司,花费了大量精力将 Java 作为 web 和桌面客户端的解决方案来推广。
8. 企业将开发工具的采购从 Smalltalk 转移到可以承诺基于 web 或者 Java 的解决方案的公司。
9. Smalltalk 的收入大幅下降,聚焦在 Smalltalk 技术的公司失败了。
10. 在市场上失败的技术很少能够复活。

四、结语

编程语言可以分为两类,一类是由各种委员会所共同制定的「特性的集合」,另一类是由个体设计的「风格的结晶」,很明显,Smalltalk 属于后者。五十多年过去了,当时和 Alan Kay 一块设计个人电脑的有些已经不在人世了,信息技术产品也经历了一轮又一轮的发展,而现实却正如 Alan Kay 所说:电脑革命还没有发生。未来会怎么样?还会有像 Alan Kay 一样的个人英雄出现吗?这很难说,让时间来告诉我们答案吧。

五、参考资料

  1. The Early History Of Smalltalk
  2. Byte Magazine Volume 06 Number 08 - Smalltalk
  3. Dr. Alan Kay on the Meaning of "Object-Oriented Programming"
  4. The Forgotten History of OOP
  5. As We May Think
  6. John von Neumann
  7. John Mauchly
  8. Sketchpad: A man-machine graphical communication system
  9. Learning-by-doing
  10. What is the difference between Alan Kay's definition of OOP and Carl Hewitt's Actor Model?
  11. The Computer Revolution Hasn't Happened Yet
  12. The Rise and Fall of Commercial Smalltalk
  13. 如何看待Erlang之父Joe Armstrong觉得OO编程很烂?
  14. 面向对象编程的弊端是什么?
  15. 睡鼠说:个人电脑之迷幻往事
  16. 计算机简史
发布于 09-06

文章被以下专栏收录