读《左耳听风》里面关于如何高效学习的总结笔记
一、端正学习态度
1.1 认识学习金字塔
学习分为被动学习和主动学习:
- 被动学习:如听讲、阅读、视听和演示,学习内容平均留存率为 5%、10%、20%和 30%。
- 主动学习:如通过讨论、实践和教授给他人,学习内容平均留存率会提升到 50%、75%和 90%。
被动学习时听别人在讲、我们在被动的接收他人的思想,被他人灌输,所以留存率并不会很高;
但是主动学习,是自己在思考论证、在操作和在输出,这才是自己掌握的学习能力。
1.2 深度学习
深度学习就是通过自己实际操作进行学习,一定要实操,比如学习英语,就要找人不断的说和讲,而不是死记硬背单词。
并且学习不是努力读更多的书,盲目追求阅读的速度和数量,这会让人产生低层次的勤奋和成长的感觉,这只是在使蛮力。要思辨,要践行,要总结和归纳,否则,你只是在机械地重复某件事,而不会有质的成长的。
深度学习的关键点,换言之,如何进行深度学习?
- 高质量的信息源和第一手知识
- 把知识连成地图,将自己的理解反述出来
- 不断地反思和思辨,与不同年龄段的人讨论
- 举一反三,并践行,把知识转换成技能
1.3 学习三个步骤
- 知识采集:信息源非常重要,获取信息源头、破解表面信息的内在本质,多方数据印证,是这个步骤的关键,就是信息源要靠谱,要找到知识的底层依赖。
- 知识缝合:所谓缝合,就是把信息组织起来,成为结构体的知识。这里,连接记忆,逻辑推理,知识梳理是很重要的三部分。
- 技能转换:通过举一反三、实践和练习,以及传授教导,把知识转化成自己的技能。这种技能可以让你进入更高的阶层。
要注意的是,学习不仅仅是为了找到答案,更是为了找到方法,只有掌握解题的思路和方法,才算拥有解决问题的能力,此外,还要不仅仅局限于知道,要学会理解和思考;学习的目的就是发现自己的不足和上升空间,从而才能让自己成长。学习是为了改变自己的思考方式,改变自己的思维方式,改变自己与生俱来的那些垃圾和低效的算法。总之,学习让我们改变自己,行动和践行,反思和改善,从而获得成长。
二、源头、原理和知识地图
2.1 挑选知识和信息源
要学会挑选信息源,一般要满足以下几点
- 第一手资料,不是被别人消化过,添油加醋的二手资料
- 是靠谱的,有大公司背书的,被时间和实践检验过的
- 也应该是加入了自己的思考,可以引人深思的,所谓信息的密集很大的文章
2.2 勿在浮沙筑高台:注重基础和原理
如果了解底层的 Socket 编程,了解多路复用和各种 I/O 模型(select, poll, epoll, aio, windows completion port, libevent 等),那么,对于 Node.js、Java NIO、Nginx、C++ 的 ACE 框架等这些中间件或是编程框架,你就会发现,无论表现形式是什么样的,其底层原理都是一个样的。
无论是 JVM 还是 Node,或者是 Python 解释器里干了什么,它都无法逾越底层操作系统 API 对“物理世界”的限制。而当你了解了这个底层物理世界以后,无论那些技术玩成什么花样,它们都无法超出你的掌控(这种感觉是很爽的)。
说白了就是了解底层,上层应用都是基于底层的,而且底层的基础知识和原理类的知识,都是经历过长时间考验的,也是历史上任务的智慧结晶,比如:TCP 协议的状态机,可以让你明白,如果你要设计一个异步通信协议,状态机是一件多么重要的事,还有 TCP 拥塞控制中的方式,让你知道,设计一个以响应时间来限流的中件间是什么样的。
3.3 使用知识图谱
大概意思就是,可以让自己把类似的知识归类,并且,学习一门新技术,要问自己,学习这个新知识的目的是什么,他解决了旧知识的什么痛点,又是如何解决的,为什么这样解决
三、深度,归纳和坚持实践
3.1 系统的学习
学习某个新技术,要多问自己几个为什么,建议通过填写以下知识模板的问题,都了解了,才算是自己学习了这个技术了
- 这个技术出现的背景、初衷和要达到什么样的目标或者想要解决什么问题。如果不知道这个,可能会理解不了里面的设计理念
- 这个技术的优势和劣势分别是什么,或者说,这个技术的 trade-off 是什么。要清楚这个技术的优势和劣势
- 这个技术适用的场景。一般分为业务场景和技术场景
- 技术组成部门和关键点。就是技术的核心思想和核心组件
- 技术的底层原理和关键实现。了解这个东西底层依赖了什么技术,参考 docker 底层技术剖析(Docker | 酷 壳 - CoolShell)
- 已有的实现和它之间的对比。
3.2 举一反三
如何学会举一反三?首先咱们拆分下举一反三的能力,可分为以下三种基本能力
- 联想能力:同一种事物不同用法,或联想与之相关的事物
- 抽象能力:这点还不太理解,解决问题的时候要学会试着把这个问题抽象
- 自省能力:就是自己找自己的毛病然后解决,比如说实现了一个功能点,要想想这样实现会不会有啥问题,如果怎么怎么样,会不会出什么问题,会的话如何解决
如何训练自己举一反三的能力?
- 对于一个场景,制造出不同的问题或难题
- 对于一个问题,努力寻找尽可能多的解,并比较这些解的优劣
- 对于一个解,努力寻找各种不同的测试用例,以图其健壮
3.3 总结归纳
做总结归纳的方法:把你看到和学习到的信息,归整好,排列好,关联好,总之把信息碎片给结构化掉,然后在结构化的信息中,找到规律,找到相通之处,找到共同之处,进行简化、归纳和总结,最终形成一种套路,一种模式,一种通用方法。
3.4 实践出真知
要学以致用,别空谈理论,实践是很累很痛苦的事,但只有痛苦才会让人反思,而反思则是学习和改变自己的动力。
3.5 坚持不懈
说到底还是靠坚持,当然,坚持也不是要苦苦地坚持,有循环有成就感的坚持才是真正可以持续的。所以,一方面你要把你的坚持形成成果晒出来,让别人来给你点赞,另一方面,你还要把坚持变成一种习惯,就像吃饭喝水一样,你感觉不到太多的成本付出。只有做到这两点,你才能够真正坚持。
四、如何学习和阅读代码
4.1 读文档还是读代码
杰夫·阿特伍德(Jeff Atwood)说过这么一句话:“Code Tells You How, Comments Tell You Why”。
- 读文档:知道为什么要这样做,重思想
- 读代码:知道是具体如何做,重实现
如果你想了解一种思想,一种方法,一种原理,一种思路,一种经验,恐怕,读书和读文档会更有效率一些;如果你想了解的就是具体细节,比如某协程的实现,某个模块的性能,某个算法的实现,那么你还是要去读代码的。
4.2 如何阅读源代码
建议满足以下条件后再去阅读源码:
- 基础知识:要有相关语言的基础技术知识
- 软件功能:要熟悉这个玩意儿到底是干啥的,有啥功能特性
- 相关文档:要读过阅读软件的相关文档,Readme 也好,Release Notes 也好,Design 也好,Wiki 也好,这些文档可以让你明白整个软件的方方面面
- 代码的组织结构:要知道每个包都是干啥的,每个目录都是啥样的功能
然后接下来可以了解这个软件是由哪部分代码构成的
- 接口抽象定义:任何代码都会有很多接口或抽象定义,其描述了代码需要处理的数据结构或者业务实体,以及它们之间的关系,理清楚这些关系是非常重要的。
- 模块粘合层:中间件,代理委托,依赖注入等
- 业务流程:不必关心细节,站在高层看数据处理流向,一般自己画一个数据流程图或时序图
- 具体实现:上述三个理解了,大概心里有数了 ,现在可以看具体实现,但是看的时候要注意看重点
- 注意业务逻辑和控制逻辑分开看:业务逻辑不必多言,就是业务处理逻辑;控制逻辑就是 flag 之类的控制变量、多线程处理、异步控制、RPC 调用及对象序列化反序列化这些
- 出错处理:如果没有特殊情况,出错处理这些东西其实可以不太关注,排除此干扰因素,高效阅读代码
- 数据处理:比如倒腾数据的 DAO、DTO 这些,不是主要逻辑,也可以不关注
- 重要的算法(核心关注):比如信息推荐算法,全局唯一 ID 算法,一般都比较难读,但是也是最有技术含量的一部分
- 底层交互:和操作系统或 JVM 的交互,通常需要底层知识,不然很难读懂
- 运行时调试:debug 一下,自己跑跑看看,会好很多
4.3 阅读代码步骤总结
- 一般自顶向下,从总体到细节的读法
- 画图是必要的,程序流程图,调用时序图,模块组织图
- 代码逻辑归类,排除杂音,关注主逻辑
- debug 跟踪一下代码,跑一跑具体看看正儿八经跑起来数据逻辑等等是啥样的
- 要有一个好用的 IDE,读代码可以跳来跳去,效率也高
五、面对枯燥和量大的知识
5.1 如何面对枯燥的知识?
一般枯燥的知识都是比较偏理论的
- 面对这个知识,要想一下自己为什么要学?然后先了解一下使用场景,学点实用的操作,再回过头看理论;比如说想学《TCP/IP 详解》,可以自己先试着写一个通过网络通讯的 demo 软件,然后再回过头来看,到底是咋做到的,就能收发消息了
- 学习需要反馈,要带着问题去学习,学完之后问题解决,这个反馈会很棒
- 找牛人讲解,也是不错的手段
5.2 如何面对大量的知识
- 一点一点学,一口一口吃,注重基础,画知识图,多问为什么,多动手,坚持
- 学习的目的,是要学到本质上,学到原理上,要经得住考验的,把学习当做投资
- 带着问题去学习,带着需要解决的挑战去学习,会获得源源不断的学习驱动力
- 多做笔记多分享,学习完毕及时输出
- 有条件的话可以找个同路人,有人同行会好很多;就算找不到,读者和观众也会给你点赞,这也是动力