76

加入一个拥有庞大代码库的现有团队可能会令人生畏。什么是最好的方法;

  • 广阔; 尝试从代码中大致了解所有内容如何链接在一起
  • 狭窄的; 一次专注于一小段代码,了解它们是如何充分工作的
  • 选择一个功能来开发和学习
  • 尝试从类图和 uml 中获得洞察力,如果可用(并且是最新的)
  • 完全不同的东西?

我正在研究目前大约 20k 行的 C++ 应用程序和库(编辑:在宏伟的计划中很小!)。在行业中,我想您会得到一位经验丰富的程序员的介绍。但是,如果不是这种情况,您可以做些什么来尽快开始增加价值?

--
答案总结:

  • 在调试模式下单步执行代码以查看它是如何工作的
  • 与比您更熟悉代码库的人配对,轮流担任编码人员和观看/讨论的人员。在团队成员中轮换合作伙伴,以便知识传播。
  • 编写单元测试。从你认为代码如何工作的断言开始。如果结果如您所料,您可能已经理解了代码。如果没有,你有一个难题要解决和/或进行调查。(谢谢Donal,这是一个很好的答案)
  • 以与上述类似的方式检查功能代码的现有单元测试
  • 阅读 UML、Doxygen 生成的类图和其他文档以全面了解代码。
  • 进行小的编辑或错误修复,然后逐步建立
  • 记笔记,不要跳进去开始开发;花时间理解比生成混乱或不适当的代码更有价值。

这篇文章是the-best-way-to-familiarize-yourself-with-an-inherited-codebase的部分副本

4

19 回答 19

25

如果可能,从一些小任务开始,围绕您的问题调试代码。在调试模式下单步执行代码是了解事物如何工作的最简单方法。

于 2008-10-18T14:07:26.943 回答
18

另一种选择是为您感兴趣的功能编写测试。设置测试工具是确定系统具有哪些依赖关系以及其状态所在位置的好方法。每个测试都以关于您认为系统应该如何工作的方式的断言开始。如果结果证明是这样工作的,那么您已经取得了一些成就,并且您已经有了一些工作示例代码来重现它。如果它不能那样工作,你就有一个谜题要解决,还有一条查询线要跟进。

于 2008-10-18T14:15:08.003 回答
11

我通常向尚未提及的人建议的一件事是,在成为开发人员之前成为现有代码库的合格用户非常重要。当新开发人员进入我们的大型软件项目时,我建议他们先花时间成为专家用户,然后再开始尝试编写代码。

也许这很明显,但我看到很多人试图过快地跳入代码,因为他们渴望开始取得进步。

于 2008-10-18T15:12:29.137 回答
9

这完全取决于您是哪种学习者和哪种程序员,但是:

  • 首先是广泛 - 您需要了解范围和规模。如果它们很好,这可能包括略读 docs/uml。如果这是一个长期项目,并且您需要全面了解所有内容,那么我实际上可能会正确阅读文档。再说一次,如果他们很好的话。
  • 狭隘 - 选择一些可以管理的东西并尝试理解它。获得代码的“味道”。
  • 选择一个功能 - 如果您有信心,可能与您刚刚看到的功能不同,然后开始进行一些小的更改。
  • 迭代 - 评估事情的进展情况,看看您是否可以从更深入地重复早期步骤中受益。
于 2008-10-18T14:09:14.413 回答
7

与严格的轮换配对。

如果可能,在浏览文档/代码库时,尝试使用严格轮换的配对。意思是,你们两个人坐在一起固定一段时间(例如,2 小时的会议),然后换对,一个人将继续完成该任务,而另一个人将与另一个伙伴一起完成另一项任务。

两人结对时,你们都会学到一条知识,然后可以在轮换发生时将其提供给团队的其他成员。这样做的好处还在于,当一对新的组合在一起时,从事该任务的人(在本例中是调查代码)可以以更容易理解的方式总结和解释这些概念。随着时间的推移,每个人都应该有相似的理解水平,并希望避免“哦,只有约翰知道那一点代码”综合症。

根据我对您的情况的了解,您有一个很好的数字(3 对),但是,如果您是分布式的,或者没有按照相同的时间尺度工作,则不太可能。

于 2008-10-18T15:05:06.170 回答
6

我建议在其上运行 Doxygen 以获得最新的类图,然后再广泛使用一段时间。这为您提供了一个快速的大图,您可以在近距离接触代码时使用它。

于 2008-10-18T14:14:07.927 回答
5

我同意这完全取决于你是什么类型的学习者。话虽如此,我曾在两家公司工作过,它们一开始就有非常大的代码库。通常,我是这样工作的:

如果可能的话,在查看任何功能代码之前,我会检查已经编写好的单元测试。这些通常可以提供很多帮助。如果它们不可用,那么我执行以下操作。

首先,我在很大程度上忽略了实现,只看头文件,或者只看类接口。我试图了解每节课的目的是什么。其次,我从似乎最重要的领域开始深入实施。这很难衡量,所以偶尔我只是从顶部开始,然后在文件列表中向下工作。我称之为广度优先学习。在这个初始步骤之后,我通常会深入了解其余代码。最初的广度优先外观有助于巩固/修复我从界面级别获得的任何想法,然后深度外观向我展示了用于实现系统的模式以及不同的设计理念。通过深度优先,我的意思是你基本上使用调试器逐步执行程序,进入每个函数以查看它是如何工作的,等等。对于非常大的系统,这显然是不可能的,但是 20k LOC 并没有那么多。:)

于 2008-10-18T14:20:43.467 回答
3

与另一位更熟悉系统的程序员一起开发新功能或修复错误。这是我见过效果最好的方法。

于 2008-10-18T14:18:20.323 回答
2

我认为您需要将其与特定任务联系起来。当您有时间时,请选择您喜欢的任何方法。

当您有需要完成的事情时,请给自己一个狭窄的焦点并完成它。

于 2008-10-18T14:09:03.303 回答
2

首先,如果您有对代码有经验的团队成员,您应该安排他们与您一起对代码进行概述。每个团队成员都应向您提供有关其专业领域的信息。让多人解释事情通常很有价值,因为有些人会比其他人更善于解释,而有些人会比其他人有更好的理解。

然后,您需要在没有任何压力的情况下开始阅读代码一段时间(如果您的老板愿意,则需要几天或一周)。它通常有助于自己编译/构建项目,并能够在调试模式下运行项目,以便您可以单步执行代码。然后,开始弄湿你的脚,修复小错误并进行小的改进。希望你很快就能为一个中型项目做好准备,然后是一个大项目。在你前进的过程中继续依靠你的队友——通常你会找到一个特别愿意指导你的人。

如果你挣扎,不要对自己太苛刻——这很正常。理解大型代码库可能需要很长时间,甚至几年。实际上,通常情况下,即使经过多年,代码的某些部分仍然有些可怕和不透明。当您在项目之间出现停机时间时,您可以深入研究这些领域,并且您经常会发现,经过几次尝试后,您甚至可以弄清楚这些部分。

祝你好运!

于 2008-10-18T14:24:48.000 回答
2

让团队让您在两周内修复错误(如果您有两周时间)。他们会很乐意找人为此负责,到这个阶段结束时,您将花费大量时间解决图书馆的问题,您可能会非常了解它。

于 2008-10-18T14:54:35.537 回答
2

如果它有单元测试(我打赌它没有)。从小处着手,确保单元测试不会失败。如果你同时盯着整个代码库,你的眼睛会呆滞,你会感到不知所措。

如果没有单元测试,您需要专注于您想要的功能。运行应用程序并查看您的功能应该影响的事情的结果。然后开始查看代码,试图找出应用程序如何创建您想要更改的内容。最后更改它并检查结果是否符合您的要求。

你提到它是一个应用程序和一个库。首先更改应用程序并坚持以用户身份使用该库。那么在你学习了这个库之后,它会更容易改变。

从自上而下的方法来看,应用程序可能有一个主循环或一个主 gui 来控制所有操作。值得了解应用程序的主要控制流程。值得阅读代码,让自己大致了解应用程序的主要流程。如果它是一个 GUI 应用程序,则创建一份文件,显示存在哪些屏幕以及如何从一个屏幕到达另一个屏幕。如果是命令行应用程序,处理是如何完成的。

即使在公司中,采用这种方法也并不罕见。通常没有人完全理解应用程序是如何工作的。人们没有时间带你参观。他们更喜欢有关特定事物的特定问题,因此您必须自己进行挖掘和实验。然后,一旦你得到你的具体问题,你就可以尝试隔离该应用程序的知识来源并提出问题。

于 2008-10-18T15:08:29.597 回答
2

您可能需要考虑查看源代码逆向工程工具。我知道有两种工具:

这两种工具都提供了相似的功能集,包括生成软件中模块之间关系图的静态分析。

这主要由调用图和类型/类规范组成。查看此信息应该可以让您很好地了解代码的各个部分是如何相互关联的。使用此信息,您可以深入了解您最感兴趣并且需要首先理解/修改的部分的实际来源。

于 2008-10-18T15:17:27.643 回答
2

首先了解“问题域”(它是工资系统吗?库存?实时控制或其他)。如果您不了解用户使用的行话,您将永远无法理解代码。

然后看对象模型;可能已经有图表,或者您可能必须对图表进行逆向工程(手动或使用 Doug 建议的工具)。在这个阶段,您还可以调查数据库(如果有的话),是否应该遵循对象模型但可能不遵循,这很重要。

查看更改历史记录或错误数据库,如果某个区域出现很多,请先查看该部分。这并不意味着它写得不好,而是每个人都在使用它。

最后,保留一些笔记(我更喜欢 wiki)。

  • 现有的人可以用它来理智地检查你的假设并帮助你。
  • 您需要稍后再参考它。
  • 团队中的下一个新人会非常感谢你。
于 2008-10-18T20:47:56.430 回答
2

我也有类似的情况。我会说你是这样的:

  • 如果它是一个数据库驱动的应用程序,请从数据库开始并尝试理解每个表、它的字段以及它与其他表的关系。
  • 一旦对底层存储很好,就可以向上移动到 ORM 层。这些表必须在代码中具有某种表示形式。
  • 一旦完成,然后继续讨论这些对象的来源和来源。界面?什么界面?任何验证?在它们进入数据存储之前对它们进行了哪些预处理?

这将使您更好地熟悉该系统。请记住,只有在您非常清楚要测试的内容以及为什么需要以这种方式进行测试时,才能尝试编写或理解单元测试。

如果大型应用程序不面向数据库,我会推荐另一种方法:

  • 系统的主要目标是什么?
  • 那么解决这个问题的系统主要组件是什么?
  • 每个组件之间有哪些交互?制作一个描述组件依赖关系的图表。询问已经在研究它的人。这些组件必须在彼此之间交换一些东西,所以也要试着弄清楚那些(比如 IO 可能会将 File 对象返回到 GUI 等等)
  • 一旦对此感到满意,就可以深入研究最不依赖的组件。现在研究该组件如何进一步划分为类以及它们如何相互交互。这样,您总共掌握了一个组件
  • 移动到下一个最不依赖的组件
  • 最后,转到核心组件,该组件通常依赖于您已经处理过的许多其他组件
  • 在查看核心组件时,您可能会参考之前检查过的组件,所以不要担心继续努力!

对于第一个策略: 以这个 stackoverflow 站点为例。检查数据存储区、存储的内容、存储方式、这些项目在代码中的表示形式、这些项目在 UI 上的呈现方式。他们从哪里来,一旦他们回到数据存储区,他们会发生什么处理。

对于第二个 ,以文字处理器为例。有哪些组件?IO、UI、页面等。这些是如何相互作用的?随着您进一步了解,请继续前进。

放松。编写的代码是一个人的心态,僵化的逻辑和思维方式,阅读这种思想需要时间。

于 2009-04-25T05:25:16.480 回答
1

我发现只是跳入代码可能有点不知所措。尝试阅读尽可能多的设计文档。这有望解释每个组件的用途和结构。如果现有的开发人员可以带您完成它,那就最好不过了,但这并不总是可能的。

一旦您对代码的高级结构感到满意,请尝试修复一两个错误。这将帮助您掌握实际代码。

于 2008-10-18T14:28:30.707 回答
1

我喜欢所有说你应该使用像 Doxygen 这样的工具来获取类图的答案,并首先尝试理解全局。我完全同意这种说法。

也就是说,这在很大程度上取决于代码的分解程度。如果它是一个巨大的混乱,它将很难学习。如果它干净,并且组织得当,它应该不会那么糟糕。

于 2008-10-18T21:04:54.803 回答
1

请参阅此答案,了解如何使用测试覆盖率工具来定位感兴趣功能的代码,而不知道该功能在哪里,或者它如何分布在许多模块中。

于 2010-07-11T22:33:50.807 回答
0

(前方无耻营销)

你应该看看nWire。它是一个用于导航和可视化大型代码库的 Eclipse 插件。我们的许多客户使用它通过打印主要流程的可视化来打入新的开发人员。

于 2009-04-19T04:53:34.967 回答