这是我拿下 Google一面的源码阅读技巧!

嗨,你好呀,我是猿java

在我的技术文章中,经常会通过分析一些核心源码来帮助读者更好地理解该技术点,自己也一直想写一篇文章来介绍如何阅读源码,刚好这段时间在 Google 1面中遇到了类似的题目:如何阅读源代码?因此,这篇文章,我将结合自身的经验以及身边一些小伙伴的经验,聊聊如何高效阅读源代码。

为什么要阅读源代码?

通常来说,作为一个技术人员,阅读源码的动力可以归纳为下面三点:

1. 解决问题

在实际工作中,我们肯定会遇到 Google搜索无法解决的问题,而阅读源码是解决问题最靠谱的一种方法,因此,对于很多程序员来说,解决工作中遇到的实际问题,是我们阅读源码最常见的一种原因。

2. 修炼基本功

作为程序员,技术层次的高低很多时候拼的是基本功,因此,能高效地理解代码是一个程序员的核心竞争力,这种能力与具体的技术栈没有关系,它是一种通用的、可迁移的能力。

如果留心观察,你会发现那些基本功扎实的人,常常能能够很快的上手一项新技术和新语言,因此,阅读源码是修炼基本功的一种很有效的方式。

3. 开阔视野

书到用时方恨少,阅读源码可以很好地开阔自己的技术视野,在生活中,我们可以发现,那些经常阅读的人文字功底一般不会太差。因此,经常阅读优秀源码的人,他的代码风格,设计思维也在被潜移默化的熏陶,久而久之,代码的优雅性以及质量就和其他人产生了差距。

另外,在实际工作中,大多数程序员很容易把自己局限在几个特定领域,比如:从事电商领域,一般对金融领域就会不太熟悉。因此,作为程序员,如果要持续成长,除了掌握当前正在从事的领域,还需要不断尝试新领域,从深度和广度拓展对编程的理解。

阅读什么样的源代码?

现如今,优秀的开源代码太多了,我该阅读什么样的源代码?这是一个困扰很多程序员的问题,在这百花齐放的源码中,我们该如何选择呢?

下面将从下面 3个角
1. 学习新语言/新框架

如何你是学习一门新的编程语言或者学习一个新的技术框架,那官方文档是最好的源码,首先你需要先阅读官网的Overview,了解它是什么?整体概要是什么?然后阅读 Quick Start,了解其快速入门指南,帮助自己快速上手,再然后在更深入地使用中查阅其对应的 API等等。

2. 学习新领域

如果你是学习一个新领域,这时候适合阅读该领域的一些经典项目,我们可以从 Github上获取其源码,然后结合一些优秀的课程或者视频,双管齐下,这样可以让你快速地了解该领域。
3. 学习某个方法

如果你想学习某个方法,比如 Java中的HashMap的put() 是如何实现的,为什么它不是线程安全的?

那你需要读 JDK标准库的源码,进入源码中查看对应的实现。如果你了解了 HashMap,那你应该发散性的阅读 ConcurrentHashMap 的源码,对两者进行对比,这样才算是真正的掌握了HashMap,了解了两者之间的差异。

有的小伙伴可能会问,我知道自己想要阅读什么样的代码,但是我不知道该从哪里开始阅读?因此,接下来我们将分析如何阅读,这里以 Java为例:

如何阅读源代码?

我自己总结的经验是:先大(粗)再小(细),先全局再细节。

如何理解呢?请听我一一道来。

首先,也是最重要的:一定不要害怕阅读英文资料,毕竟源码的世界都是英文。

全局

我们可以借鉴读书的方式,大多数人在阅读一本新书时,首先是先快速浏览目录,了解整本书的章节,然后再从头开始阅读或者选择最感兴趣的章节阅读,对于阅读源码也一样,我们切莫一上来就扎进代码细节里面,因为读书时,我们从头到尾的阅读问题不是很大,但是,阅读代码如果也是这样从头读到尾就很容易犯困,而且效果也不好,最终很容易放弃。通常,我们应该先了解该源码的整体结构,比如包结构,类结构等等,这里以 Java并发包为例:

  • java.util.concurrent:项目的主包
  • java.util.concurrent.aotmic:原子类包
  • java.util.concurrent.lock:锁相关的类包
  • ....:其他一些类

理解了这些包和类的结构之后,我们对整个源码结构有了一个系统性的了解,脑海里就有了一张粗略的地图。

细节

在了解了全貌之后,接下来就是了解源码的细节,这里,我也分享几个诀窍:

1. 带着问题看源码

当我们阅读源码时,可以尝试着带一些问题,这样可以在源码中找答案,增加阅读源码的目的性。例如,阅读 Springboot源码时,我们可以问自己:​Spring是如何加载Bean的?​它又是如何卸载Bean的?

有了问题,在心里就有一个明确的目标,你也可以先对问题做出一些猜想,然后从代码里面去寻找真相,听起来是不是很想侦探破案​?​随着读代码的次数多了,经验足了,你就能摸索出很多阅读的规律,这就是带着问题看源码的魅力。

2. 运行和 Debug源码

有时候,不知道代码的关系时,我们可以通过调试的方式来运行和理解代码,可以尝试在代码中添加一些断点(或打印日志),这样,我们就可以像调试自己的代码一样,去理解源代码的整个运行过程。​下面总结了我经常使用的几个方法:

  • 设置断点:在关键方法或逻辑上设置断点。
  • 单步执行:逐步执行代码,观察程序的执行顺序。
  • 打印语句:如果可以修改源码,可以增加一些打印语句,帮助理解。
  • 查看变量:在调试视图中查看变量的值和变化。

3. 整理代码关系

在阅读源代码的过程中,我们不能仅仅是读,还需要用笔或工具画出类,接口或者模块之间的关系图以及主要的流程图等,因为这些图就像是源代码的地图,可以帮助我们更好地理解代码之间错综复杂的关系。当我们能够把代码或者模块之间的关系理清楚时,对于源码的理解是不是又更进一步了​?​

关于UML画图工具,推荐3个比较好的工具:
excalidraw
draw.io
ProcessOn

4. 深入理解源码

上面三方面其实还是对代码结构的一个理解,因此,接下来需要我们更深入地去理解代码,比如它的架构思想,设计模式,设计原则等。通常可以从下面的角度出发:

  1. 理解设计模式:很多Java项目使用了设计模式,如单例模式、工厂模式、观察者模式等。识别和理解这些设计模式的使用,可以帮助你更好地理解代码的设计思路和扩展性。

  2. 理解异常处理:查看代码中异常处理的方式,理解异常是如何被捕获和处理的。注意异常的传播和日志记录,这对于理解程序的稳健性和错误处理机制很重要。

  3. 理解性能优化:阅读代码时,留意性能优化的实现。例如,使用缓存来减少计算,使用异步处理来提高响应速度等。理解这些优化措施可以帮助你学习高效编程的技巧。

除了上面 4个技巧之外,还有其他一些有效的方式,比如:

  1. 和同事讨论:我个人很喜欢CR(Code Review),一方面是CR别人的代码,一方面是让别人 CR我的代码,在 CR的过程中查缺补漏,同时学习他人的优点​。

  2. 参与社区讨论:参与开源项目的建设,参与社区讨论也是一种有效的学习方式,比如​:Github项目​。

  3. 实践练习:在阅读源码的过程中,可以尝试修改或扩展部分功能,通过动手实践,加深对代码的理解。

总结

本文,我总结了一些自己阅读源码的经验,仅供大家参考。阅读源码是一个长期积累的过程,也是一个痛苦的过程,它比想象的要复杂得多,没有标准、系统的方法来训练这项技能。

但是,只要我们不断练习读代码,找到适合自己的方法和工具,坚持突破,随着时间和经验的增长,你会发现自己阅读得越多速度就会越快而且越高效,对代码的理解也越深入。

如果你有什么好的源码阅读方式,欢迎评论区留言,我们一起讨论,一起进步。

交流学习

最后,把猿哥的座右铭送给你:投资自己才是最大的财富。 如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。

drawing