【问题标题】:What's the best way to become familiar with a large codebase? [closed]熟悉大型代码库的最佳方式是什么? [关闭]
【发布时间】:2010-09-17 22:08:15
【问题描述】:

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

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

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

--
答案总结:

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

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

【问题讨论】:

  • 20K 行并不是一个很大的代码库。当它只有 20K 行时,我会阅读它。我在大学里没有学到的一件事是使用大型代码库。
  • 确实如此。 20k似乎不多。我们有 C++ 文件,每个文件超过 10k 行。我知道,这很糟糕,但我们现在没有时间清理。 (想象一下,我只是想着就翻白眼)不过,大部分臃肿都是来自 cmets。
  • 嘿,确实!我并不是要暗示 20k 是一个巨大的代码库(我从未说过它是),我只是在寻找通用的、可扩展的建议。到目前为止很好的答案;很多事情要考虑。
  • 20k 是 .. 什么,一个文件? ;-)
  • 我咨询过的一个地方有一个 40k 行的文件,其中包含深度嵌套的 if/then 语句,这些语句实现了某种业务规则。太可怕了。

标签: legacy legacy-code codebase


【解决方案1】:

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

【讨论】:

  • 在调试时考虑变量的期望值是值得的,如果调试器显示不同,找出原因。我个人不喜欢调试器,但更喜欢强制你提前思考的打印语句。
  • @extraneon 除了强迫你提前思考,打印语句让你更容易看到大量的输入。因此,例如,如果一个变量通常为 2,并且在 100 次循环中变为 10,您将能够使用 printf 语句发现它,但使用调试器更难跟踪。
【解决方案2】:

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

【讨论】:

  • 我一直认为这是熟悉别人代码的最佳方式。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    这在很大程度上取决于你是什么样的学习者和什么样的程序员,但是:

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

    【讨论】:

      【解决方案5】:

      严格轮换配对。

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

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              【解决方案9】:

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

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

              【讨论】:

                【解决方案10】:

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

                【讨论】:

                • 这就是我倾向于做事的方式。做事是无可替代的。简单地阅读代码/文档/测试永远不会真正削减它。
                【解决方案11】:

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

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

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

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

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

                【讨论】:

                  【解决方案12】:

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

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

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

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

                  • 现有的人可以用它来检查你的假设并帮助你。
                  • 您需要稍后再参考它。
                  • 团队中的下一位新人将非常感谢您。

                  【讨论】:

                    【解决方案13】:

                    我也遇到过类似的情况。我会说你是这样的:

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

                    这将使您更好地熟悉系统。请记住,只有在您非常清楚要测试什么以及为什么需要测试它时,才能尝试编写或理解单元测试> 那样。

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

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

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

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

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

                    【讨论】:

                      【解决方案14】:

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

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

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

                      祝你好运!

                      【讨论】:

                        【解决方案15】:

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

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

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

                        【讨论】:

                          【解决方案16】:

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

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

                          【讨论】:

                            【解决方案17】:

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

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

                            【讨论】:

                              【解决方案18】:

                              请参阅this answer,了解如何使用测试覆盖工具来定位感兴趣功能的代码,而无需了解该功能在哪里,或者它如何分布在多个模块中。

                              【讨论】:

                              • 链接已损坏。
                              【解决方案19】:

                              (无耻营销)

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

                              【讨论】:

                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 2010-09-16
                                • 1970-01-01
                                • 2010-09-12
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多