如何正确的阅读代码【译】

如何阅读代码而不扯掉自己的头发

  1. 写更多代码
  2. 阅读更多代码
  3. 每天重复以上

这是我再转行做编程几乎两年后给自己的建议。幸运的是,现在网络上有大量的课程和辅导来教会我们如何编码。不幸的是,现在依旧几乎没有什么指导我们如何阅读代码的资源。
这是一个巨大的差距,目前越来越多的毕业生进入到技术领域,对阅读源码的强调从未如此重要。就像Brandon Bloom所说的:

如果代码在你的机器上运行,那就是你的软件,你要为此负责,你必须理解它们。

Yes,you.

虽然每一个程序员都应该阅读代码,但是他们并没有。很多程序员选择避免阅读代码的原因是因为阅读别人的代码很难,这让人沮丧,并且让他们觉得自己很蠢。我了解这种感受,因为我的感觉也是这样。

事情并不是一定要这样

当我阅读其他人的代码的时候,我想出了一个阅读过程,这个过程只包含三步。很多人可能已经遵循这三步了,但是我保证还存在很多人并不是这样的。

以下是我的步骤。

1.选择一个特殊的兴趣点

当我第一次尝试阅读代码的时候,那真是一场灾难。

那时候我在学习Sinatra,我想深入的了解下底层细节。对于从哪里开始我一无所知。不开玩笑的说,我找到了Github上的仓库,开始盲目随机挑选文件。

我想我可以花一下午的时间学习它,并且用一顿晚餐的时间牢牢的掌握它。终究,阅读我自己的代码就简单多了,那么区别到底在哪呢?

我们都知道是怎么回事了,我只想说,阅读别人的代码的感觉就像撞上了一堵满是文字的墙。

duang,duang,duang

我一次想学习的太多了,很多初学者在第一次尝试阅读源码的时候都会犯一样的错误。

思维模型是一步一步建立起来的,代码应该用一样的方式阅读。

相比较通过艰难险阻来消化1000行代码,不如专注于一个单独的主题。如果可以分解成一个单独的方法就更好了。

有一个狭小的目标可以帮助你了解什么是有相关的,什么是无关的。没有必要在不相关的地方浪费精力。

无论如何,选择一个特殊的主题并不会解决你所有的问题。现在依旧有一个问题,那就是如何从代码库中找到相关的代码。

这时候步骤二就来啦。

2.找到那根松散的线

现在你有了一个明确的要学习的方法,下一步要做什么呢?

我们非常幸运,编程语言都有调查工具。

不管你想知道一个对象的一个类,一个类的父类,追踪堆栈,或者某个特定方法的所有者,大多数语言都提供这些特性。当你开始解开代码库的挂毯时,你会找到很多可以追寻的松线。

与其用文字解释这个概念,我宁愿用代码展示给你。

调查

假设我想学习更多关于ActiveRecord相关的内容,我会将我的注意点集中在belongs_to方法,试图理解它是如何影响我的的ActiveRecord模型的。

ActiveRecord是Rails的一部分,Rails是以Ruby构建的,Ruby提供了大量的研究工具。

我的第一个方法是使用调试工具,比如pry gem,用来仔细的分析我的一个ActiveRecord models。以下是我选择用来调试的模型的代码。

class Comment < ActiveRecord::Base
  belongs_to :creator, foreign_key: 'user_id', class_name: 'User'
  belongs_to :post
  binding.pry
  validates :body, presence: true
end

将注意力集中在binding.pry的部分。当Rails运行到这一行代码时,pry会暂停应用的运行并打开命令控制行。

下面是我在学习这个belongs_to关联的时候在pry控制点做的简单交互。

  • 我输入的所有行都以pry >开头
  • =>后显示的是控制台的输出
pry> class = belongs_to(:post).class
=> ActiveRecord::Reflection::AssociationReflection
pry> class.ancestors
=> [ActiveRecord::Reflection::AssociationReflection,        
    ActiveRecord::Reflection::MacroReflection,
     ...omitted for brevity ]
pry> defined? belongs_to
=> "method"
pry> method(:belongs_to).owner
=> ActiveRecord::Associations::ClassMethods

以防你不了解Ruby,并且这些交互使你困惑,我提供了以下SparkNotes。

  • belongs_to :post运行时,它会返回一个AssociatonReflection类的实例。
  • MacroRefletionAssociationReflection的超类。
  • belongs_to是定义在位于ActiveRecord::AssociationsClassMethods模块中的一个方法类。

现在我有了很多引线,我应该先循着哪一条线呢?因为我对belongs_to方法本身更感兴趣,而并不想了解它的返回值,我开始研究ClassMethods模块。

3.跟随足迹

现在你有了想要遵循的线索,剩下要做的事就是追踪这条线索知道你找到想要的答案。这看上去是个很明确的步骤,但是很多初学者都在这里被绊倒。

其中一个原因就是代码库并没有目录,我们只能寄希望于维护者是以一种可读的方式组织自己的代码。

在更大的项目中有很多的维护人员,通常情况下这并不是一个问题。

在小型的项目中,你可能发现自己正在趟过一个巨大单一的文件,试图破译一个单个名称的变量,然后数不清的问自己:”这东西从哪来的?”。

Github的搜索

一个能使这个任务更简单的工具是Github的搜索工具(假设你正在阅读的工程在Github上)。Github的搜索很便利,因为它会展示出所有和你搜索内容相匹配的文件,并且给出这些匹配内容在文件中的位置。

为了获得最好的结果,你需要使你搜索的内容越明确越好,这需要你知道自己正在找的东西是什么。用你交叉的十指漫无目的得在Github中搜索是徒劳的。

回到我再步骤二中举得例子,我正在尝试在ActiveRecord::Associations中找到ClassMethods模块。通俗的来讲,我正在寻找嵌套在ActivieRecord模块中的Associations模块中的ClassMethods模块。并且我还在寻找belongs_to方法。

这是我搜索的内容。

img

显示的结果正好是我正在寻找的内容。

img

belongs_to method inside of ClassMethods

可能需要更多的研究

GitHub将显著的缩小你的搜索范围,依靠这个,我们可以找到一个更简单的点来深入的学习代码库。

不幸的是,发现一个类或者一个方法本身很少能最终解开谜团,你可能发现自己在一个一个模块间来回跳转,直到对全局有了理解。

我的情况是,belongs_to类引导我到了BelongsTO类中的build方法。这将我带到了Association超类。

build method in BelongsTo class

build method in Association class

最后,我发现belongs_to方法会导致Rails添加几个实例方法到我的模型中,包括getter和setter方法。它使用称为元编程的高级编程技术来实现这一点。

Rails还创建了一个Reflection类的实例,用于存储有关该关联的信息。

Rails API文档中是这样描述的:

Reflection enables the ability to examine the associations and aggregations of Active Record classes and objects. This information, for example, can be used in a form builder that takes an Active Record object and creates input fields for all of the attributes depending on their type and displays the associations to other objects.

好神奇。

结束

我不能保证分析其他人的程序将会是很有趣并且让人愉快的,但是这值得去做。这会给你的技能树增加一个至关重要的技能,并且提供额外的自由。你将不再需要依靠完整的文档或示例。虽然这是值得欣赏的,但是并不能解决所有问题。正如Jeff Atwood所说:

No matter what the documentation says, the source code is the ultimate truth, the best and most definitive and up-to-date documentation you’re likely to find.

不管文档是咋说的,源码都是无法否认的事实,你可以找到最好的,最可信的,最新的文档。

所以尝试一下吧!

现在肯定有一些你一直渴望了解学习的东西。 不要让代码库的大小吓倒你。 打开代码库到您最喜欢的框架并开始挖掘。 如果你按照我在这篇文章中列出的步骤,你很快就会成为一名源代码大师。

原文地址:https://medium.com/launch-school/how-to-read-source-code-without-ripping-your-hair-out-e066472bbe8d

发表评论

电子邮件地址不会被公开。 必填项已用*标注