熟悉大型代码库的最佳方法是什么?[关闭]


75

加入已经拥有大型代码库的现有团队可能会令人生畏。最好的方法是什么?

  • 广阔; 尝试从代码中获得所有内容如何链接在一起的一般概述
  • 狭窄; 一次专注于一小段代码,了解它们如何充分发挥作用
  • 选择一项功能,以在发展中学习和学习
  • 尝试从类图和uml中获得见解(如果有)(并且是最新的)
  • 还有其他东西吗?

我正在研究目前大约有2万行的C ++应用程序和库(编辑:在宏伟的计划中占很小的空间!)。在行业中,我想您会得到经验丰富的程序员的介绍。但是,如果不是这种情况,您应该怎么做才能尽快开始增加价值?

-
答案摘要:

  • 在调试模式下单步执行代码以查看其工作方式
  • 与比您更熟悉代码库的人配对,轮流成为编码人员和观看/讨论人员。在团队成员中轮换合作伙伴,以便知识传播。
  • 编写单元测试。首先声明您认为代码将如何工作。如果结果符合您的预期,则您可能已经理解了代码。如果没有,您将有一个难题需要解决,或者需要进行询问。(感谢多纳尔,这是一个很好的答案)
  • 与上述类似,对功能代码进行现有的单元测试
  • 阅读UML,Doxygen生成的类图和其他文档,以广泛了解代码。
  • 进行少量编辑或错误修复,然后逐步建立
  • 记笔记,不要跳进去开始发展;花时间理解比生成混乱或不合适的代码更有价值。

这篇文章是使用继承的代码库熟悉自己的最佳方法的部分重复


4
20K行不是一个很大的代码库。当只有2万行时,我会阅读。我在大学里没有学到的一件事是使用大型代码库。
Paco

确实。20k看起来并不多。我们有C ++文件,每个文件都超过1万行。我知道这很糟糕,但是我们现在没有时间清理。(试想一下,我只是想着想就翻白眼了)但是,大部分的膨胀来自评论。
HS。

2
嘿,的确如此!我并不是说20k是一个巨大的代码库(我从未说过),只是在寻找通用的,可扩展的建议。到目前为止的好答案;有很多事情要考虑。
RJFalconer

20k是..什么,一个文件?;-)
user2864740 2015年

我咨询过的一个地方有一个40k行的文件,该文件深度嵌套了if / then语句,该语句实现了某种业务规则。太可怕了
戴夫牛顿

Answers:


24

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


2
调试时需要考虑变量的期望值,如果调试器显示不同,则找出原因。我个人不喜欢调试器,但更喜欢打印语句,这些语句会迫使您提前考虑。
Extraneon

1
@extraneon除了迫使您提前考虑之外,打印语句还使您可以更轻松地查看大量输入。因此,例如,如果一个变量通常为2,并在100个循环中变为10,则可以使用printf语句来发现它,但是使用调试器很难找到它。
Elazar Leibovich 2010年

18

另一个选择是针对您感兴趣的功能编写测试。设置测试工具是建立系统具有哪些依存关系以及其状态位于何处的好方法。每个测试都以关于您认为系统应该工作的方式的断言开始。如果事实证明如此,您就已经取得了一些成就,并且已经有了一些可以重现的示例代码。如果那样行不通,那么您有一个难题要解决,还要进行一系列的询问。


我一直认为这是熟悉他人代码的最佳方法。
比尔蜥蜴

11

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

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


9

这完全取决于您是什么样的学习者和程序员,但是:

  • 广泛优先-您需要了解范围和规模。如果很好,这可能包括略读docs / uml。如果这是一个长期的项目,并且您需要对所有内容都有充分的了解,那么我可能会正确地阅读文档。再说一次,如果他们很好。
  • 缩小-选择可管理的内容并尝试理解它。获得代码的“味道”。
  • 选择一项功能-如果您有信心,可以选择与刚刚看过的功能不同的功能,然后开始进行一些小的更改。
  • 迭代-评估进展情况,看看您是否可以从更深入的早期步骤中受益。

7

搭配严格轮换。

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

你们将成对地学习一些知识,然后当轮换发生时,这些知识就可以反馈给团队的其他成员。这样做的好处还在于,当一对新人放在一起时,从事这项工作的人(在这种情况下,是研究代码)可以以更容易理解的方式总结和解释概念。随着时间的流逝,每个人都应该处于相似的理解水平,并希望避免出现“哦,只有约翰知道那部分代码”的综合症。

据我所知,这是一个不错的数字(3对),但是,如果您分布均匀,或者工作时间不同,则不可能实现。


6

我建议在其上运行Doxygen以获取最新的类图,然后再扩展一段时间。这为您提供了一个快速的概览,可以让您在接触代码时变得一尘不染。


5

我同意这完全取决于您是哪种类型的学习者。话虽这么说,但我曾在两家公司拥有非常庞大的代码库。通常,我是这样工作的:

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

首先,我在很大程度上忽略了实现,只看了头文件或类接口。我试图了解每个课程的目的。第二,我从最重要的领域入手深入实施。这很难衡量,因此有时我只是从顶部开始,然后在文件列表中逐一进行。我称之为广度优先学习。第一步之后,我通常会深入研究其余的代码。最初的广度优先外观有助于巩固/修复我从接口层获得的任何想法,然后深度外观向我展示了用于实施系统的模式以及不同的设计思想。深度优先,我的意思是,您基本上是使用调试器逐步完成程序的,逐步进入每个函数以了解其工作原理,等等。对于真正的大型系统,这显然是不可能的,但是20k LOC并不多。:)


3

与另一个对系统更熟悉的程序员合作开发新功能或修复错误。这是我见过的最佳方法。


2

我认为您需要将此与特定任务联系在一起。当您有时间时,请按照自己的想法选择哪种方法。

当您有需要完成的事情时,请集中精力完成任务。


2

让团队将您的错误修复两个星期(如果有两个星期)。他们会很乐意让某人对此负责,到该阶段结束时,您将花费大量时间解决图书馆的问题,以至于您可能非常了解。


这就是我倾向于做事的方式。做事无可替代。仅仅阅读代码/文档/测试永远不会真正削减它。
斯蒂芬·达林顿

2

如果它具有单元测试(我敢打赌没有)。从小处着手,并确保单元测试不会失败。如果您立即凝视整个代码库,您的眼睛将蒙住眼睛,您会感到不知所措。

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

您提到它是一个应用程序和一个库。首先更改应用程序,并坚持以用户身份使用库。然后,在您学习了库之后,将更容易进行更改。

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

即使在公司中,采用这种方法也很常见。通常没有人完全了解应用程序的工作方式。人们没有时间向您展示。他们喜欢有关特定事物的特定问题,因此您必须自己进行挖掘和试验。然后,一旦遇到您的特定问题,就可以尝试隔离该应用程序的知识来源并提出问题。


2

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

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

查看更改历史记录或错误数据库,如果有很多问题,请先进行研究。这并不意味着它写得不好,而是每个人都在使用它。

最后,记下一些笔记(我更喜欢维基)。

  • 现有人员可以使用它来理清您的假设并帮助您。
  • 您稍后需要参考。
  • 团队中的下一位新员工将非常感谢您。

2

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

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

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

并且在不将大型应用程序推向数据库的情况下,我建议使用另一种方法:

  • 系统的主要目标是什么?
  • 那么,解决该问题的系统主要部件是什么?
  • 每个组件之间有哪些交互作用?制作一个描述组件依赖关系的图形。问一个已经在做的人。这些组件之间必须互相交换东西,因此也要设法弄清楚(例如IO可能会将File对象返回给GUI等)
  • 一旦对此感到满意,就跳入最不依赖的组件中。现在研究如何将该组件进一步分为几类,以及它们之间如何相互作用。这样一来,您就可以完全掌握单个组件
  • 移至下一个最不依赖的组件
  • 最后,转到核心组件,该组件通常会依赖于您已经解决的许多其他组件
  • 在查看核心组件时,您可能会参考先前检查过的组件,所以不要担心继续努力!

对于第一个策略: 以这个stackoverflow网站为例。检查数据存储,正在存储的内容,如何存储,这些项目在代码中的表示形式,这些项目在UI上的显示位置。它们从何而来,一旦返回数据存储区,将对它们进行什么处理。

对于第二个, 以文字处理器为例。有哪些组件?IO,UI,Page等。它们之间是如何相互作用的?继续学习,继续前进。

放松。书面代码是某人的心态,僵化的逻辑和思维方式,要读懂该思想会花费一些时间。


2

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

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

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

祝好运!


2

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

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

这主要由调用图和类型/类的十进制组成。查看这些信息应该可以使您清楚地了解代码的各个部分之间的关​​系。使用此信息,您可以挖掘最感兴趣的零件的实际来源,并且首先需要了解/修改。


1

我发现只是跳入代码可能有点让人不知所措。尝试阅读有关设计的尽可能多的文档。希望这将解释每个组件的目的和结构。如果现有的开发人员可以帮助您解决问题,那将是最好的选择,但这并不总是可能的。

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


1

我喜欢所有的答案,这些答案都说您应该使用Doxygen之类的工具来获取类图,然后首先尝试了解全局。我完全同意这种说法。

就是说,这很大程度上取决于代码开始时的分解程度。如果它是一个巨大的混乱,它将很难学习。如果它干净整洁,组织得当,应该没那么糟。



0

(未来的无耻营销)

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.