This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
<audio id="audio" title="100 | 高效学习:面对枯燥和量大的知识" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/80/1e/80b3803c703ed1eb79d725f6c4f3801e.mp3"></audio>
# 如何面对枯燥的知识
首先,我们要知道,为什么会有枯燥的知识?一般来说,枯燥的东西通常是你不感兴趣的东西,而你不感兴趣的东西,可能是你并不知道有什么用的东西。这样的知识通常是比较底层或是抽象度比较高的知识,比如:线性代数,或者一些操作系统内部的原理……越理论的东西就越让人觉得枯燥。
我还记得当初上大学学习《计算机网络》时直接学习那个七层协议以及那些报文让我感觉枯燥得不行。那个时候完全不知道这些东西有什么用因为我连网络是什么都没有见过。直到有一天我在老师的公司里看到了网卡、网线和Hub然后了解了Windows NT的域和IP地址然后用Power Builder 连上了SQL Server用SQL写入并读取了数据我才真正明白网络原来有这么好玩。
我开始学习《TCP/IP 详解》又感到一阵枯燥。然后有一个同事给我递来了《Unix网络编程》我照着其中的例子写了一个聊天服务器前端用Delphi写了一个QQ的样子那种兴奋劲就别提了。再后来因为要处理网络问题调优网络性能我才发现以前随便学了点的《TCP/IP详解》对我在排查网络问题上有很大的帮助。这个时候我才认真地看了这本书也正是这个时候才算是真正读进去了。
后来我让我团队的一个人学《TCP/IP详解》这本书他发现有点难啃就买了一本《图解TCP/IP》。我找来一看发现这种图文并茂的书真是增加了很不错的阅读体验一下子就觉得不是很枯燥了。这让我回想起来那本《从一到无穷大》的相对论科普书简单、一点也不枯燥。然而能把这么复杂的问题用这么简单的语言讲清楚的一定是这个领域的大牛了。
我列举我的这个学习过程,就是想说,如果你发现有些知识太过于枯燥,那么可以通过下面的方法解决。
1. 这个知识对于你来说来太高级了,你可能不知道能用在什么地方。
1. 人的认知是从感性认识向理性认识转化的,所以,你可能要先去找一下应用场景,学点更实用的,再回来学理论。
1. 学习需要有反馈,有成就感,带着相关问题去学习会更好。
1. 当然,找到牛人来给你讲解,也是一个很不错的手段。
# 如何面对大量的知识
看过《程序员练级攻略》的朋友们一定会有这样的疑问东西太多了怎么学。我给你的建议是一点一点学一口一口吃。你可以使用我前面说过的那些方法注重基础画知识图多问为什么多动手然后坚持住哪怕你每周就学一个知识点你一年也可以学到50个知识点。只要你在进步总有一天可以把这些知识学到手的。
当然,你的目的不是学完这些知识,因为学无止境,你永远也学不完,所以你在学习时,一定不要学在表面上,一定要学到本质,学到原理上,那些东西是不容易变的,也是经得住时间考验的。把学习当成投资,这是这个世界上回报最好的投资。
带着问题去学习,带着要解决的东西去学习,带着挑战去学习,于是每当你解决了一个问题,做了一个功能,完成了一个挑战,你就会感到兴奋和有成就感。这样,你也就找到了源源不断的学习驱动力。
把你学习的心得、过程、笔记、代码分享出来,找到和你一同学习的人,因为一个人长跑很辛苦,有人同行就会好很多,就算没有人同行,你的读者,你的观众也会为你鼓掌加油,这些也是让你持续前行的动力。
人的一生是要永远学习的。加油!
# 认真阅读文档
我发现很多技术问题都是出在技术人员不认真读技术手册上,我自己也一样。在我的成长生涯中,我发现很多答案或其实都在文档中,而我却没有仔细地去读一下。可能是,我们都不想投入太多的时间吧。
在这里我想说用户手册User Manual一定要好好地读一读很多很多提示都在里面了这是让你可以少掉很多坑的法宝。比如Unix和Linux的manDocker和Kubernetes的官方文档Git的操作文档……你的很多很多问题的答案都在这些文档中。
举个例子,很多年前,我掉了一个坑,我把这个问题记录在了文章《 [C/C++返回内部静态成员的陷阱](https://blog.csdn.net/haoel/article/details/1388498) 》中。 其中提到了一个函数 `char *inet_ntoa(struct in_addr in);`我还批评了一下这个函数。然而只要你man 一下这个函数就可以看到“The string is returned in a statically allocated buffer, which subsequent calls will overwrite”。
还有很多中国的文档都会教人把tcp_tw_recycle和tcp_tw_resue这两个参数打开。然而只要你man 一下 [TCP(7)](http://man7.org/linux/man-pages/man7/tcp.7.html) ,就可以看到这样的描述:
<img src="https://static001.geekbang.org/resource/image/63/29/6380f606c4a66bb0a869c19b8ea1ad29.png" alt="">
你就可以看到这两个参数都是不建议被打开的。
认真阅读用户手册不但可以让你少掉很多坑,同时,还能让你学习到很多。
# 其它几个实用的技巧
<li>
**用不同的方式来学习同一个东西**。比如:通过看书,听课,创建脑图,写博客,讲课,解决实际问题,等等。
</li>
<li>
**不要被打断**。被打断简直就是学习的天敌,所以,你在学习的时候,最好把手机设置成勿扰模式放在一边,然后把电脑上的所有通知也关掉,最好到一个别人找不到你的地方。
</li>
<li>
**总结压缩信息**。当你获得太多的信息时,你需要有一个“压缩算法”。我常用的压缩算法是只关心关键点,所以,你需要使用表格、图示、笔记或者脑图来帮助你压缩信息。
</li>
<li>
**把未知关联到已知**。把你新学的知识点关联到已知的事物上来。比如你在学习Go语言你就把一些知识关联到自己已经学过的语言上比如C和Java。通过类比你会学得更扎实也会思考得更多。
</li>
<li>
**用教的方式来学习**。你想想如果你过几天要在公开场合对很多人讲一个技术那么这个压力会让你学得更好。因为要教给别人所以这么高的标准需要你不但要把自己已掌握的东西学好还要把周边的也一并学了才可能做到百问不倒。你才敢去教别人不是么试试教6岁的孩子编程如果你掌握了这种技能那么你一定是把知识吃得非常透彻了。
</li>
<li>
**学以致用**。把学到的东西用起来,没有什么比用起来能让你的知识更巩固的了。在实践中,你才会有更为真实的体会,你才会遇到非常细节和非常具体的问题,这些都会让你重新思考,或深化学习。
</li>
<li>
**不要记忆**。聪明的人不会记忆知识的,他们会找方法,那些可以推导出知识或答案的方法。这也是为什么外国人特别喜欢方法论。
</li>
<li>
**多犯错误**。犯错会让你学得到更多,通过错误总结教训,你会比没有犯过错的人体会得更深。但是千万不要犯低级错误,也不要同一个错误犯两次。
</li>
如果你有更好的一些技巧,欢迎你分享出来。
# 小结
总结一下今天的内容。首先,我先分析了为什么会有枯燥的知识。我认为,枯燥的知识通常是你不感兴趣的知识,也有可能是你不知道有什么用的东西。然后,结合自己的经历给出了面对枯燥的知识时该怎样做。此外,我们身处在信息爆炸时代,如何面对如此量大的知识,也是我们面临的一个挑战。我建议,一定不要学在表面上,一定要学到本质上、原理上,一定要学那些不容易改变,能经得住时间考验的东西。
随后,我分享了认真阅读文档的重要性,不仅可以让你少掉很多坑,还可以让你学习到很多知识。最后,我分享了好几条实用的学习技巧,这些也是我在工作中慢慢收集和总结起来的。希望对你有帮助。
下面是《高效学习》系列文章的目录。
- [端正学习态度](https://time.geekbang.org/column/article/14271)
- [源头、原理和知识地图](https://time.geekbang.org/column/article/14321)
- [深度,归纳和坚持实践](https://time.geekbang.org/column/article/14360)
- [如何学习和阅读代码](https://time.geekbang.org/column/article/14380)
- [面对枯燥和量大的知识](https://time.geekbang.org/column/article/14389)

View File

@@ -0,0 +1,147 @@
<audio id="audio" title="96 | 高效学习:端正学习态度" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/44/e6/44481beeffc560ca73d323dd21e7bae6.mp3"></audio>
在开始这一系列文章之前,我想说,如果你想从我这里得到一些速成的方法,那么你就不用往下看了,学习是不可能速成的。这里只有一些方法和技巧,是我这么多年来行之有效的,分享出来也许对你有帮助。一方面,可能会让你学得更多和更累,另一方面,可能会让你学得更系统、更全面。总之,学习是一件“逆人性”的事,就像锻炼身体一样,**需要人持续付出,会让人感到痛苦,并随时想找理由放弃**。
大部分人都认为自己爱学习,但是:
- 他们都是只有意识没有行动,他们是动力不足的人。
- 他们都不知道自己该学什么,他们缺乏方向和目标。
- 他们都不具备自主学习的能力,没有正确的方法和技能。
- 更要命的是,他们缺乏实践和坚持。
如果你去研究一下古今中外的成功人士,就会发现,他们基本上都是非常自律的,也都是非常热爱学习的。他们可以沉得下心来不断地学习,在学习中不断地思考、探索和实践。
所以如果你不能克服自己DNA中的弱点不能端正自己的态度不能自律不能坚持不能举一反三不能不断追问等那么无论有多好的方法你都不可能学好。所以有正确的态度很重要。
然后,我会在后面给你一些方法和相关的技能,让你可以真正实际操作起来。
# 主动学习和被动学习
1946年美国学者埃德加·戴尔Edgar Dale提出了「学习金字塔」Cone of Learning的理论。之后美国缅因州国家训练实验室也做了相同的实验并发布了「学习金字塔」报告。
<img src="https://static001.geekbang.org/resource/image/e4/16/e46f9dc2d0bc9e5f62ab688e1675b616.png" alt="">
人的学习分为「被动学习」和「主动学习」两个层次。
<li>
**被动学习**如听讲、阅读、视听、演示学习内容的平均留存率为5%、10%、20%和30%。
</li>
<li>
**主动学习**如通过讨论、实践、教授给他人会将原来被动学习的内容留存率从5%提升到50%、75%和90%。
</li>
这个模型很好地展示了不同学习深度和层次之间的对比。
我们可以看到,你听别人讲,或是自己看书,或是让别人演示给你,这些都不能让你真正获得学习能力,因为你是在被别人灌输,在听别人说。
只有你开始自己思考,开始自己总结和归纳,开始找人交流讨论,开始践行,并开始对外输出,你才会掌握到真正的学习能力。
举个大家都懂的例子那就是学习英文我们从小就是在开始学习英文了很多人英文成绩可以考得很好语法也可以不错。然而哪天真正要和外国人交流的时候却发现自己的英文能力渣得不要不要的只会回答Fine. Thank you, and you? 这就是浅度学习的结果。
我的英文能力也是一样的,直到有一天进到外企,外企请了个外教每周来公司三次和我们练英文,我的英文能力才有一点点进步,然而,还是不够。后来有一天,公司的客户抱怨我们的一线客服处理问题太慢,问我们在后台做开发的人有谁去一线支持客户,我举手了。于是我接了半年来自日本、新加坡、德国、法国、英国等多个国家的客户电话和邮件。
在这期间,我的英文能力直线上升,速度快得不得了。一方面是我要把自己知道的讲给客户听,另一方面要跟客户有交流,所以我学得更努力,也更有效果。主要是日本人和德国人给了我足够的信心,这两个国家的人可能是这世界上最严谨的人,他们非常喜欢打破沙锅问到底,而且他们的英文也不怎么好,但是他们都用很慢的语速来和我交流,一方面是怕他们自己说不好,另一方面是也希望我用慢速的话和他们说。于是,大家都在一种慢速的环境下说英文,把每个单词的音都发准了,这使我提高了英文能力。
后面再跟一些口音很奇葩的老外(比如印度人和法国人)说英文的时候,我就会让他们说慢点,以便我适应他们的口音。几年后,我到了另外一家外国公司工作,需要跟一些口音非常重的印度人和非洲人说英文,我都能听懂,着实把我身边的同事们都震住了。这就是深度学习的最好的例子,要践行!
**所以,学习不是努力读更多的书,盲目追求阅读的速度和数量,这会让人产生低层次的勤奋和成长的感觉,这只是在使蛮力。要思辨,要践行,要总结和归纳,否则,你只是在机械地重复某件事,而不会有质的成长的。**
# 浅度学习和深度学习
老实说,对于当前这个社会:
<li>
大多数人的信息渠道都被微信朋友圈、微博、知乎、今日头条、抖音占据着。这些信息渠道中有营养的信息少之又少。
</li>
<li>
大多数公司都是实行类似于996这样的加班文化在透支和消耗着下一代年轻人让他们成长不起来。
</li>
<li>
因为国内互联网访问不通畅,加上英文水平受限,所以,大多数人根本没法获取到国外的第一手信息。
</li>
<li>
快餐文化盛行,绝大多数人都急于速成,心态比较浮燥,对事物不求甚解。
</li>
所以,你看,在这种环境下,你根本不需要努力的。你只需要踏实一点,像以前那样看书,看英文资料,你只需要正常学习,根本不用努力,就可以超过你身边的绝大多数人。
我们整个世界进入了前所未有的信息爆炸时代人们担忧的不再是无知识可学而是有学不完的知识。而且时代的节奏变得越来越快你可能再也不像20年前可以沉着优雅平和地泡上一杯茶坐在一个远离喧嚣的环境下认认真真地看本书。这个时代你再也不会有大块大块的时间你的时间都被打成碎片了不知不觉你也成为了快餐文化的拥趸……
在这样一个时代下,种种迹象表明,快速、简单、轻松的方式给人带来的快感更强烈,而高层次的思考、思辨和逻辑则被这些频度高的快餐信息感所弱化。于是,商家们看到了其中的商机,看到了如何在这样的时代里怎么治愈这些人在学习上的焦虑,他们在想方设法地用一些手段推出各种代读、领读和听读类产品,让人们可以在短时间内体会到轻松获取知识的快感,并产生勤奋好学和成长的幻觉(老实说,像我这种付费专栏或是得到等知识付费产品基本上就是类似的产物)。
这些所谓的“快餐文化”可以让你有短暂的满足感,但是无法让你有更深层次的思考和把知识转换成自己的技能的有效路径,因为那些都是需要大量时间和精力的付出,不符合现代人的生活节奏。人们开始在朋友圈、公众号、得到等这样的地方进行学习,导致他们越学越焦虑,越学越浮燥,越学越不会思考。于是,他们成了“什么都懂,但依然过不好这一生”的状态。
只要你注意观察,就会发现,少数的精英人士,他们在训练自己获取知识的能力,他们到源头查看第一手的资料,然后,深度钻研,并通过自己的思考后,生产更好的内容。而绝大部分受众享受轻度学习,消费内容。
你有没有发现,在知识的领域也有阶层之分,那些长期在底层知识阶层的人,需要等着高层的人来喂养,他们长期陷于各种谣言和不准确的信息环境中,于是就导致错误或幼稚的认知,并习惯于那些不费劲儿的轻度学习方式,从而一点点地丧失了深度学习的独立思考能力,从而再也没有能力打破知识阶层的限制,被困在认知底层翻不了身。
可见深度学习十分重要,但应该怎样进行深度学习呢?下面几点是关键。
- **高质量的信息源和第一手的知识**。
- **把知识连成地图,将自己的理解反述出来**。
- **不断地反思和思辨,与不同年龄段的人讨论**。
- **举一反三,并践行之,把知识转换成技能**。
换言之,学习有三个步骤。
<li>
**知识采集**。信息源是非常重要的,**获取信息源头、破解表面信息的内在本质、多方数据印证**,是这个步骤的关键。
</li>
<li>
**知识缝合**。所谓缝合就是把信息组织起来,成为结构体的知识。这里,**连接记忆,逻辑推理,知识梳理**是很重要的三部分。
</li>
<li>
**技能转换**。通过**举一反三、实践和练习**,以及**传授教导**,把知识转化成自己的技能。这种技能可以让你进入更高的阶层。
</li>
我觉得这是任何人都是可以做到的,就是看你想不想做了。
此外,在正式开始讲如何学习之前,让我先说一些关于学习的观点,这是在为后面的那些学习方法和技巧做提纲挈领的铺垫。
# 学习是为了找到方法
**学习不仅仅是为了找到答案,而更是为了找到方法**。很多时候尤其是中国的学生他们在整个学生时代都喜欢死记硬背因为他们只有一个KPI那就是在考试中取得好成绩所以死记硬背或题海战术成了他们的学习习惯。然而在知识的海洋中答案太多了你是记不住那么多答案的。
只有掌握解题的思路和方法,你才算得上拥有解决问题的能力。所有的练习,所有的答案,其实都是在引导你去寻找一种“以不变应万变”的方法或能力。在这种能力下,你不需要知道答案,因为你可以用这种方法很快找到答案,找到解,甚至可以通过这样的方式找到最优解或最优雅的答案。
这就好像,你要去登一座山,一种方法是通过别人修好的路爬上去,一种是通过自己的技能找到路(或是自己修一条路)爬上去。也就是说,需要有路才爬得上山的人,和没有路能造路的人相比,后者的能力就会比前者大得多得多。所以,**学习是为了找到通往答案的路径和方法,是为了拥有无师自通的能力**。
# 学习是为了找到原理
**学习不仅仅是为了知道,而更是为了思考和理解**。在学习的过程中,我们不是为了知道某个事的表面是什么,而是要通过表象去探索其内在的本质和原理。真正的学习,从来都不是很轻松的,而是那种你知道得越多,你的问题就会越多,你的问题越多,你就会思考得越多,你思考得越多,你就会越觉得自己知道得越少,于是你就会想要了解更多。如此循环,是这么一种螺旋上升上下求索的状态。
但是,这种循环,会在你理解了某个关键知识点后一下子把所有的知识全部融会贯通,让你赫然开朗,此时的那种感觉是非常美妙而难以言语的。在学习的过程中,我们要不断地问自己,这个技术出现的初衷是什么?是要解决什么样的问题?为什么那个问题要用这种方法解?为什么不能用别的方法解?为什么不能简单一些?……
这些问题都会驱使你像一个侦探一样去探索背后的事实和真相,并在不断的思考中一点一点地理解整个事情的内在本质、逻辑和原理。**一旦理解和掌握了这些本质的东西,你就会发现,整个复杂多变的世界在变得越来越简单。你就好像找到了所有问题的最终答案似的,一通百通了**。
# 学习是为了了解自己
**学习不仅仅是为了开拓眼界,而更是为了找到自己的未知,为了了解自己**。英文中有句话叫You do not know what you do not know可以翻译为你不知道你不知道的东西。也就是说你永远不会去学习你不知道其存在的东西。就好像你永远Google不出来你不知道的事因为对于你不知道的事你不知道用什么样的关键词你不知道关键词你就找不到你想要的知识。
这个世界上有很多东西是你不知道的,所以,学习可以让你知道自己不知道的东西。只有当我们知道有自己不知道的东西,我们才会知道我们要学什么。所以,我们要多走出去,与不同的人交流,与比自己聪明的人共事,你才会知道自己的短板和缺失,才会反过来审视和分析自己,从而明白如何提升自己。
山外有山,楼外有楼,人活着最怕的就是坐井观天,自以为是。因为这样一来,你的大脑会封闭起来,你会开始不接受新的东西,你的发展也就到了天花板。**开拓眼界的目的就是发现自己的不足和上升空间,从而才能让自己成长**。
# 学习是为了改变自己
**学习不仅仅是为了成长,而更是为了改变自己**。很多时候,我们觉得学习是为了自己的成长,但是其实,学习是为了改变自己,然后才能获得成长。为什么这么说呢?我们知道,人都是有直觉的,但如果人的直觉真的靠谱,那么我们就不需要学习了。而学习就是为了告诉我们,我们的很多直觉或是思维方式是不对的,不好的,不科学的。
只有做出了改变后,我们才能够获得更好的成长。你可以回顾一下自己的成长经历,哪一次你有质的成长时,不是因为你突然间开窍了,开始用一种更有效率、更科学、更系统的方式做事,然后让你达到了更高的地方。不是吗?当你学习了乘法以后,在很多场景下,就不需要用加法来统计了,你可以使用乘法来数数,效率提升百倍。
当你有一天知道了逻辑中的充要条件或是因果关系后,你会发现使用这样的方式来思考问题时,你比以往更接近问题的真相。**学习是为了改变自己的思考方式,改变自己的思维方式,改变自己与生俱来的那些垃圾和低效的算法。总之,学习让我们改变自己,行动和践行,反思和改善,从而获得成长**。
# 小结
总结一下今天的内容。首先学习是一件“逆人性”的事就像锻炼身体一样需要人持续付出但会让人痛苦并随时可能找理由放弃。如果你不能克服自己DNA中的弱点不能端正自己的态度不能自律不能坚持不能举一反三不能不断追问等那么无论有多好的方法你都不可能学好。因此有正确的态度很重要。
此外,还要拥有正确的学习观念:学习不仅仅是为了找到答案,而更是为了找到方法;学习不仅仅是为了知道,而更是为了思考和理解;学习不仅仅是为了开拓眼界,而更是为了找到自己的未知,为了了解自己;学习不仅仅是为了成长,而更是为了改变自己,改变自己的思考方式,改变自己的思维方式,改变自己与生俱来的那些垃圾和低效的算法。
端正的学习态度和正确的学习观念,是高效学习的第一步,拥有这两者一定可以让你事半功倍。然后就是要总结和掌握高效学习的方法,这是我们下篇文章中将要分享的内容。敬请期待。
下面是《高效学习》系列文章的目录。
- [端正学习态度](https://time.geekbang.org/column/article/14271)
- [源头、原理和知识地图](https://time.geekbang.org/column/article/14321)
- [深度,归纳和坚持实践](https://time.geekbang.org/column/article/14360)
- [如何学习和阅读代码](https://time.geekbang.org/column/article/14380)
- [面对枯燥和量大的知识](https://time.geekbang.org/column/article/14389)

View File

@@ -0,0 +1,91 @@
<audio id="audio" title="97 | 高效学习:源头、原理和知识地图" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a8/20/a812154ef4efc2a99c1291d2322a1a20.mp3"></audio>
有了上一篇文章中分享的那些观点,我们来看看应该怎么做。下面是我觉得比较不错的一些学习的方法,或者说对我来说最有效的学习方法。我相信,只要你和我一样,做到的话,你的学习效率一定能够提升很快。
# 挑选知识和信息源
还是我在《程序员练级攻略》中说的那样英文对于我们来说至关重要尤其是对于计算机知识来说。如果你觉得用百度搜中文关键词就可以找到自己想要的知识那么你一定远远落后于这个时代了。如果你用Google英文关键词可以找到自己想要的知识那么你算是能跟得上这个时代。如果你能在社区里跟社区里的大牛交流得到答案那么你算是领先于这个时代了。
所以,我认为你的信息源要有下面几个特质。
<li>
应该是第一手资料,不是被别人理解过、消化过的二手资料。尤其对于知识性的东西来说,更是这样。应该是原汁原味的,不应该是被添油加醋的。
</li>
<li>
应该是有佐证、有数据、有引用的,或是有权威人士或大公司生产系统背书的资料。应该是被时间和实践检验过的,或是小心求证过的,不是拍脑袋野路子或是道听途说出来的资料。
</li>
<li>
应该是加入了一些自己的经验和思考,可以引发人深思的,是所谓信息的密集很大的文章。
</li>
顺便说一句我发现Medium 上的文章质量比较高很多文章都Google到了Medium上。
我在《程序员练级攻略 》后期的文章中罗列了很多文章资源,有的读者很不能理解,他们觉得我多少应该导读一下或是写上一些自己的想法,而不是只是简单地罗列出来。这里请允许我辩解一下,我之所以这样做,并不是因为偷懒,我完全可以把这些信息资料全部隐藏起来,翻译也好,搬运也好,导读也好,自己消化完后再写出来。那么,我可以写出多少个专栏来?
我觉得只要我有时间极客时间上的所有专栏都不用写了我一个人就OK了。我可以写得又快又好而且超出所有的人。那我可以挣到很多钱。但我不想这样我想把我读过的好的文章推荐给大家就像推荐书一样。那些是信息源头已经写得非常不错了我不用再多废话。而且那些文章底部都有很多的引用你可以一路点过去。
但**我想通过这些简单链接的方式,为我的读者打开一个全新的世界,他们可以在这个世界中自己找食吃,而不需要依赖我,这才是我想给大家带来的东西**。我不知道,我的那些推荐文章,有没有让你看到了一个很广阔的世界,在那里,每天都在产生很多最新、最酷、最有营养的一手信息,而不是被我或他人消化过的二手信息。
这里,我只想说,对于一个学习者来说,找到优质的信息源可以让你事半功倍。一方面,就像找到一本很好的武林秘籍一样,而不是被他人翻译过或消化过的,也不会有信息损失甚至有错误信息会让你走火入魔。另一方面,你需要的不只有知识和答案,更重要的是掌握学习的方法和技能。你要的是“渔”,而不是“鱼”。
# 注重基础和原理
我在很多的场合都提到过,基础知识和原理性的东西是无比重要的。这些基础知识就好像地基一样,只要足够扎实,就要可以盖出很高很高的楼。正所谓“勿在浮沙筑高台”。我说过,很多人并不是学得不够快,而他们的基础真的不行。基础不行,会影响你对事物的理解,甚至会让你不能理解为什么是这样。当你对事物的出现有不理解的东西时,通常来说,是因为你的基础知识没有跟上。
在《程序员练级攻略 》一文中,我用了很大的篇幅给出了学习基础技术的路径。只要你努力学习那些基础知识,了解了其中的原理,就会发现这世界上的很多东西是大同的。
举个例子如果你学习过底层的Socket编程了解多路复用和各种I/O模型的话select, poll, epoll, aio, windows completion port, libevent等那么对于Node.js、Java NIO、Nginx、C++的ACE框架等这些中间件或是编程框架你就会发现无论表现形式是什么样的其底层原理都是一个样的。
无论是JVM还是Node或者是Python解释器里干了什么它都无法逾越底层操作系统API对“物理世界”的限制。而当你了解了这个底层物理世界以后无论那些技术玩成什么花样它们都无法超出你的掌控这种感觉是很爽的
再举一个例子,当学了足够多的语言,并有了丰富的实践后,你开始对编程语言的各种编程范式或是控制流有了原理上的了解,这时再学一门新语言的话,你会发现自己学得飞快。
就像我2010年学习Go语言一样除了那些每个语言都有的if-else、 for/while-loop、function等东西以外我重点在看的就是出错处理是怎么玩的内存管理是怎么玩的数据封装和扩展怎么玩的多态和泛型怎么搞的运行时识别和反射机制是怎么玩的并发编程怎样玩……
这些都是现代编程语言必需的东西,如果没有,那么这个语言的表达能力就很落后了。所以,当知道编程语言的本质和原理后,你学习一门新的语言是非常非常快的,而且可以直达其高级特性。
**最最关键的是,这些基础知识和原理性的东西和技术,都是经历过长时间的考验的,所以,这些基础技术也有很多人类历史上的智慧结晶,会给你很多启示和帮助**。比如TCP协议的状态机可以让你明白如果你要设计一个异步通信协议状态机是一件多么重要的事还有TCP拥塞控制中的方式让你知道设计一个以响应时间来限流的中件间是什么样的。
当学习算法和数据结构到一定程度的时候,你就会知道,算法不仅对于优化程序很重要,而且,会让你知道,该如何设计数据结构和算法来让程序变得更为健壮和优雅。
有时候,学习就像拉弓蓄力一样,学习基础知识感觉很枯燥很不实用,工作上用不到,然而学习这些知识是为了未来可以学得更快。基础打牢,学什么都快,而学得快就会学得多,学得多,就会思考得多,对比得多,结果是学得更快……这种感觉,对于想速成的人来说,很难体会。
这里我想再次强调一下,请一定要注重基础知识和原理上的学习!
# 使用知识图
先讲一个故事2000年我从昆明到上海开始沪飘的岁月。刚到上海找不到好工作只能大量地学习和看书C/C++/JavaTCP/IPWindows编程Unix编程等等。结果呢书太多了根本看不过来。我想要更多地掌握知识结果我发现以死记硬背的方式根本就是在使蛮力学习我很难在很短的时间内学习很多的知识。
于是我自己发明了一种叫“联想记忆法”的方法比如在学习C++的时候面对《C++ Primer》这种厚得不行的书我就使用联想记忆法。
我把C++分成三部分。
<li>
第一部分是C++是用来解决C语言的问题的那么C语言有什么问题呢指针、宏、错误处理、数据拷贝…… C++用什么技术来解决这些问题呢?
</li>
<li>
第二部分是C++的面向对象特性封装、继承、多态。封装让我想到了构造函数、析构函数等。构造函数让我想到了初始化列表想到了默认构造函数想到了拷贝构造函数想到了new……多态让我想到了虚函数想到了RTTIRTTI让我想到了dynamic_cast 和 typeid等。
</li>
<li>
第三部分是C++的泛型编程。我想到了template想到了操作符重载想到了函数对象想到STL想到数据容器想到了iterator想到了通用算法等等。
</li>
于是,我通过“顺藤摸瓜”的方式,从知识树的主干开始做广度或是深度遍历,于是我就得到了一整棵的知识树。这种“顺藤摸瓜”的记忆方式让我记住了很多知识。**最重要的是,当出现一些我不知道的知识点时,我就会往这棵知识树上挂,而这样一来,也使得我的学习更为系统和全面**。
这种画知识图的方式可以让你从一个技术最重要最主干的地方出发开始遍历所有的技术细节,也就是画地图的方式。如果你不想在知识的海洋中迷路,你需要有一份地图,所以,**学习并不是为了要记忆那些知识点,而是为了要找到一个知识的地图,你在这个地图上能通过关键路径找到你想要的答案**。
# 小结
总结一下今天的内容。首先,我强调了,挑选知识和信息源的重要性,因为优质的信息源可以让你事半功倍。其次,我认为,一定要注重基础和原理,基础打牢,学什么都快,而学得快就会学得多,学得多,就会思考得多,对比得多,结果是学得更快。
最后,我指出,学习时一定要使用知识图,学习并不是为了要记忆那些知识点,而是为了要找到一个知识的地图,你在这个地图上能通过关键路径找到你想要的答案。我相信,只要掌握了好的方法,你能做到的话,你的学习效率一定提升很快。
下篇文章中,我将接着介绍几个不错的学习方法。希望对你有帮助。
下面是《高效学习》系列文章的目录。
- [端正学习态度](https://time.geekbang.org/column/article/14271)
- [源头、原理和知识地图](https://time.geekbang.org/column/article/14321)
- [深度,归纳和坚持实践](https://time.geekbang.org/column/article/14360)
- [如何学习和阅读代码](https://time.geekbang.org/column/article/14380)
- [面对枯燥和量大的知识](https://time.geekbang.org/column/article/14389)

View File

@@ -0,0 +1,122 @@
<audio id="audio" title="98 | 高效学习:深度,归纳和坚持实践" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b6/3a/b6427beebb4a62407ff7f68b9524f53a.mp3"></audio>
# 系统地学习
在学习某个技术的时候我除了会用到上篇文章中提到的知识图还会问自己很多个为什么。于是我形成了一个更高层的知识脑图。下面我把这这个方法分享出来。当然学习一门技术时Go语言也好Docker也好我都有一个学习模板。只有把这个学习模板中的内容都填实了我才罢休。这个模板如下。
<li>
**这个技术出现的背景、初衷和要达到什么样的目标或是要解决什么样的问题**。这个问题非常关键,也就是说,你在学习一个技术的时候,需要知道这个技术的成因和目标,也就是这个技术的灵魂。如果不知道这些的话,那么你会看不懂这个技术的一些设计理念。
</li>
<li>
**这个技术的优势和劣势分别是什么或者说这个技术的trade-off是什么**。任何技术都有其好坏在解决一个问题的时候也会带来新的问题。另外一般来说任何设计都有trade-off要什么和不要什么所以你要清楚这个技术的优势和劣势以及带来的挑战。
</li>
<li>
**这个技术适用的场景**。任何技术都有其适用的场景,离开了这个场景,这个技术可能会有很多槽点,所以学习技术不但要知道这个技术是什么,还要知道其适用的场景。没有任何一个技术是普适的。注意,所谓场景一般分别两个,一个是业务场景,一个是技术场景。
</li>
<li>
**技术的组成部分和关键点**。这是技术的核心思想和核心组件了,也是这个技术的灵魂所在了。学习技术的核心部分是快速掌握的关键。
</li>
<li>
**技术的底层原理和关键实现**。任何一个技术都有其底层的关键基础技术这些关键技术很有可能也是其它技术的关键基础技术。所以学习这些关键的基础底层技术可以让你未来很快地掌握其它技术。可以参看我在CoolShell上写的Docker底层技术那一系列文章。
</li>
<li>
**已有的实现和它之间的对比**。一般来说,任何一个技术都会有不同的实现,不同的实现都会有不同的侧重。学习不同的实现,可以让你得到不同的想法和思路,对于开阔思维,深入细节是非常重要的。
</li>
基本上来说如果你按照我上面所提的这6大点来学习一门技术你一定会学习到技术的精髓而且学习的高度在一开始就超过很多人了。如果你能这样坚持2-3年我相信你一定会在某个领域成为炙手可热的佼佼者。
# 举一反三
举一反三的道理人人都知道,所以,在这里我并不想讨论为什么要举一反三,而是想讨论如何才能有举一反三的能力。我认为,人与人最大的差别就是举一反三的能力。那些聪明的或者是有经验的人举一反三起来真是太令人惊叹。
我觉得一个人的举一反三能力,可以分解成如下三种基本能力。
<li>
**联想能力**。这种能力的锻炼需要你平时就在不停地思考同一个事物的不同的用法,或是联想与之有关的其他事物。对于软件开发和技术学习也一样。
</li>
<li>
**抽象能力**。抽象能力是举一反三的基本技能。平时你解决问题的时候,如果你能对这个问题进行抽象,你就可以获得更多的表现形式。抽象能力需要找到解决问题的通用模型,比如数学就是对现实世界的一种抽象。只要我们能把现实世界的各种问题建立成数据模型(如,建立各种维度的向量),我们就可以用数学来求解,这也是机器学习的本质。
</li>
<li>
**自省能力**。所谓自省能力就是自己找自己的难看。当你得到一个解的时候要站在自己的对立面来找这个解的漏洞。有点像左右手互博。这种自己和自己辩论的能力又叫思辨能力。将自己分裂成正反方左右方甚至多方站在不同的立场上来和自己辩论从而做到不漏过一个case从而获得完整全面的问题分析能力。
</li>
在这方面,我对自己的训练如下。
1. 对于一个场景,制造出各种不同的问题或难题。
1. 对于一个问题,努力寻找尽可能多的解,并比较这些解的优劣。
1. 对于一个解,努力寻找各种不同的测试案例,以图让其健壮。
老实说,要获得这三种能力,除了你要很喜欢思考和找其它人来辩论或讨论以外,还要看你自己是否真的善于思考,是否有好奇心,是否喜欢打破沙锅问到底,是否喜欢关注细节,做事是否认真,是否严谨……
这一系列的能力最终能构建出你强大的思考力,而这个思考力会直接转换成你的求知和学习能力。其实,我也是在不断地加强自己的这些能力。
# 总结和归纳
对自己的知识进行总结和归纳是提高学习能力的一个非常重要的手段。这是把一个复杂问题用简单的语言来描述的能力。就像我小时候上学时,老师让我们写文章的中心思想一样。这种总结和归纳能力会让你更好地掌握和使用知识。
也就是说,我们把学到的东西用自己的语言和理解重新组织并表达出来,本质上是对信息进行消化和再加工的过程,这个过程可能会有信息损失,但也可能会有新信息加入,本质上是信息重构的过程。
**我们积累的知识越多,在知识间进行联系和区辨的能力就越强,对知识进行总结和归纳也就越轻松**。而想要提高总结归纳的能力,首先要多阅读,多积累素材,扩大自己的知识面,多和别人讨论,多思辨,从而见多识广。
不过,我们需要注意的是,如果只学了部分知识或者还没有学透,就开始对知识进行总结归纳,那么总结归纳出来的知识结构也只能是混乱和幼稚的。因此,**学习的开始阶段,可以不急于总结归纳,不急于下判断,做结论,而应该保留部分知识的不确定性,保持对知识的开放状态**。当对整个知识的理解更深入,自己站的位置更高以后,总结和归纳才会更有条理。总结归纳更多是在复习中对知识的回顾和重组,而不是一边学习一边就总结归纳。
我们来总结一下做总结归纳的方法:**把你看到和学习到的信息,归整好,排列好,关联好,总之把信息碎片给结构化掉,然后在结构化的信息中,找到规律,找到相通之处,找到共同之处,进行简化、归纳和总结,最终形成一种套路,一种模式,一种通用方法**。
要训练自己这方面的能力,你需要多看一些经典的方法论图书,看看别人是怎样总结和归纳知识的。你可以在一开始模仿并把自己的理解的知识给写出来,写博客会是一种很好的方式。另外一种更好的方式是讲一遍给别人听。总之,你需要把你总结归纳的知识公开出来,给别人看,接受别人的批评和反馈,这样你才能成长得更快。其实,我也在锻炼这样的能力。
如果你在Coolshell上看过我写的《[TCP的那些事儿](https://coolshell.cn/?s=TCP%E7%9A%84%E9%82%A3%E4%BA%9B%E4%BA%8B%E5%84%BF)》你就能知道我对《TCP/IP详解》这本这么厚的书以及一些日常工作经验的总结我写成了两篇比较简单的博客。你需要像我一样扩大自己的知识面然后学会写博客就能慢慢地拥有这种能力了。这种将信息删减、精炼和归纳的方法可以让你的学习能力得到快速的提升。当你这么做的时候一方面是在锻炼你抓重点的能力另一方面是在锻炼你化繁为简的能力。这两种能力都是让你高效学习的能力。
最后,还想说一下,一般来说,拥有这样能力的人,都需要有在更高的维度上思考问题的能力。比如一些名人的金句,就是这种能力的体现。这种能力需要你非常深入的思考,需要你的阅历和经验,当然,和聪明人在一起也是提升这种能力的最有效的选择。
# 实践出真知
所谓实践出真知,也就是学以致用,不然只是纸上谈兵,误国误民。只有实践过,你才能对学到的东西有更深的体会。就像我看 《Effective C++》和《More Effective C++》这两本书一样,一开始看的时候,我被作者的那种翻来覆去不断找到答案又否定自己的求知精神所折服。但是,作者的这种思维方式只有在我有了很多的实践和经验(错误)后,才能够真正地体会为什么是这样的。
这两书不厚但是我看了十多年书中的很多章节我都可以背出来但是我想得到的不是这些知识而是这种思维方式这需要我去做很多的编程工作才能真正明白才会有斯科特·迈耶斯Scott Meyers那样的思维方式这才是最宝贵的。
另外,实践出真知也就是英文中的 Eat your own dog food。吃自己的狗粮你才能够有最真实的体会。那些大公司里的开发人员写完代码自己不测试自己也不运维我实在不知道他们怎么可能明白什么是好的设计好的软件不吃自己的狗粮不养自己的孩子他们就不会有痛苦没有痛苦就不会想改进没有改进的诉求也就不会有学习的动力没有学习就不会进步没有进步就只会开发很烂的软件……不断地恶性循环下去。
实践是很累很痛苦的事但只有痛苦才会让人反思而反思则是学习和改变自己的动力。Grow up through the pain 是非常有道理的。
# 坚持不懈
坚持不懈是一句正确的废话。前段时间我在我的读者群中发起了一个名为ARTS的活动。每人每周写一个ARTSAlgorithm 是一道算法题Review是读一篇英文文章Technique/Tips是分享一个小技术Share是分享一个观点。我希望大家可以坚持一年但是我也相信能够坚持下来的人一定很少绝大多数人都是虎头蛇尾的但是我依然相信会有人坚持下来的。
坚持是一件反人性的事所以它才难能可贵也更有价值。我从2003年写blog到今天15年了看书学习写代码我都会一点一点的坚持。人不怕笨怕的是懒怕的是找到各种理由放弃。
这里我想鼓励一下你。现在很多国外的在线视频课都是3-5分钟一节课一共20节课总时长不到两个小时。然而你会发现能坚持看完的不到千分之一。当年Leetcode只有151道题的时候一共有十几万人上来做题但全部做完的只有十几个万分之一。所以只要你能坚持就可以超过这个世界上绝大多数人。想一想如果全中国有100万个程序员只要你能坚持学习技术2-3年你就可以超过至少99万人了可能还更多
当然,坚持也不是要苦苦地坚持,有循环有成就感的坚持才是真正可以持续的。所以,**一方面你要把你的坚持形成成果晒出来,让别人来给你点赞,另一方面,你还要把坚持变成一种习惯,就像吃饭喝水一样,你感觉不到太多的成本付出。只有做到这两点,你才能够真正坚持**。
希望我的这些话可以让你有足够的动力坚持下去。
# 小结
总结一下今天的内容。我分享了系统学习、举一反三、总结归纳、实践出真知和坚持不懈等几个方面的内容。
<li>
在系统学习中,我给出了我学习时用的学习模板,它不但有助于你学习到技术的精髓,更能帮你提升你的学习高度。坚持几年,你一定能在某个领域成为炙手可热的佼佼者。
</li>
<li>
在举一反三中,我分享了如何获得这种能力的方法。
</li>
<li>
在总结和归纳中,我指出,积累的知识越多,在知识间进行联系和区辨的能力越强,总结归纳的能力越强,进而逐渐形成在更高维度上思考问题的能力。
</li>
<li>
在实践出真知中,我阐明了实践的重要性,并认为,只有实践过,才能对学到的东西有更深的体会。
</li>
<li>
最后,我强调,虽然学习方法很重要,但坚持不懈更为重要,并给出了怎样做才能让自己对学习这件反人类的事儿坚持不懈。
</li>
下篇文章中,我将分享一些学习技巧,也是我这么多年来行之有效的。希望对你有帮助。
下面是《高效学习》系列文章的目录。
- [端正学习态度](https://time.geekbang.org/column/article/14271)
- [源头、原理和知识地图](https://time.geekbang.org/column/article/14321)
- [深度,归纳和坚持实践](https://time.geekbang.org/column/article/14360)
- [如何学习和阅读代码](https://time.geekbang.org/column/article/14380)
- [面对枯燥和量大的知识](https://time.geekbang.org/column/article/14389)

View File

@@ -0,0 +1,136 @@
<audio id="audio" title="99 | 高效学习:如何学习和阅读代码" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/12/68/12cc434cd3c3077814539be765d22568.mp3"></audio>
# 读文档还是读代码
杰夫·阿特伍德Jeff Atwood说过这么一句话“[Code Tells You How, Comments Tell You Why](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/)”。我把其扩展一下:
- **代 码 =&gt; What, How &amp; Details**
- **文档/书 =&gt; What, How &amp; Why**
可见,**代码并不会告诉你 Why**看代码只能靠猜测或推导来估计Why是揣测不准确所以会有很多误解。**而且我们每个人都知道Why是能让人一通百通的东西也是能让人醍醐灌顶的东西**。
但是,**代码会告诉你细节**,这是书和文档不能给你的。**细节是魔鬼,细节决定成败**。这样的话我们不但听过很多我们做技术的也应该体会过很多。当然我们也要承认这些代码细节给人带来的快感毕竟不如知道Why后的快感大至少对我是这样的
**书和文档是人对人说的话,代码是人对机器说的话**(注:代码中有一部份逻辑是控制流程的逻辑,不是业务逻辑)。所以:
<li>
**如果你想知道人为什么要这么搞,那么应该去看书**像Effective C++、Code Complete、Design Pattern、Thinking in Java等**看文档**。
</li>
<li>
**如果你要知道让机器干了什么?那你应该看代码!**就像Linus去看zlib的代码来找性能问题。
</li>
因此,我认为都比较重要,关键看你的目的是什么了。
<li>
**如果你想了解一种思想,一种方法,一种原理,一种思路,一种经验,恐怕,读书和读文档会更有效率一些**因为其中会有作者的思路描述。像Effective C++之类的书里面有很多对不同用法和设计的推敲TCP/IP详解里面也会有对TCP算法好坏的比较……这些思维方式能让你对技术的把握力更强而光看代码很难达到这种级别。现在你知道什么样的书是好书了吧 ;-)
</li>
<li>
**如果你想了解的就是具体细节,比如某协程的实现,某个模块的性能,某个算法的实现,那么你还是要去读代码的**因为代码中会有更具体的处理细节尤其是对于一些edge case或是代码技巧方面的内容
</li>
另外,看看下面的几个现象,你可以自己比较一下。
<li>
很多时候,我们去读代码,那是因为没有文档,或是文档写得太差。
</li>
<li>
很多时候,**在Google、Stack Overflow、GitHub过后你会发现你掌握的知识就是一块一块的碎片既不系统也不结构化更别说融会贯通了。你会觉得自己需要好好地读一本书系统地掌握知识。你的这种感觉一定很强烈吧**。
</li>
<li>
很多时候在读别人代码的时候你会因为基础知识或是原理不懂或是你在不知道为什么的情况下要么完全读不懂代码要么会误解代码。比如如果你没有C语言和TCP原理方面的基础知识就根本读不懂Linux下TCP的相关代码。我们因为误解代码用意而去修改代码造成的故障还少吗
</li>
<li>
很多时候看到一个算法或是一个设计时比如Paxos你是不是会想去看一下这个算法的实现代码是什么样的思考一下如何才能实现得好但是如果你没看过Paxos的算法思想我不认为你光看代码实现就能收获Paxos的思想。
</li>
<li>
很多时候,**当你写代码的时候,你能感觉得到自己写的代码有点别扭,怎么写都别扭,这个时候,你也会有想去看别人的代码是怎么实现的冲动**。
</li>
类似的情况还有很多,但从代码中收获大,还是从书中收获大,在不同的场景、不同的目的下,会有不同的答案。这里,谈一谈人的学习过程吧。从学习的过程中,我们来分析一下看代码和看书这两个活动。人对新事物的学习过程基本都是从“感性认识”到“理性认识”的。
<li>
**如果你是个新手,那应该多读代码,多动手写代码**因为你需要的是“感性认识”这个时候“理性认识”你体会不到。一是因为你没有切身的感受即便告诉你Why你也体会不到。另一方面这个阶段你要的不是做漂亮而是做出来。所以在**新手阶段你会喜欢GitHub这样的东西**。
</li>
<li>
**如果你是个老手,你有多年的“感性认识”了,那么你的成长需要更多的“理性认识”**。因为这个阶段一方面你会不满足于做出来你会想去做更牛更漂亮的东西另一方面你知道的越多你的问题也越多你迫切地需要知道Why这时你需要大量地找牛人交流读牛人的书是一种特殊的人与人的交流所以**这个阶段,你会喜欢读好的书和文章**。
</li>
然而,对于计算机行业这个技术创新能力超强、技术种类繁多的行业来说,我们每个人都既是新手,也是老手。
# 如何阅读源代码
很多人问过我如何读代码。因为我在外企里工作的时间较长所以我经常接手一些国外团队写的代码。我发现虽然老外写的代码比国人好一点儿有Code Review但依然有文档缺失、代码注释不清、代码风格混乱等一些问题这些都是阅读代码的障碍。这里我把我的一些阅读源代码的经验分享给你希望对你有用。
首先,在阅读代码之前,我建议你需要有下面的这些前提再去阅读代码,这样你读起代码来会很顺畅。
<li>
**基础知识**。相关的语言和基础技术的知识。
</li>
<li>
**软件功能**。你先要知道这个软件完成的是什么样的功能,有哪些特性,哪些配置项。你先要读一遍用户手册,然后让软件跑起来,自己先用一下感受一下。
</li>
<li>
**相关文档**。读一下相关的内部文档Readme也好Release Notes也好Design也好Wiki也好这些文档可以让你明白整个软件的方方面面。如果你的软件没有文档那么你只能指望这个软件的原作者还在而且他还乐于交流。
</li>
<li>
**代码的组织结构**。也就是代码目录中每个目录是什么样的功能每个文档是干什么的。如果你要读的程序是在某种标准的框架下组织的比如Java的Spring框架那么恭喜你这些代码不难读了。
</li>
接下来,你要了解这个软件的代码是由哪些部分构成的,我在这里给你一个列表,供你参考。
<li>
**接口抽象定义**。任何代码都会有很多接口或抽象定义,其描述了代码需要处理的数据结构或者业务实体,以及它们之间的关系,理清楚这些关系是非常重要的。
</li>
<li>
**模块粘合层**。我们的代码有很多都是用来粘合代码的比如中间件middleware、Promises模式、回调Callback、代理委托、依赖注入等。这些代码模块间的粘合技术是非常重要的因为它们会把本来平铺直述的代码给分裂开来让你不容易看明白它们的关系。
</li>
<li>
**业务流程**。这是代码运行的过程。一开始,我们不要进入细节,但需要在高层搞清楚整个业务的流程是什么样的,在这个流程中,数据是怎么被传递和处理的。一般来说,我们需要画程序流程图或者时序处理图。
</li>
<li>
**具体实现**。了解上述的三个方面的内容,相信你对整个代码的框架和逻辑已经有了总体认识。这个时候,你就可以深入细节,开始阅读具体实现的代码了。对于代码的具体实现,一般来说,你需要知道下面一些事实,这样有助于你在阅读代码时找到重点。
<ul>
<li>
**代码逻辑**。代码有两种逻辑一种是业务逻辑这种逻辑是真正的业务处理逻辑另一种是控制逻辑这种逻辑只是用控制程序流转的不是业务逻辑。比如flag之类的控制变量多线程处理的代码异步控制的代码远程通讯的代码对象序列化反序列化的代码等。这两种逻辑你要分开很多代码之所以混乱就是把这两种逻辑混在一起了详情参看《编程范式游记》
</li>
<li>
**出错处理**。根据二八原则20%的代码是正常的逻辑80%的代码是在处理各种错误,所以,你在读代码的时候,完全可以把处理错误的代码全部删除掉,这样就会留下比较干净和简单的正常逻辑的代码。排除干扰因素,可以更高效地读代码。
</li>
<li>
**数据处理**。只要你认真观察就会发现我们好多代码就是在那里倒腾数据。比如DAO、DTO比如JSON、XML这些代码冗长无聊不是主要逻辑可以不理。
</li>
<li>
**重要的算法**。一般来说我们的代码里会有很多重要的算法我说的并不一定是什么排序或是搜索算法可能会是一些其它的核心算法比如一些索引表的算法全局唯一ID的算法、信息推荐的算法、统计算法、通读算法如Gossip等。这些比较核心的算法可能会非常难读但它们往往是最有技术含量的部分。
</li>
<li>
**底层交互**。有一些代码是和底层系统的交互一般来说是和操作系统或是JVM的交互。因此读这些代码通常需要一定的底层技术知识不然很难读懂。
</li>
</ul>
</li>
<li>
**运行时调试**。很多时候代码只有运行起来了才能知道具体发生了什么事所以我们让代码运行进来然后用日志也好debug设置断点跟踪也好。实际看一下代码的运行过程是了解代码的一种很好的方式。
</li>
总结一下,阅读代码的方法如下:
- 一般采用自顶向下,从总体到细节的“剥洋葱皮”的读法。
- 画图是必要的,程序流程图,调用时序图,模块组织图……
- 代码逻辑归一下类,排除杂音,主要逻辑才会更清楚。
- debug跟踪一下代码是了解代码在执行中发生了什么的最好方式。
对了阅读代码你需要一个很好的IDE。我记得以前读C和C++代码时有一个叫source insight的工具就大大提高了我的代码阅读效率。说白了就是可以查看代码间相互的调用reference的工具这方面Visual Studio做得是非常好的。
# 小结
总结一下今天的内容。我先跟你探讨了“是读文档,还是读代码”,分析对比了从文档和代码中各自能收获到哪些东西,然后给出建议,如果想了解思想、方法和原理,读书和读文档会更有效率;如果想知道具体细节,还是应该读代码。随后分享了一些我阅读代码和源代码时候的方法和技巧。希望对你有启发。
下篇文章是《高效学习》系列的最后一篇,我将分享一下面对枯燥和量大的知识时,我们该怎样做。
下面是《高效学习》系列文章的目录。
- [端正学习态度](https://time.geekbang.org/column/article/14271)
- [源头、原理和知识地图](https://time.geekbang.org/column/article/14321)
- [深度,归纳和坚持实践](https://time.geekbang.org/column/article/14360)
- [如何学习和阅读代码](https://time.geekbang.org/column/article/14380)
- [面对枯燥和量大的知识](https://time.geekbang.org/column/article/14389)