SICP 101 - 通过代码看世界

本文是对 Structure and Interpretation of Program - SICP 一书导论部分的总结,作者提出程序员往往和三个对象相关:人的大脑、程序集合、计算机本身。SICP 使用 Scheme 语言来教授编程,Scheme 的英文含义正是“做计划”,编程的核心在于对现实世界的不断抽象,如果说艺术解释了我们的梦想,计算机则以程序之名在执行它们。

SICP - Structure and Interpretation of Program 《计算机程序的解释和构造》,这是一本关于程序设计的入门书籍,长年以来被 MIT 作为教材,被认为是此领域不可多得的好书。对于雇主而言,程序员应该担负起成功的、误差错的、完美的使用机器的责任。根据 Alan J. Perlls 的理解,作为程序员,责任并不是担负这一完美运行机器的责任,而是扩展这一领域,将其发展到新方向,并随时保持趣味性。关于计算的知识 —— 这些其他人也都能学到,不论是学会使用一门编程语言,写一个健壮的、好用的库,写一个前端后端编译器,甚至编写自己的编程语言和操作系统,数据库系统等。成功计算的钥匙并不掌握在某个程序员手上,我们需要掌握的并且应该掌握的,是一种智慧:看到机器比第一次站在它面前时能做的更多的能力,只有这样,才能够将它向前推进。雷军在“代码人生”中认为,“学会写程序并不难,只要下决心钻研,再精妙的算法都能被掌握,最难也最有价值的是找到合适的商业化的点子,用代码将其实现”也表达了类似的观念 —— 即程序反映了人对世界认识的抽象。

什么是程序员?Coder、程序员是从和程序打交道的角度来说的,但这一定义偏离了核心,Programming、Programmer 程序设计师,程序规划者才是更为确切的描述。和教育者、将军、减肥专家、心理学家和父母的规划类似,而和军人、学生等被规划的不同,程序员是对需求做规划的人,这里的业务(即程序具体用于什么,服务什么应用)并不重要,重要的是其性能,是否可以在构建大型程序时无缝衔接。总的来说,可以将程序员的工作划分为三个对象中:人的大脑、计算机程序的集合以及计算机本身

Programmer 更多是从“人的大脑”入手的,每一个计算机程序都是现实或精神中某个过程的一个模型,其位于人们的经验或者思维中,琐碎且繁多,人们只能部分理解它们(感觉到知觉的混沌过程,并非经过考察的逻辑分层抽象思维),因此,通过程序将脑中的模型进行模拟的过程也不是一次性的,而是不断演化的,随着我们对默认认识的不断深入、扩大和广泛,就不得不修改程序,直到模型达到亚稳定状态。一个模型接着一个模型,Programming 的乐趣就在于源源不断的扩大对于世界的认识,从感觉、知觉到思维的抽象,在增添、修改和重构代码时对于模型进行去魅、整合和修整,以更加自然、直接、健壮的反映对世界的抽象认识,以更加轻松的应对千变万化的需求。如果说艺术解释了我们的梦想,则计算机则以程序之名在执行着它们,程序设计语言、离散的符号和函数是画笔,而机器则是挥洒创意的画布,不同而是,程序是更具实用性的艺术。

当然,Coder 反映了程序开发不同的一面,即计算机是一位一丝不苟的工匠,其程序必须正确,但随着小东西成长为大程序,程序变复杂后就很容易出问题。从“计算机程序的集合”这个对象入手,我们需要开发出保证程序结构正确性的算法和惯用法,通过一些被证明很有价值的组织技术,将这些结构组合成更大的结构,用更接地气的话来说,就是软件工程,不同程序设计语言内置了较为基础的抽象方式:基于过程抽象的函数,基于数据抽象的对象,函数式编程、面向对象编程等等,此外还有领域内的,比如并发编程中的协程、Future/Promise、Async/Await,大型软件复用代码的设计模式等等。这些组织技术和惯用法让我们以不同的视角和方式处理程序集合,因而说,程序设计语言并不是一种简简单单对于计算机控制的工具,而是一种用来组织概念,进行程序化思考的方式,一个 Scala 程序员和一个 go 程序员对于同一过程的思维抽象和代码实现差异巨大,而这种差异对于外行或者混混沌沌长久使用某一编程语言的人来说却很难知晓。

最后,有必要从“计算机本身”这个对象进行思考,因为机器是程序执行的载体,虽然我们更倾向认为,代码主要是用来抽象业务的,主要目的是写给人看的,附带作用是能跑在机器上。虽然这一看法对于雇主们而言可能不好理解和接受。在一些全能工况下,需要关注计算机本身,比如程序执行速度,程序性能等,这时理解计算机运行原理以及程序如何操纵更低层次硬件的就非常重要。

“人的大脑”和“计算机程序的集合”这两个对象都涉及抽象,并非泾渭分明的,可以从一个简单的角度来进行区分:人的大脑这部分主要涉及业务以及伪代码表述和业务的统一抽象模型,而计算机程序的集合这部分则跟程序设计语言、类库的选用密切相关,涉及特定语言和框架下特有的对于代码的抽象和逻辑复用,比如 Java 面向对象封装(过程 + 数据融合的抽象),基于设计模式的代码组织,通过 IOC 和 AOP 框架实现依赖注入,Go 通过对 Struct 数据进行抽象等。

同样的,要看到“人的大脑”和“计算机程序的集合”之间密切的关联:作为 Programmer 的“人的大脑”对大多数人来说并没有那么有创造性,他们认为:计算机程序对个别具体用途而言却是很好,但是缺乏弹性。这句话的含义是,大部分代码都是为了完成某一特定需求而产生的,之后就再无用处,需要重新编写新的代码。但实际上,这恰恰反映了为什么“程序设计很容易成为一种表述理解肤浅、草率而就的思想”这一论断。如果程序被用来实现肤浅的思维和草率的动作,那么复杂性是无法进行控制的,将会爆炸性增长,即粗鄙和非精心设计的思维抽象“坏大脑”导致代码膨胀“坏代码”,软件很容易变得不可维护。因此,这个例子很容易支持我们的观点,即上述提到的“一个计算机语言不仅仅是让计算机去执行操作的一种方式,更重要的是一种表述有关方法学的思想的新颖的形式化媒介”,根据这个观点,可以推论:程序必须写的能够供人们阅读,偶尔的供计算机执行,而不是反过来。计算机革命是一种关于我们如何去思考的方式,以及我们如何去表达自己的思考的一个革命,计算为精确处理“怎么做”而非数学上的“是什么”的概念提供了一种框架。基于这种“怎么做”的框架,通过不同编程语言和工具提供的抽象机制以及我们自己创建的抽象去控制复杂性,才能够让程序设计真正的变为一种艺术而非工具

总的来说,“人的大脑”和“计算机程序的集合" 之间是互相影响,共同作用的,看不到不同编程语言和其抽象方式如何影响了我们思维的“门外汉”不理解后者,他们的思维不能或者从未有效落地。看不到技术是为业务服务的“呆子”不理解前者,他们无法认识编程的目的和本质,无法发掘编程艺术之美,也无法去发掘机器的更多能力,无法推动机器为社会服务和进步。从价值的角度来看,程序反映人对世界的认识是最重要的,而代码组织和特性利用则是次要的,虽然这深刻的影响了我们的思维方式,而让计算机程序运行则是最不重要的(相对而言),换言之,相比较 Run Code,更高层次的目标是 Clean Code,而最高层的目标则是 Known the world by Programming。

Reference:

https://www.bilibili.com/video/av8515129

https://cisco.github.io/ChezScheme/#get

https://groups.csail.mit.edu/mac/ftpdir/mit-scheme/#Download