学习方法总结

端正学习态度

学习是一件“逆人性”的事,就像锻炼身体一样,需要人持续付出,会让人感到痛苦,并随时想找理由放弃。

主动学习和被动学习

learn the pyramid learning
  • 被动学习:如听讲、阅读、视听、演示,学习内容的平均留存率为 5%、10%、20% 和 30%。

  • 主动学习:如通过讨论、实践、教授给他人,会将原来被动学习的内容留存率从 5% 提升到 50%、75% 和 90%。

只有你开始自己思考,开始自己总结和归纳,开始找人交流讨论,开始践行,并开始对外输出,你才会掌握到真正的学习能力。

所以,学习不是努力读更多的书,盲目追求阅读的速度和数量,这会让人产生低层次的勤奋和成长的感觉,这只是在使蛮力。要思辨,要践行,要总结和归纳,否则,你只是在机械地重复某件事,而不会有质的成长的。

浅度学习和深度学习

深度学习
  • 高质量的信息源和第一手的知识。

  • 把知识连成地图,将自己的理解反述出来。

  • 不断地反思和思辨,与不同年龄段的人讨论。

  • 举一反三,并践行之,把知识转换成技能。

学习有三个步骤:

  • 知识采集。信息源是非常重要的,获取信息源头、破解表面信息的内在本质、多方数据印证,是这个步骤的关键。

  • 知识缝合。所谓缝合就是把信息组织起来,成为结构体的知识。这里,连接记忆,逻辑推理,知识梳理是很重要的三部分。

  • 技能转换。通过举一反三、实践和练习,以及传授教导,把知识转化成自己的技能。这种技能可以让你进入更高的阶层。

学习是为了找到方法

学习不仅仅是为了找到答案,而更是为了找到方法。

学习是为了找到通往答案的路径和方法,是为了拥有无师自通的能力。

学习是为了找到原理

学习不仅仅是为了知道,而更是为了思考和理解。

一旦理解和掌握了这些本质的东西,你就会发现,整个复杂多变的世界在变得越来越简单。你就好像找到了所有问题的最终答案似的,一通百通了。

学习是为了了解自己

学习不仅仅是为了开拓眼界,而更是为了找到自己的未知,为了了解自己。

开拓眼界的目的就是发现自己的不足和上升空间,从而才能让自己成长。

学习是为了改变自己

学习不仅仅是为了成长,而更是为了改变自己。

学习是为了改变自己的思考方式,改变自己的思维方式,改变自己与生俱来的那些垃圾和低效的算法。总之,学习让我们改变自己,行动和践行,反思和改善,从而获得成长。

源头、原理和知识地图

挑选知识和信息源

注重基础和原理

最最关键的是,这些基础知识和原理性的东西和技术,都是经历过长时间的考验的,所以,这些基础技术也有很多人类历史上的智慧结晶,会给你很多启示和帮助。

学习就像拉弓蓄力一样,学习基础知识感觉很枯燥很不实用,工作上用不到,然而学习这些知识是为了未来可以学得更快。

使用知识图

最重要的是,当出现一些我不知道的知识点时,我就会往这棵知识树上挂,而这样一来,也使得我的学习更为系统和全面。

学习并不是为了要记忆那些知识点,而是为了要找到一个知识的地图,你在这个地图上能通过关键路径找到你想要的答案。

深度,归纳和坚持实践

系统地学习

  1. 这个技术出现的背景、初衷和要达到什么样的目标或是要解决什么样的问题。

  2. 这个技术的优势和劣势分别是什么,或者说,这个技术的 trade-off 是什么。

  3. 这个技术适用的场景。

  4. 技术的组成部分和关键点。

  5. 技术的底层原理和关键实现。

  6. 已有的实现和它之间的对比。

举一反三

  1. 联想能力。

  2. 抽象能力。

  3. 自省能力。

训练方法
  1. 对于一个场景,制造出各种不同的问题或难题。

  2. 对于一个问题,努力寻找尽可能多的解,并比较这些解的优劣。

  3. 对于一个解,努力寻找各种不同的测试案例,以图让其健壮。

总结和归纳

我们积累的知识越多,在知识间进行联系和区辨的能力就越强,对知识进行总结和归纳也就越轻松。

学习的开始阶段,可以不急于总结归纳,不急于下判断,做结论,而应该保留部分知识的不确定性,保持对知识的开放状态。

把你看到和学习到的信息,归整好,排列好,关联好,总之把信息碎片给结构化掉,然后在结构化的信息中,找到规律,找到相通之处,找到共同之处,进行简化、归纳和总结,最终形成一种套路,一种模式,一种通用方法。

将信息删减、精炼和归纳的方法,可以让你的学习能力得到快速的提升。当你这么做的时候,一方面是在锻炼你抓重点的能力,另一方面是在锻炼你化繁为简的能力。这两种能力都是让你高效学习的能力。

实践出真知

实践是很累很痛苦的事,但只有痛苦才会让人反思,而反思则是学习和改变自己的动力。Grow up through the pain, 是非常有道理的。

坚持不懈

人不怕笨,怕的是懒,怕的是找到各种理由放弃。

坚持也不是要苦苦地坚持,有循环有成就感的坚持才是真正可以持续的。所以,一方面你要把你的坚持形成成果晒出来,让别人来给你点赞,另一方面,你还要把坚持变成一种习惯,就像吃饭喝水一样,你感觉不到太多的成本付出。只有做到这两点,你才能够真正坚持。

如何学习和阅读代码

杰夫·阿特伍德(Jeff Atwood)说过这么一句话:“Code Tells You How, Comments Tell You Why”。我把其扩展一下:

  • 代 码 ⇒ What, How & Details

  • 文档 / 书 ⇒ What, How & Why

代码并不会告诉你 Why。而且,我们每个人都知道,Why 是能让人一通百通的东西,也是能让人醍醐灌顶的东西。

代码会告诉你细节。细节是魔鬼,细节决定成败。

书和文档是人对人说的话,代码是人对机器说的话。所以:

  1. 如果你想知道人为什么要这么搞,那么应该去看书(像 Effective C++、Code Complete、Design Pattern、Thinking in Java 等),看文档。

  2. 如果你要知道让机器干了什么?那你应该看代码!(就像 Linus 去看 zlib 的代码来找性能问题。)

关键看你的目的是什么:

  • 如果你想了解一种思想,一种方法,一种原理,一种思路,一种经验,恐怕,读书和读文档会更有效率一些。

  • 如果你想了解的就是具体细节,比如某协程的实现,某个模块的性能,某个算法的实现,那么你还是要去读代码的。

在 Google、Stack Overflow、GitHub 过后,你会发现,你掌握的知识就是一块一块的碎片,既不系统,也不结构化,更别说融会贯通了。你会觉得自己需要好好地读一本书,系统地掌握知识。你的这种感觉一定很强烈吧。

当你写代码的时候,你能感觉得到自己写的代码有点别扭,怎么写都别扭,这个时候,你也会有想去看别人的代码是怎么实现的冲动。

  • 如果你是个新手,那应该多读代码,多动手写代码。所以,在新手阶段,你会喜欢 GitHub 这样的东西。

  • 如果你是个老手,你有多年的“感性认识”了,那么你的成长需要更多的“理性认识”。这个阶段,你会喜欢读好的书和文章。

如何阅读源代码

  1. 基础知识。相关的语言和基础技术的知识。

  2. 软件功能。你先要知道这个软件完成的是什么样的功能,有哪些特性,哪些配置项。你先要读一遍用户手册,然后让软件跑起来,自己先用一下感受一下。

  3. 相关文档。读一下相关的内部文档,Readme 也好,Release Notes 也好,Design 也好,Wiki 也好,这些文档可以让你明白整个软件的方方面面。如果你的软件没有文档,那么,你只能指望这个软件的原作者还在,而且他还乐于交流。

  4. 代码的组织结构。也就是代码目录中每个目录是什么样的功能,每个文档是干什么的。如果你要读的程序是在某种标准的框架下组织的,比如:Java 的 Spring 框架,那么恭喜你,这些代码不难读了。

要了解这个软件的代码是由哪些部分构成的,参考列表:

  1. 接口抽象定义。任何代码都会有很多接口或抽象定义,其描述了代码需要处理的数据结构或者业务实体,以及它们之间的关系,理清楚这些关系是非常重要的。

  2. 模块粘合层。我们的代码有很多都是用来粘合代码的,比如中间件(middleware)、Promises 模式、回调(Callback)、代理委托、依赖注入等。这些代码模块间的粘合技术是非常重要的,因为它们会把本来平铺直述的代码给分裂开来,让你不容易看明白它们的关系。

  3. 业务流程。这是代码运行的过程。一开始,我们不要进入细节,但需要在高层搞清楚整个业务的流程是什么样的,在这个流程中,数据是怎么被传递和处理的。一般来说,我们需要画程序流程图或者时序处理图。

  4. 具体实现。了解上述的三个方面的内容,相信你对整个代码的框架和逻辑已经有了总体认识。这个时候,你就可以深入细节,开始阅读具体实现的代码了。对于代码的具体实现,一般来说,你需要知道下面一些事实,这样有助于你在阅读代码时找到重点。

    • 代码逻辑。代码有两种逻辑,一种是业务逻辑,这种逻辑是真正的业务处理逻辑;另一种是控制逻辑,这种逻辑只是用控制程序流转的,不是业务逻辑。比如:flag 之类的控制变量,多线程处理的代码,异步控制的代码,远程通讯的代码,对象序列化反序列化的代码等。这两种逻辑你要分开,很多代码之所以混乱就是把这两种逻辑混在一起了(详情参看《编程范式游记》)。

    • 出错处理。根据二八原则,20% 的代码是正常的逻辑,80% 的代码是在处理各种错误,所以,你在读代码的时候,完全可以把处理错误的代码全部删除掉,这样就会留下比较干净和简单的正常逻辑的代码。排除干扰因素,可以更高效地读代码。

    • 数据处理。只要你认真观察,就会发现,我们好多代码就是在那里倒腾数据。比如 DAO、DTO,比如 JSON、XML,这些代码冗长无聊,不是主要逻辑,可以不理。

    • 重要的算法。一般来说,我们的代码里会有很多重要的算法,我说的并不一定是什么排序或是搜索算法,可能会是一些其它的核心算法,比如一些索引表的算法,全局唯一 ID 的算法、信息推荐的算法、统计算法、通读算法(如 Gossip)等。这些比较核心的算法可能会非常难读,但它们往往是最有技术含量的部分。

    • 底层交互。有一些代码是和底层系统的交互,一般来说是和操作系统或是 JVM 的交互。因此,读这些代码通常需要一定的底层技术知识,不然,很难读懂。

  5. 运行时调试。很多时候,代码只有运行起来了,才能知道具体发生了什么事,所以,我们让代码运行进来,然后用日志也好,debug 设置断点跟踪也好。实际看一下代码的运行过程,是了解代码的一种很好的方式。

阅读代码的方法如下:

  • 一般采用自顶向下,从总体到细节的“剥洋葱皮”的读法。

  • 画图是必要的,程序流程图,调用时序图,模块组织图……

  • 代码逻辑归一下类,排除杂音,主要逻辑才会更清楚。

  • debug 跟踪一下代码是了解代码在执行中发生了什么的最好方式。

面对枯燥和量大的知识

如何面对枯燥的知识

如果你发现有些知识太过于枯燥,那么可以通过下面的方法解决。

  • 这个知识对于你来说来太高级了,你可能不知道能用在什么地方。

  • 人的认知是从感性认识向理性认识转化的,所以,你可能要先去找一下应用场景,学点更实用的,再回来学理论。

  • 学习需要有反馈,有成就感,带着相关问题去学习会更好。

  • 当然,找到牛人来给你讲解,也是一个很不错的手段。

如何面对大量的知识

在学习时,一定不要学在表面上,一定要学到本质,学到原理上,那些东西是不容易变的,也是经得住时间考验的。把学习当成投资,这是这个世界上回报最好的投资。

带着问题去学习,带着要解决的东西去学习,带着挑战去学习,于是每当你解决了一个问题,做了一个功能,完成了一个挑战,你就会感到兴奋和有成就感。

认真阅读文档

认真阅读用户手册不但可以让你少掉很多坑,同时,还能让你学习到很多。

其它几个实用的技巧

  1. 用不同的方式来学习同一个东西。

  2. 不要被打断。

  3. 总结压缩信息。

  4. 把未知关联到已知。

  5. 用教的方式来学习。

  6. 学以致用。

  7. 不要记忆。

  8. 多犯错误。