「RustConAsia 2019」如何高效学习Rust

「RustConAsia 2019」如何高效学习Rust

RustConAsia 2019大会昨天刚刚圆满闭幕,趁热打铁分享一下我在首届RustCon Asia 2019大会上Topic的文稿,后续整个大会的录播视频也会逐步放出。

现场是一个二十分钟左右的演讲,但是文稿我稍微比现场分享丰富了点内容,做了一点补充。

以下是正文。


我叫张汉东,你也可以叫我Alex。很高兴能和大家齐聚一堂交流Rust,也很感谢大会组织者秘猿和PingCAP,能为我们提供这样的平台,让我感觉到一个更加真实的Rust社区。

我今天给大家带来的主题是《如何高效学习Rust》。


1. 首先我会做一个自我介绍

2. 然后会大家分享一下我对「Rust学习曲线高」的一些思考

3. 接下来给大家带来一个高效学习模型

4. 最后,围绕这个高效学习模型带来十条关于Rust学习的建议给大家做参考

我曾经做了很多年的Ruby工程师,后来有缘翻译了《Ruby原理剖析》,也是因为这本书,开启了我对底层开发的兴趣。也恰好,此时Rust 1.0刚好发布,所以我就开始学习Rust。

通过对Rust的深入,我越来越觉得,这是一门值得所有人都去学习的语言。所以我写了《Rust编程之道》这本书,想要让更多的人更容易地去学习Rust。并且我运营了Rust日报,每天分享十条左右的业内动态,目的有两个,第一个是积累一些学习资料,Rust日报里已经积累了很多博客、开源项目。 另一个目的呢,就是通过这个动态,让大家感受到Rust的生机勃发,让更多的人可以了解到这个社区的发展。

我平时没事也喜欢做一些Rust周边,比如说这个Rust勋章和棒球帽。大家收到的小礼物,除了我的书,其实勋章也是我参与制作的(曾经社区内的一次周边定制活动,这次大会举办方PingCAP和秘猿也参与了周边定制活动,参与他们开源项目的贡献者们也会得到胸章噢)。

除了写书呢,我的日常工作也包括做企业培训,去年分别为两家公司做过Rust的培训和开发,去帮助他们引入了Rust。并且创办了辅导式付费自学社群《混沌学社》,帮助想要自学编程的人达成目标。也在线下做一个少年创客俱乐部的创业项目。平时有空,也会参与开源项目的贡献,但为什么这是日常工作呢?说的我好像有工资似的,这是因为Rust的开源文化,对我影响比较大,所以我也乐意去花点时间做点贡献。

通过Rust这门语言,我仿佛看到互联网未来十年即将由它而引起的变革。这种感觉推动着我,所以我才如此积极地参与到Rust的推广活动中。

但是Rust自诞生以来,有一个标签就一直围绕着它:「Rust学习曲线高」。这句话似乎达成了一种共识,就差放到区块链上面了。这其实也为Rust语言的推广造成了一种负面的影响。因为,大多数的人还是喜欢更轻松更易于上手的语言。

所以,借这次大会,我来分享一下对「Rust学习曲线高」的一些正向的思考,同时也分享一些学习经验。希望可以帮助到初学者。

你以为的Rust学习曲线是这样的吗?你认为想要把Rust学会,成为专家,只需要往里面投入时间就可以了。真的不是「从入门到放弃」?「从入门到再次入门」?

拿我自己来说,Rust的学习过程,给我留下了很多至暗时刻。我在2016年写过一篇文章,《如何学习一门新语言》,其中提到了我的学习过程:从前期的懵懂,到后期的重新调整学习策略。我实际上是从入门到再次入门。

从来没有哪门语言让我这么郁闷过,所以我回头好好思考了这个问题,到底为什么会这样?经过我的思考呢,我得出这样一个结论。

Rust呢,它是集很多语言的优点于自身的现代化的语言。它打破了传统语言多年积累下来的「用户习惯」:

1. 包管理器。Cargo说它是个包管理器,它还可以做其他工作,完全是一个工作流引擎。

2. 解决内存安全,引入了所有权机制。所有权几乎是绝大部分新人的入门障碍之一。为什么呢?因为我们过去这么多年,几乎很少有人去关注内存安全。什么是内存安全?什么是未定义行为?所有权是解决问题的手段,但是如果你连问题是如何产生的都不知道,又怎么可能理解解决问题的手段?

3. 现代化类型系统。Rust汲取了现代计算机科学的成果——类型系统。并且,在设计之初也做了「去专业化」处理,把类型系统里「更加学术」的一面替换为语义性更强,更实用的一面。但是,这依然对于大多数人来说是比较陌生的。

4. 零成本抽象。经常用高级语言的人,对「抽象」这个概念倒是比较了解,但是「零成本」就难理解了。经常和底层打交道的人,对于「零成本」比较了解,但是对于「抽象」可能认识的不太深。Rust语言,兼顾了上层的抽象和底层的性能。

5. 史上第一严编译器。就像nick大佬(nrc)在大会开场分享中讲过的那样,Rust语言在设计之初就考虑语言的人体工程学问题。那么个这个人体工程学是在哪表现呢? 就是语义。但Rust又必须遵循另外一个原则,就是内存安全。所以这就要求开发者和编译器共用同一个心智模型。从来没有哪门编程语言会这样要求开发者,都一把梭习惯了。

所以,

得到这个结论以后,我又进一步反思了自己的学习习惯,才想明白Rust的学习曲线背后的真正意义。

欢迎来到真实的世界。

也许有人看出来了,这张图是「达克效应」,也被叫做邓宁-克鲁格效应,的图示。

「达克效应」一般是指人在自己不擅长的领域中往往都会得出错误的结论,但却无法正确认识自身的不足,属于一种认知偏差的现象。这种效应很常见的一种表现就是:做不好事情就抱怨工具有坑。

横座标代表知识和技能的等级,从左到右代表新手到专家。纵座标是自信心,自下而上代表自信心从低到高。

在最初的阶段,也就是红色陡峭曲线的那一个上升区域,自信心是爆棚的。

但是有很多人,落入了「盲人摸象」和「妄自菲薄」的两个陷阱中。按我们以往的学习习惯,看看文档,了解下语法,就可以上手写代码了。但是却频频遭遇编译器的拦截。有些人就在和编译器的搏斗之中,过早地陷入了语言的各种细节中。这就是盲人摸象。另外一些人则认为Rust可能是太难了,自己学不会,而选择了放弃。这就是妄自菲薄。

这就是因为前面所说的,知识断层引起的问题。我们以为Rust和传统语言一样,所以依旧延续了之前的学习习惯。但实际上,我们自己「并不知道Rust语言已经产生了前面所说的知识断层」,然而更可怕的是什么呢? 我们并不知道自己不知道这个事。 所以在直觉上,就会对Rust编译器的行为感到困惑?你根本不会想到是你自己的问题。

然后呢,就到了第二个阶段,绝望之谷。 在这个阶段呢,你会逐渐地意识到自己的知识短板。你会发现自己,原来什么都不懂什么都不会。

有的人,在这个阶段,就会放弃。因为他有挫败感。

而有的人呢,虽然也会感到挫败,但他并没有放弃,而是重新开始学习填补自己的知识短板。

只有第二种人,才有可能进入第三个阶段,开始稳步提升。分清「哪些我已经知道了,哪些还不懂」,查漏补缺,逐渐理解Rust的概念。


在第三个阶段其实也存在一个误区,那就是感觉Rust的概念实在是太多了,有点「乱花渐欲迷人眼」的感觉。但实际上,你可以退一步。「浅草才能没马蹄」,低下头,去寻找这些概念之间的共性和关联,把握语言的一致性。突破了这一点,后面的学习才能逐渐地走向平稳。

所以,感到Rust学习曲线高,这不能怪Rust,而应该反思自己,进行自我检测,看看自己的知识结构哪里出现了缺陷,学习方法哪里出现了问题。抓住这个机会,就可以进一步完善自己,让自己成长。

这个世界上如果想做好什么事情,都并不那么简单,包括编程。我们之前一把梭习惯了,但我们并没有意识到,那种方式其实是存在问题的。直到出现了Rust语言,它只不过是想把你拉回到真实的世界,让我们认真地去面对、思考和处理现实世界中的问题,而不是草率地一把梭。

如果说,最初我是因为Rust的安全、高性能、高级的抽象表达能力而喜欢Rust。那么随着我学习的深入,我是因为Rust让我看到了另一个更好的世界,另一个更好的自我,而更喜欢Rust。

那么如何才能更高效地学习Rust呢?简单来说,如果学习过程能少走一点弯路,就是高效。我站在过来人的角度,给大家分享一些经验。

首先应该明白一点,高效并不等于快速学习。 「21天精通Rust」,那仅限于大神,不能作为普适的学习方法推广。

当我们谈到「高效」的时候,实际上是想去做一种「优化」。学习是大脑高度参与的一种心智活动。那么高效学习,就是去优化你的学习。

我们优化程序优化网络是如何优化呢?其实基本原则很简单。分清不能改变的和可以改变的,然后去想尽一切可能去改变我们可以改变的。对于学习的优化也是一样的思路。

认知科学把大脑处理信息的过程分成短时记忆和长时记忆两步。

第一阶段是输入,大脑通过各种感官器官识别各种信息,在大脑中形成短时记忆。 这个阶段的高效,取决于你单位时间内识别信息的数量。

第二阶段是输出,通过各种输出手段,比如复述、分类、记录、重组、练习等等,将获取的信息进行二次加工,最终形成长时记忆。这个长时记忆,实际上就是知识体系结构,或者是知识网络。只有知识形成了相互关联的网络,才是牢固的。所以,这个过程,会有一定的信息损耗。如果你能把短时记忆的内容全部关联到你当前的知识网络中,那么损耗率就少。如果只能关联部分,那么剩下的就会随着时间的推移而被遗忘。

根据这个大脑的信息处理模型,可以得出一个高效学习的模型:

高效 = (信息量 * 损耗系数)/单位时间

所以,在信息量一定的情况下,单位时间越短,越高效;在单位时间一定的情况下,信息量越多越高效。但是信息量还需要考虑信息的损耗,如果学了,但是没有理解,就等于没学。

要提升学习的效率,就需要在单位时间、信息量和损耗系数三个因素上寻求方案。

人一天24个小时,除了工作、休息等日常时间,余下的学习时间也不太多。但每天至少应该能挤出连续的一个小时来学习应该不成问题。成年人的专注力是可以持续一个小时的。但其实很多人对时间是没有概念的。这里推荐番茄工作法,就是把24小时,以半小时为单位,分隔为连续的时间块。每个时间块,被称为一个番茄钟。在一个番茄钟内,又限定其中25分钟专注学习或工作的时间,另外5分钟用来休息。利用番茄钟,可以把每天1小时的学习时间,分成两个学习单元。 其中一个单元用来输入,另外一个单元用来输出。

输入和输出,构成一个完整的学习单元,减少信息的损耗。如果只有输入,没有输出,那么你的信息损耗率就会成倍增加。在规划好你的学习时间之后,就要想办法增加你的信息量带宽。

经过我多年的实践,我发现信息量和下面的因素是相关的:

  1. 态度。 不能急于求成。一旦急于求成,就容易给自己安排过多的学习内容,造成信息负载,从而阻塞你的大脑,结果反而啥也没学。
  2. 精力管理。学习是需要保持主动性的。而主动性的学习,则需要身体能保持一定的活力。这就需要你自己能平衡生活、工作、学习的节奏。
  3. 学习目标和方法。这是最关键的。只有符合人类认知规律的学习,才是最科学最高效的。基于前面所说大脑的信息处理模型,知识只有形成一张相互关联的网络,才能长期记忆。利用这张知识网络,学习就可以像蜘蛛捕食一样,一旦有未知的知识点落入网中,你就可以马上知道它所处在知识结构中的哪一个位置,然后再慢慢地消化它。如果发现未知的知识点不在你的知识网络范围,那么你就可以向那个方向织网,扩展你的知识网络。

那么,接下来就围绕这个高效学习模型给大家十条建议。

第一条,从整体出发,不要让自己陷入到细节中。

学习,需要掌控感。先从外围,从整体,慢慢了解Rust。Rust语言有哪些特性?Rust是设计哲学是什么?Rust的社区和生态如何? 可以对Rust有一个高屋建瓴的认知。就像画画一样,先画好轮廓,再画细节,这有利于你建立知识网络,可以增加掌控感,并且可以促使信息进入到长时记忆,有效降低信息的损耗。

第二条,抛弃一次性学会的念头,分层次递进式学习。

不要抱着一次性学会Rust的想法去学习。Rust语言中蕴含的知识体系,本身就是有层次的。我在《Rust编程之道》第一章中给出了语言架构。可以按这个层次来学习,帮助自己建立复合的立体的知识体系。

第三条,想尽一切办法已知的知识建立关联。

这一条也是我写作《Rust编程之道》的思路之一。有读者曾经和我聊天,他说,第一次看你书的样章,感觉目录比较平庸,都是老调重弹的感觉。

但其实,我要的就是这种效果。

这个世界上,没有任何一件事物是凭空出现的。你不可能盖一座空中楼阁。

知识也是一样的。别看Rust中很多新的概念。但其实每一个概念,都可以和旧的知识建立关联。

新语言的出现,本质原因是为了解决某个问题。比如Rust中所有权的概念。所有权是解决问题的手段,要想理解它,就必须明白问题所在。也就是说,明白什么是安全。想明白什么是安全,就得搞清楚,这个世界为什么不安全。安全和不安全是一体两面。明白为什么不安全,自然就能理解Rust解决不安全问题的思路,也就自然理解了所有权的概念。

顺着知识的脉络去寻找,和你已知的知识产生联系。这样才有助于构建知识网络。如果不能建立联系,那么你的知识结构肯定存在漏洞,那么你就继续顺着知识的脉络去查漏补缺。

我书的内容组织,也基本遵循这个原则,就是为了帮助大家把新知识和已知的知识建立关联,从而形成知识网络。这也是我在宣传书的时候说,可以降低Rust学习曲线的原因之一。

当然,你如果看其他的资料,也可以遵循这个学习原则。

第四条,学会阅读源码,从源码中学习。

首先,Rust标准库源码是值得一读。你不必通篇全读,只需要在学习过程中,看到哪读到哪。

比如你学习String字符串的时候,看看源码,你就会发现,噢,原来String就是一个u8类型的动态数组。那么它的一些方法,是不是和动态数组的方法类似呢?这一下就能找到共性。但是你又看到u8,是一个字节序列,再结合文档说明,你就可以很容易发现,字符串是一个utf-8编码的字节序列。

然后就是阅读第三方库了。可以找一些常用的库来阅读,学习最佳实践。也可以从Rust日报中查找你感兴趣的擅长领域的库来阅读。

其实阅读源码,并不要求你完全学会了Rust才行。在你掌握了基本的语法,即可阅读源码。阅读的过程中,编译器并不会出来干扰你。你只需要阅读源码的整体组织结构,了解Rust代码的组织方式、编码风格、设计风格、最佳实践即可。阅读源码也是一种知识的应用。

第五条。通过主题式阅读来补基础知识。

举个例子,比如你不懂得Rust异步开发中的futures、async、await等概念。那么你不妨去翻一翻javascript、python、C#等语言中的相关概念。概念都是相同的,不同的是具体的实现。先把概念理清了,再回头看Rust中的实现。你就会发现,Rust之所以迟迟没有登陆异步功能,就是因为Rust语言是一门高度要求一致性、内存安全、性能的语言。所以在异步语法设计上,要做诸多的考量。所以才迟迟未稳定。但你知道,这个功能是值得等待的,好事多磨。

这就是一种主题式阅读补基础知识的方法。同样的方法,还适合去理解并发安全、Unsafe Rust等等。

有助于你拎清概念和实现,建立更容易迁移的知识结构。

第六条。时刻把握Rust的设计哲学。

在学习过程中,时刻把握Rust的设计哲学:安全、实用、性能。我们说,要尽力和已知的知识相关联。但也要注意以Rust的特性为出发点。否则,已知的知识则会成为我们学习的绊脚石。

Rust吸取了很多语言的特性。你可以在Rust中看到你熟悉语言的影子。但是你要站在Rust的角度去寻找共性,建立联系,而不是站在你熟悉语言的角度上去看Rust。

第七条。有意识地构建属于自己的Rust心智模型。

什么是心智模型?

一名乒乓球运动员,可以根据乒乓球的弹射速度、旋转方向等外界因素,迅速判断出各种可能性,从而选择最佳的回击策略。

一名赛车手,根据不断变化的路况,快速地进行各种操作。这依赖于他大脑中的心智模型,来达成人车合一的状态。

心智模型,就是人脑,或者说,是你思想和意识在客观世界的延伸。可以帮助你判断。编程也一样,其实前面说的,Rust语言架构,就是Rust语言在我心里构建的心智模型。我通过这个心智模型,来和Rust编译器达成一致,所以在我写代码的时候,可以尽可能地 遵守了Rust的语言规则,大幅度地降低编译器报错的情况。即便是编译器报错了,也可以快速地通过错误信息定位问题。

如何构建你的心智模型呢?这就需要你从纷繁复杂的语言特性中,寻找共性,寻找一致性,在你心里串起一个精简的知识网络。

第八条,多分享和交流。

有人的地方就有Bug。再怎么天才,也有出错的时候。学习最忌讳闭门造车。所以,多交流分享你的学习心得,以教为学。其实我写Rust编程之道的一个目的,就是为了系统性地整理自己的学习心得,只有写出来,才是学会了。而且写出来给别人看,也可以达到交流的目的。所以,我体验了一次集体智慧的力量。因为我没有找到合适的技术审核人员,导致书中有一些错漏,但是读者们非常热心,帮我勘误。在这个过程中,也帮助我纠正了之前的错误认知。

第九条,参与开源项目贡献。

现在Rust招聘职位并不多。通过前期的针对性学习和训练,阅读源码,自己实现一些自己的小项目之后。也可以考虑参与大型的开源项目做贡献。 比如PingCAP的TiKV、秘猿的Cita区块链、还有我们的Rust语言,它自身也是一个Rust项目。可以参考我另一篇文章:如何为TiKV做贡献 ,了解更多。

当然,最好还是找你自己擅长领域的项目去做贡献。

第十条,阅读《Rust编程之道》。

这其实也不算广告了。我这本书的内容组织、写作逻辑都是遵循上面所说的认知规律。可以帮助你高效地掌握Rust语言。而且,我还组织了读者群,大家可以在交流中学习,互帮互助,不怕学不会。

以上。

编辑于 2019-04-22

文章被以下专栏收录