如何阅读别人的代码?

来源:未知

点击:

  团队内部组织了一次阅读代码的workshop,给一个完全陌生的项目,在三个小时内了解项目的大致内容并写文档。主要目的是训练快速高效地了解新项目的能力。以下是workshop上得到的比较有用的点:

  从功能说明开始

  当我们获得一个新项目时,第一件事不是去研究代码,而是从功能上理解该项目的用途。如果是UI,在其创建的页面上操作操作。如果是领域建模的项目,了解其代表的基本业务逻辑。如果它是某个事务处理项目,了解该过程的主要步骤。在研究代码如何实现之前,我们需要知道它的用途。

  找到网址提交class

  入口class定义了代码的边界。当我们处理一个已知的项目时,入口似乎是透明的,因为通常我们不会经常修改入口。但是接到一个我们不了解的项目,找到入口class总是好的。这样我们就可以专注于入口之后的代码,而忽略入口之前的代码。从这里开始,至少我们知道将第一个debugger放在哪里。

  问自己一个问题:代码是如何分解

  对于初次的分析,只有一个目标:回答代码是如何分解的。没有目标,我们很容易被某些实现所吸引,并迷失在代码丛林中。初步分析应避免过于深入。通常,代码库越大,我们应该分析的越抽象。

  浏览包结构用以对项目有大致印象

  当我们看到一个UI项目包含models,views,controllers时,我们可以猜测该模块使用了MVC模式。当我们看到一个项目包含services,sessions,repository,database我们可以发现它们之间的分层关系。有些项目的包的命名用了领域内语言如:queue,classification,filter,等等,如果我们不了解域,那么我们很难弄清楚它代表什么。当我们看到一些utilities,helpers,tools之类的包时,我们知道可以在初次分析中跳过它们。但是,有时由于包命名的歧义性或项目的演变比较复杂,我们可能从包结构上得不到有用的信息。

  Imports有助于发现依赖关系

  通过查看每个类的 imports,我们可以快速构建依赖关系图。从 imports 中,我们可以分析内部和外部的依赖性。在一个设计良好的模块中,如果一个类具有很多外部依赖关系,则通常是边界类,其中应该没有什么业务逻辑。从这些类中,我们可以构建项目的框架。由 IntelliJ 生成的 UML 可以辅助发现依赖关系,但是如果我们对探索依赖关系图的方向不谨慎,则很容易使得 UML 过于复杂难以发现有用信息。

  从接口,类的属性和方法获中取更多信息

  我们通过接口来了解主要功能。从类的属性中,我们可以看到封装了什么。我们可以将封装的类按照读与写分类,或者按照使用的阶段分组。有时当模块设计不当或项目本身非常简单,分解可能基于方法而不是类。在这种情况下,我们需要深入分析类的方法。

  识别出设计模式可以加速分析

  当我们在代码的某些部分中找到某些模式时,就可以假设其余的代码会做什么。在这种情况下,我们不再是阅读代码,而是验证假设。我们知道该去哪里以及要看什么,因此可以更快地分析代码。这也意味着,如果我们已经了解了很多中设计模式那么阅读代码将会更快。

  检查提交历史记录,如果我们发现奇怪的代码

  提交历史可以帮助我们了解对代码是新还是旧,是被频繁修改或自创建以来很少被修改。如果发现某些代码与上下文不一致,可以检查提交历史记录。如果它们属于同一提交,则可能存在一些我们还未发现的隐藏原因。如果不是,则不一致的原因可能是由于当前开发人员与之前的想法不一。如果还想进一步的话,我们还可以检查此次提交的 ticket 的描述,用以了解这段修改是为了解决什么问题。

  当我们想了解特定部分的代码时,测试非常有用。

  有时测试也很有用。单元测试可以帮助我们理解单个类的作用,集成测试可以帮助我们理解整体业务逻辑。某些测试使用的是“when - given - then”的形式。它们是可执行文档,为我们提供了具体示例。