如何学习开源项目?

身为一个程序员,或多或少总要接触一些开源项目。如果想深入理解并掌握你喜欢的开源项目,应该如何学习才能更快速、更科学、更牢固的掌握这个开源项目呢?是否一股脑就钻进源代码的世界中呢?

learn1

现在,我就分享一套我自己总结的学习方法:“听”、“说”、“读”、“写”。没错,就是简单的四字真言。其核心本质就是一个 “了解——深入——掌握” 的过程。

当然,这一套学习方法并不仅仅局限于学习开源项目,在工作、生活中,当我们想要了解并掌握一些新技能时,同样可以融会贯通使用之。

那么,什么是「听说读写」呢?下面,我将详细解析这四字真言的意义以及如何运用。

听,顾名思义,就是听别人怎么介绍这个项目。

  1. 听官方怎么说
  2. 听大佬怎么说

原则:以官方为准。

第一步:RTFM(Read The Fucking Manual),即要听官方怎么介绍(这是最重要的,切记不要第一次就百度)。 例如:官方概述、Wiki、帮助手册等等。遇到陌生的概念或者名词,可以先 google 一下,对它们有一个大概的理解,通过这种方式,将官方的介绍过几遍,这样可以对整个项目有一个大致的理解,了解项目解决了什么问题、提供了什么功能、用到了哪些组件和技术等。再深入一点,可以跑通一下项目自带的 examples。

第二步:搜索网络上有价值的相关博文。在进行第一步后,可能因为官方文档的晦涩、自身英语阅读能力的不足等因素,还是无法真正理解;或者想了解他人是如何使用这个开源项目等等,此时我们就可以在网络上搜索一些前人的文章,来帮助自己更好理解。当然,这是一个“屎里淘金”的过程,目前中文搜索的结果中,充释着大量低质量且相互重复的文章,抑或是文章已经过时。

经过以上的两个步骤后,应该对这个项目有了一个较为清晰的理解,甚至可以上手使用这个项目。另外,最好在上手使用的过程中,对项目的目录组织结构有一个较为详细的了解,这对掌握项目的模块划分有很重要的帮助。

说,是在自己的脑海中,“说”出自己的理解。

在“听”的过程中,都是在强制接收别人的思想和理念,至于别人为什么要这么做,可能并不是很清楚,仅仅是“知其然而不知其所以然”。到这一阶段,就需要开动自己的脑筋,把他人的思想转换为自己的理解,要“知其然更知其所以然”。这是一个强调自我理解的过程。

我的自我理解的秘诀:把代码世界无限向现实世界靠拢。因为代码世界中所出现的模型、流程等,都是为了解决现实世界中出现的问题,而现实世界往往更加复杂,且定会有类似的场景能够解释代码世界。这便是,代码也源于生活

举个栗子,很多人对于 lua 协程无法理解得通透,或者是刚开始理解了一部分,等过一段时间后又忘记了(我曾经也经过这样的阶段)。lua 协程本质是一个逻辑片段,只是它能够被主协程启动、唤醒(coroutine.resume),它自身可以让出执行(coroutine.yield),很多人会对这两个函数的返回值和参数很迷惑。迷惑是因为理解得不够,当我们把协程套用到下面的生活场景时,一切就清晰明了了。

假如你是一个设计师,周六老板接了一个项目,交给你来做设计,并交代了一些甲方爸爸的【需求1】。你开始熬夜加班设计了【方案1】,然后把方案交给老板,老板给甲方爸爸看,甲方不满意并提出了一些【需求2】,然后老板打电话喊起了昨天熬夜的你,并让你下班前改好,你骂骂咧咧又开始加班修改,最终在下班前赶出了【方案2】,并发给老板,最终通过了老板和甲方爸爸,老板看你幸苦熬夜,给你了一些安慰,并放了你的假(TMD不给奖金)。

co = coroutine.create(
	function work(需求)
		local 方案1 = 加班设计(需求1)
		local ok, 需求2 = coroutine.yield(方案1) --方案给老板,并等待是否通过
		
		local 方案2 = 加班修改(需求2)
		local ok,老板的安慰 = coroutine.yield(方案2) --方案再次验收
	
		设计通过()
	end
)

local ok, 方案1 = coroutine.resume(co, 需求1)
local 不通过, 需求2 = 给甲方爸爸(方案1)

local ok, 方案2 = coroutine.resume(co, 需求2)
local 通过 = 给甲方爸爸(方案2)
coroutine.resume(co, 老板的安慰)

通过上面这个现实世界的场景和代码世界的结合,会发现这些代码中原本复杂晦涩的概念就变得非常清晰,且记忆得更加牢固,因为你已经有了自己的理解。

读,字面意思,就是阅读代码。

阅读代码是一个打磨细节的过程,正所谓:“细节决定成败”。虽然经过前两个阶段,或许对整个项目有了不错的理解,也掌握了最核心的部分,但是,如果不深入到代码内部,可能很多细节、具体的实现方式等,并不是完全掌握。这个过程是一个长久且枯燥的过程,但是却是提升技能、增长底气的必经之路。在阅读代码的过程中,将会有诸多提升:

  • 能够学到别人优秀的编程方法和思路,反思自己编码过程中的不足以及如何改进。
  • 能了解到一些算法的具体实现方式。
  • 在此过程中,如果遇到自己知识薄弱的部分,还能跳出来自我补习一下。

当然,阅读代码也是要科学的方式,切不可一头跳进代码的长河中,这样很容易迷失于其中。我的方法是:先主干后枝干,且画出其中的数据结构关系图。关于如何画图,可以参考我之前的这篇博文

另外,在阅读代码时,不要直接去看代码的实现,应当先整理去关键函数的调用关系,先忽略实现细节,然后由浅入深,否则会给自己带来很大的挫败感。 learn2

这里可以推荐两个工具,calltreecflow,前者已经是一个上古的工具了,网上搜索了很多方法,但是都不能通过编译(可能是我姿势不对),最终找到了一个别人编译好的,已经放到我的 repo,后者也是一个类似的工具,并提供了 apt 安装方式。

写,就是做笔记,把自己掌握的知识记录下来。

所谓“好记性不如烂笔头”,千万不要迷信自己的记忆力。在我看来,写代码就是一个手工活,一段时间不上手,基本上就会把知识还回去。

我们可以做笔记,把这些掌握的知识通过文字记录下来,不论是通过云笔记还是个人博客。记录,不仅仅是一个备忘或者后期复习的作用,而且在我们写作记录的过程中,会更进一步帮助我们理解和掌握学到的知识。