Rust 语言团队邀请嘉宾 Felienne Hermans 来分享编程心理学[1],通过这个课程来了解一下,语言在设计的时候如何做决策也是不错的。并且对于 Rust 的学习也是有帮助的。
“Felienne Hermans ,来自荷兰莱顿大学社会学教授,编程心理学是她所教授的研究生课程之一。 国内好像没有这样的课程,搜到一个编程心理学兴趣小组(PPIG),成立于 1987 年 :https://www.ppig.org/ 已经举办了 32 届年度研讨会了,最新的一届是 2021 年。感兴趣的可以看一下。
因为搬运国外视频太麻烦,所以就以图文方式,给大家分享一下。Felienne 教授的 PPT 有个习惯,就是当出现熊猫的时候,就是她想让学生做某事或思考某事的时候。
接下来,你需要代入 Rust 语言设计者的角色来阅读此文。
演讲正文
第一个思考练习:给你两种编程语言 A 和 B,研究哪种语言更好的方法是什么呢?
说明:你可以把 A 看作是 Rust 1.x 版本,B 看作是 Rust 2.x 版本,你会用什么办法来判断哪个版本更好?你可以自己思考一下。
图片中这种雕像位于 Felienne 教授的学校里,上面雕刻的是荷兰语,意为:「只要通过测量就能知晓」。她想表达的是,只有通过测量事物才能了解事物本身。Felienne 教授说,这是她在接触的学生或编程领域的大多数人互动时看到的思维框架,大家都想通过一些数值来衡量一些东西,这就是基本的科学方法。
科学方法基本步骤就是:
- 观察客观事物(Observation)。比如,看到一个苹果掉落。
- 将其理论化(Theory)。对所有的苹果向下掉落的行为进行建模,形成公式或定理之类。
- 设立假设(Hypothesis)。某个苹果将会掉落,准备去验证。
- 进行实验(Experiment)。这个苹果确实掉落了,验证完毕。
但今天的主题是编程语言设计,Felienne 教授会告诉你除了这种常规的科学方法之外的其他方法。这些方法不一定需要测量和实验。
其实,科学也分不同的类型,比如自然科学与社会科学、人文科学等。
自然科学研究,主要的研究对象是针对「自然产物」,比如宇宙天体、微观粒子、引力等,你可以理解为是「神造之物」。
而社会人文科学类,主要的研究对象是人们生产的东西,比如考古学、音乐、社会关系、书籍、包括编程语言等等,你可以理解为是「人造之物」。
这两类都是做科学研究。但是对于自然科学来说,前面讲到的科学研究方法是非常适合的,因为你对整个宇宙没有什么控制权,你只能通过这种测量、理论化、假设和验证的方式去探索。
但是社会人文类科学则不太适合这种方法。比如说医学实验,人们可能知道他们在做实验,然后他们可能会受这种心理影响而表现出不同的方式,所以需要进行双盲实验才有可能符合模型。但是微观粒子,该是什么样就是什么样。
假如你做考古,你该设计什么样的实验呢?你去考古现场挖出古人使用过的工具,你观察它,然后思考它的用处,然后形成你的理论,到此你的研究就结束了,你并没有机会真正回到过去去验证你的假设。所以对于研究人造的对象来说,就不会像研究自然生成的对象那么严谨。
以上两类不同的科学研究方法,对于编程语言来说,其实后者更加适用。因为编程语言也是人造的。
现在想象一下,假如有两类人,一类喜欢JavaScript,另一类喜欢 C#,那么该如何对其进行测量才能比较两门语言的好坏呢?
你也许能很快想到一些可以测量的指标:
- 代码行数
- 代码执行时间
- 代码开发效率
- 代码中的 Bug 数量
- 语言社区规模
- 语言生态系统的规模
当然,还有很多可以比较的点。但大多数人第一个比较关心的就是性能基准测试(Benchmark)。
性能基准测试是在一些论文和编程语言中非常常见。除了代码执行效率,也包括编译效率。
当然,越快越好。但是,也有人认为代码行数越短越好。
但是为什么代码行数越短越好呢?
拿生命游戏来说,如果用 Cpp 实现,你可能需要 200 行代码。但是你用 APL 语言的话,你用一行代码就能实现生命游戏。
“APL语言(APL,A Programming Language的缩写)是一种表达能力很强的会话语言。应用范围包括数学统计、事务经营、信息检索、报表生成、财务预算等。它也可用于模拟计划管理、图形处理、正文编辑、计算机辅助教学等方面。APL的特点是,语法规则简单,运算符丰富,表达式简练,并包含多种构造和处理数据的运算符。它在数据加工和矩阵计算上特别有效,不过程序员具有较高的数学素养。 一行 APL 代码实现生命游戏:life←**{↑1 ω∨.∧3 4= /,¯1 0 1∘.⊖¯1 0 1∘.⌽⊂ω}**
对于有些人来说,一行代码就是比200行代码更好。所以,这里的好与坏,取决于你的偏好。
那么,我们还可以做其他方法来测量吗?
我们还可以在互联网上提出问题,让程序员们来选择自己喜欢的语言,看哪门语言喜欢的人更多。比如 Stackoverflow网站每年举办的投票,喜欢 Rust 语言的人就很多。
上面说的这三种测量方法,都可以看作是一种定量研究。
无论你是进行性能基准测试,还是测量代码行数,亦或是进行网络调研,最终你得到的还是一些具体的数字。这有点像是自然科学研究。
但我们也可以从人们使用该语言的体验进行衡量,比如询问一些人,使用 C# 时的一些感受,是快乐呢,还是困扰。同样,也可以这样来询问人们使用 JavaScript 的感受。然后拿着两种语言的感受进行对比。但是这个过程是定量的吗?
Felienne 教授认为,通过设定具体的分析方法可以将这个过程变成定量研究。比如可以设定一些具体的分数来衡量使用感受,就能得到人们对于两种语言使用感受的评分数字。所以,是不是量化研究,要取决于分析方法。
当然,我们也可以越来越远离定量研究,比如,你可以问人们,为什么喜欢 javascript?然后你就会得到各种各样非常不同的答案,这些数据则更难用数字去衡量。这属于定性的研究。
定性研究也可以通过多种方式,比如调查问卷、日常问答、针对性采访等等。但是定性研究的目标不是得到一个具体的测量数字,而是想要去理解他们的偏好。
Felienne 教授认为编程语言设计中的一个误区就是,想要定量地确定哪种语言更好。但我们不仅要知道哪个更好,还要知道为什么它更好。想象一下,能否测量 C# 程序员比 Java 程序员快乐半个百分点呢?如果能做到这点,是不是就能把C#中这部分好的内容拿到 Rust 中呢?你只能通过定量的研究来获取这些数据。
如果使用开放文本来进行分析 javascript,一部分人群会从技术面来谈论他们的喜好。比如函数式编程、容易部署、无需编译、node.js 生态等等。
而另外一些人会从社会面角度来讨论,比如他是因为朋友使用javascript 而对这门语言产生了好感。再比如有些人喜欢 Haskell 语言,其实和Haskell 语言无关,他们可能只是喜欢这门语言的人很酷?或者是因为 Haskell 有严格的类型让你能避免 javascript 中可能的错误。
还有一些人可能会关注编程的环境,比如在什么平台编程,linux 还是 windows,或者,如何进行编程。
所以,对于编程语言设计人员,需要让不同的研究人员,更加系统地对人们的喜好进行独立分类,然后比较。这种研究术语社会科学研究,因为从某种意义来说,我们是在面对不同的人群来询问他们的感受。
也有一种人文科学研究方式,虽然在编程语言设计中不是很常用,但是在软件工程中比较常用。就是阅读一些源码。
这种研究方式在语言学或历史学中叫做「语料库分析」,你可以在其中查看一些数据语料库,来看人们谈论问题的方式。比如你想了解女性或男性在文学作品中的讨论方式有什么不同,就可以通过阅读文学作品来达成这个目标。
阅读代码也是相似的一种过程。你可以通过 GitHub 来达成这个目标。GitHub 让编程语言设计人员根据人们编写的代码来做出关于 PL 设计的决策。
Felienne 教授推荐了一篇论文《对反模式在软件可变性影响的探索性研究(An Exploratory Study of the Impact of Antipatterns on Software Changeability)》[2]。这篇论文的作者们查看了 Eclipse 代码中,发现了反模式(AntiPattern)代码异味(code smell),他们发现几乎所有版本的 eclipse 中,带有反模式的类,比其他类更容易发生更改、问题和未处理的异常。
“反模式(anti-pattern)指的则是在实践中明显出现,但低效或有待优化的设计模式,是用来解决问题的带有共同性的不良方法。 程序开发领域,代码中的任何可能导致深层次问题的症状都可以叫做代码异味。
通过阅读实际的代码,可以在编程语言设计层面来避免很多反模式和代码异味。
Felienne 教授也谈到她自己参与合著的一篇论文,这篇论文是研究儿童编程教育可视化语言 Scratch 中,儿童使用什么样的变量名。在 Scratch 中,变量名中允许使用空格。这是 Scratch 一个有趣的地方,其他文本类型语言中不允许变量中存在空格。所以 Felienne 教授和这篇论文其他作者都好奇,儿童是否喜欢这个功能。她们可以通过询问儿童来进行分析,但是对于儿童来说,这可能是他们唯一知道的编程语言,他们肯定会说,“为什么不喜欢呢?”。所以,通过阅读儿童实际编写的 Scratch 程序才能发现他们是否真正喜欢变量中加空格。结论是,有三分之一的项目中的变量使用了空格,然后还有一些其他有趣的东西,比如字符串中孩子们喜欢加圆括号。
但是某一个时刻,孩子们开始使用 Python 或 Rust 这种文本语言,发现他们不能在变量名中使用空格了,也许会令他们感到困惑。
所以,作为 Rust 语言的设计者,要明白自己要做什么,并且需要什么样的数据。是定量的数据,还是定性的数据。比如你想了解一些语言特性,另多少人感到困惑,那就需要定量数据;如果你想了解这些语言特性为什么让人感到困惑,就需要定性数据。也可以通过 GitHub 中人们的各种意见,明白什么样的代码会产生什么样的问题。
总之,如果你想衡量一些对你有用的东西,你需要选择合适的研究方法。
小结
Felienne 教授分享了科学研究的不同方法,以及它们在编程语言设计领域该如何应用。选择一种合适的研究方法,才会事半功倍。
“前几天笔者在知乎上看到一个某大学的学生参加2019年社科中心的一项田野调查,收集云南省怒江农村残疾家庭的数据。当地人对他抱怨,他的调查问卷非常不接地气,无法反映出真实生活。但是他们老师却说,定量分析非常科学。但其实这种可能更需要定性分析吧。
这些方法其实对于我们学习 Rust 的时候也有帮助。因为编程语言都是人造的,包括 Rust,不是神造的。你不需要像搞科学研究那样对编程语言做定量分析式的探索性学习,比如,有的人学一门编程语言的时候,啥资料都不看,直接通过动手写代码的实验性方式来学习编程语言。这种方式其实非常低效。因为已经有很多资料来对 Rust 的语言设计、语法特性都有系统和详尽的描述,你只需要花时间先去了解一下,再动手写代码,其实可以做到事半功倍。
参考资料
[1]
编程心理学: https://www.youtube.com/watch?v=nrkVIq0ccII
[2]
《对反模式在软件可变性影响的探索性研究(An Exploratory Study of the Impact of Antipatterns on Software Changeability)》: https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.150.1292&rep=rep1&type=pdf