计算机程序的构造和解释

先来看一下前两天在Lambda the Ultimate看到的一篇文章。如果你不是程序员,可以不看下面的第二个引用。

戳程序: 为什么麻省理工不再教《计算机程序的构造和解释》

一篇博客; 是这么说的:

在纽约Lisp见面会上的这次演讲中,Gerry Sussman被问到为什么MIT不再教传说中的基于Sussman和Abelson的经典教案《计算机程序的结构和解释》(SICP)的6.001课程。Sussman的回答是:(1)他和Hal Abelson厌倦了教这门课(他们从80年代就开始教了)。于是在1997年,他们走进系主任的办公室,说:“我们不干了。你们看着办吧。”而更重要的是,(2)他们觉得SICP课程已经不能为如今的工程培养工程师了。Sussman说,在八九十年代,工程师们通过组合简单易懂的部件来构建复杂的系统。SICP的目标是为构造这种系统提供抽象语言。

今天,这种情况已经不复存在。Sussman指出,工程师们现在经常为复杂的硬件编写代码,而他们并不完全了解这些硬件(而且往往因为商业机密而完全不了解)。在软件层面也是如此,因为编程环境有各种功能强大的库,根据Sussman的说法,他的学生大部分时间都在阅读这些库的手册,来想办法将它们拼接在一起完成工作。他说,现在的编程“更像科学。你抓住库的一角,然后戳它。你写程序戳它,看看它能做什么。然后说,‘我可以调整它来做我想要的事情吗?’”。SICP的“综合分析”视角——用较小的、简单的部件构建一个较大的系统——变得无关紧要。如今,程序不是设计,是戳出来的。

然后,有个Hacker news thread,里面有个评论值得一提:

我们应该把什么认为是基础?

很好的问题,一个完整的答案对于评论来说太长了(不过倒挺适合写一篇博客文章,我现在就去写,因为这似乎是一个话题)。但我在这里对太长不看的版本现挂一下。

人工智能、机器学习、自然语言处理和网页设计都是应用领域,不是基础知识。(你列出的不是计算机图形学、计算机视觉、机器人学、嵌入式系统——都是应用,不是基础)。你可以用一天的时间把你需要的集合论和图论都学完。大多数人在高中时就已经懂了。你要的东西就没有多么复杂。你可以放心地跳过范畴论。你确实需要的是花一些时间在计算机程序是可以用数学方法推理的数学对象这个概念上。这是现在绝大多数人都缺失的部分,而且你的大脑要绕这些弯可能一上来有些棘手。你需要了解什么是不动点,以及为什么它很重要。你需要自动机理论,但同样,基础知识其实并不复杂。你需要知道图灵完备性,要知道图灵机基础上还有下推自动机和有限状态机。你需要知道图灵机可以做到下推自动机不能做的事情(比如解析上下文敏感语法),下推自动机可以做到有限状态机不能做的事情(比如解析无上下文语法),以及有限状态机可以且仅可以解析正则表达式。

你需要一些编程语言理论。你需要知道什么是绑定,以及有两种类型的绑定很重要:词法和动态绑定。你需要知道什么是环境(名称和绑定之间的映射),以及环境是如何链接的。你需要知道求值和编译的关系,以及环境在这两个过程中的作用。你需要知道静态和动态类型之间的区别。你需要知道如何将高级语言编译成寄存器转换语言。对于操作系统,你需要知道什么是进程,什么是线程,并行进程导致问题的一些方式,以及处理这些问题的一些机制,包括其中一些机制需要的硬件支持(例如原子检查并设置指令)。你需要一些基本的数据结构。你主要需要了解数据结构的本质不过是,让关联映射对特定情况下的特定操作,效率更高。

你需要一点数据库的知识。同样,你真正需要知道的是,数据库的本质在于处理随机存取存储器和非易失性存储之间的架构差异,而现在这些这些操作越来越少,因为这些架构差异也开始模糊了。就这样。

其实上面引用的文章里面两段话更多的还是面向开发者的,那么更简单来说,大人,时代变了。软件工程科学正在严格执行它的使命——降低开发的门槛。

之前有个概念叫TDD,测试驱动开发。而我参加工作以来,最直观的感受是,对于用户软件,我们小作坊真正践行的,也是TDD,不过不是test-driven-development,而是try-driven-development,我称之为尝试驱动开发。其实就是Yarden Katz博客里面讲的戳(poking)。当然了,不是说因为是小作坊所以在戳,人家也讲了,趋势就是戳。甚至往往戳都不戳,写个东西出来,看上去可以运行,那就可以了。别人我不知道,反正我是这样,跑一跑,能跑就万事大吉了,能应付多少边界情况,就看自己写的时候想到多少了,换句话说,听天由命,“问题出现我再告诉大家”。

SICP是关于如何实现抽象的一本书,它的核心是如何组织代码,实现建模,以及规模大了以后,逻辑的隔离。这里面最核心的是什么,是抽象本身是可以抽象的。我知道,抽象抽象这样的概念,可能太抽象了。举例来说,我们可以用1代表一个东西,可以是一个🍎可以是一个🍐,这就是抽象。而1 + 1可以用来代表吃一个🍎又吃一个🍎(我吃不下,我每次只能吃一个),则是抽象了的抽象。因为学加法的人只要学习数字是怎么相加的了,不需要再考虑为什么“可以用1代表一个东西”。你不需要学习皮亚诺公理也能掌握加法,丝毫不妨碍你加到本科毕业。

编程也是一样的。如果说SICP教大家如何抽象,那么教会了一批人以后,业界就会充分发挥抽象的威力,抽象到就像你造房子要打洞的时候,只需要找一个电钻,只要会装不同的钻头然后插上电按开关就可以了。所以几十年下来,软件工程的实践也变成了,抽象能力更强的人负责为能力不那么强的人抽象一部分逻辑,这是什么,这就是更高层次的抽象。这不再只是针对工程内容的抽象,而是针对工程本身,甚至是整个工程业界的抽象。所以从事软件开发的人往往不清楚他们使用的工具的原理,而这正是这些工具设计的初衷。

所以,现在只是为大家开发大家现在使用的软件,需要的能力要求其实并不高。我刚才举例子用的是造房子,这也是为什么软件工程师也叫工程师,工程师那可不就是造房子的嘛。当然了,读过《黑客与画家》的程序员可能会愤愤不平地说,编程是介于工程和艺术之间的1。殊不知,造房子本来也就是介于工程和艺术之间的,乡下搭小平层也是造房子,北京搭鸟巢也是造房子。就像建筑工程更多的是单一的造桥铺路等基础设施建设和民用建筑工程,编程更多的是要求快速交付的后台数据管理系统和面向普通用户的软件。如果接受了如今的编写程序约等于造房子这个事实,那么我再说几点我要说的,

所以如果你要杠,建筑工人会结构力学是不是对施工有好处;那肯定有,但是并不会起到决定性作用。如果你要杠,如果建筑工人会结构力学,是不是有可能在某个细节上的处理让本来可能断的桥不断;且不说这可能性有多小,就是不排除这样的可能,但是我们只知道断了的叫豆腐渣工程,不断的叫XX大桥,总之不叫建筑工人之结构力学之杰作。

所以我想说什么呢?我想说的是,就算不了解编程,大家可以很自信地瞧不起你身边的程序员,如果你之前以为他们看上去做着很厉害的事情,说不定其实简单得出乎你的意料;相应的,以后大家用到不好用的软件,不要骂程序员了,正如你家房子墙太薄不应该怪泥瓦匠,要怪就怪开发商不舍得花钱(小声:或者怪自己买房子之前没看清楚,或者怪自己没钱买在更高档的小区)!

当然了,只是说这个,我也没必要把原文贴出来,我真正想说的是,编程并不是造房子。是的,我上面说了一大堆编程就是造房子,现在又反过来了。因为下面的话是对同行说的,还是留点情面吧。两个人用两个电钻可以同时打两个洞,两个人同时用两个技术栈写一个功能,可能两个人都要丢了饭碗,合十个孕妇之力,并不能在一个月内把孩子生下来2,这就是软件工程的“人月神话”。虽然这个神话正在真的走上成为神话的路,因为比如说同一套服务端接口,两个人负责面向不同平台的客户端开发,往往不适用这个规则。但就是这样的例子,也被软件工程一直以来的梦想,多端运行制衡着,所以,还是谨慎乐观吧。

如果你问我程序员还要不要看SICP,那当然要看了,不管什么时代,又有谁能忍住《九阴真经》(请在黄蓉的指导下练习)的诱惑呢。

现在你要问我程序员该锻炼什么技能?嗯……学习。技能只是技能,学习是meta技能。学会了学习,可以学习所有技能。要怎么学会学习呢,要从简单的开始,先熟悉学习的这个过程,然后总结自己是怎么学习的。

比如有空的时候留心一下怎么看大门吧。就算学不会学习,转保安的时候可能会少点痛苦。再怎么说,技多不压身啊。

Footnotes

  1. 硅谷创业之父Paul Graham文集

  2. 人月神话 https://book.douban.com/subject/1102259/

Published

Tags

Coding