it-swarm.cn

您如何进入大型代码库?

您使用什么工具和技术来探索和学习未知的代码库?

我在考虑诸如grepctags,单元测试,功能测试,类图生成器,调用图,诸如sloccount之类的代码度量之类的工具。我会对您的经验,您使用或编写的助手以及您使用的代码库的大小感兴趣。

我意识到熟悉代码库是一个随时间推移而发生的过程,熟悉度可以表示从“我能够总结代码”到“我可以将其重构并缩小到其大小的30%”之类的任何内容。但是,如何开始呢?

145
miku

我一直做的事情如下:

打开我的编辑器的多个副本(Visual Studio/Eclipse/Whatever),然后调试并执行换行以单步执行代码。找出代码流程,堆栈跟踪以查看关键点在哪里,然后从那里开始。

我可以逐个方法地查看方法-但是,如果我可以单击某些内容然后查看它在代码中的执行位置并进行后续操作,那就太好了。让我来感受一下开发人员如何使事情工作。

55
ist_lion

你怎么吃大象?

一次咬一口:)

认真地讲,我尝试先与代码的作者交谈。

64
user2567

在完成工作之前,我是否需要hack一下

在很大程度上,是(抱歉)。

您可能会考虑的方法:

  1. 尝试从业务角度找出代码应该做什么。
  2. 阅读现有的所有文档,无论文档多么糟糕。
  3. 与可能知道something的人谈谈代码。
  4. 在调试器中单步执行代码。
  5. 介绍一些小的变化,看看有什么突破。
  6. 对代码进行少量更改以使其更清晰。

我要做的一些澄清代码的事情是:

  1. 运行代码修饰符以很好地格式化代码。
  2. 添加评论以解释我的想法
  3. 更改变量名称以使其更清晰(使用重构工具)
  4. 使用突出显示特定符号所有用途的工具
  5. 减少代码中的混乱情况-注释掉代码,无意义的注释,无意义的变量初始化等。
  6. 更改代码以使用当前的代码约定(再次使用重构工具)
  7. 开始将功能提取到有意义的例程中
  8. 在可能的情况下开始添加测试(不太可能)
  9. 摆脱魔术数字
  10. 尽可能减少重复

...以及您可以进行的其他任何简单的改进。

逐渐地,这背后的含义应该变得更加清晰。

至于开始的地方?从您所知道的开始。我建议输入和输出。您通常可以弄清楚这些应该是什么以及它们的用途。通过应用程序跟踪数据,并查看数据去向和更改方式。

我所有这些问题中的一个是动力-它可能是一个真正的障碍。它帮助我将整个业务视为一个难题,并庆祝我所取得的进步,无论规模如何。

39
Kramii

您的情况实际上很常见。任何不得不从事可以处理现有代码的新工作的人都将处理其中的某些元素。如果该系统确实是一个令人讨厌的旧系统,则非常类似于您所描述的。当然,目前没有任何文档。

首先,许多人推荐Michael Feathers的 有效地使用旧版代码 。这确实是一本不错的书,其中包含有用的章节,例如“我无法将此类纳入测试工具”或“我的应用程序没有结构”,尽管有时Feathers只能提供比解决方案更多的同情。特别是,这本书及其示例主要针对花括号语言。如果您正在使用粗糙的SQL过程,则可能没有那么有用。我认为“我对这个代码的理解不充分,无法更改它”一章谈到了您的问题。 Feathers在这里提到了一些明显的事情,例如做笔记和标记清单,但也很重要的一点是,如果您具有源代码管理,则可以删除未使用的代码。许多人将代码的注释部分保留在原处,但这通常无济于事。

接下来,我认为您建议的方法无疑是一个好步骤。您必须首先全面了解代码的用途。

如果您需要回答问题,一定要与导师或团队中的某人合作。

另外,如果发现了缺陷,请抓住机会支持代码(尽管有时您不必为此而自愿……缺陷会找到您!)。用户可以解释他们使用软件的目的以及缺陷如何影响他们。当试图理解软件的含义时,这通常可能是非常有用的知识。另外,以有针对性的攻击目标进入代码有时可以帮助您在面对“野兽”时集中精力。

32
Bernard Dy

当我有一个非常大的源文件时,我喜欢执行以下操作:

  • 将整个混乱复制到剪贴板
  • 粘贴到Word/textmate中
  • 将字体大小减小到最小。
  • 向下滚动以查看代码中的模式

当您回到常规编辑器时,会对代码看起来多么陌生感到惊讶。

13
sal

这需要时间

尝试理解旧版代码库时不要太着急,尤其是当它使用的是您不熟悉的技术/语言/框架时。这只是一个不可避免的学习过程,需要一些时间。

一种方法是在相关技术的代码和教程之间来回切换。您阅读/观看了该教程,然后查看代码以了解您的前辈是如何做到的,请注意任何异同,做笔记并向任何现有开发人员提问。

“为什么你要这样做?”

“我注意到大多数在线人都是这样做的,你们都是这样做的。为什么呢?”

“是什么让你们所有人选择技术X而不选择技术Y?”

这些问题的答案将帮助您了解项目的历史以及设计和实施决策背后的原因。

最终,您将对它足够熟悉,可以开始添加/修复问题。如果这一切看起来令人困惑,或者似乎发生了太多的“魔术”,则您还没有花费足够的时间查看,消化和绘制图表。创建图表(顺序图,过程流程图等)是您了解复杂过程的好方法,此外,它们还将帮助“下一个家伙”。

12
CFL_Jeff

cscope可以执行ctags对C的所有操作,此外,它还可以列出所有当前函数的调用位置。加上它非常快。轻松扩展到数百万个LOC。整洁地集成到emacs和vim。

C和C++代码计数器-cccc可以生成html格式的代码指标。我也用wc来获取LOC。

doxygen可以在html中生成语法突出显示和交叉引用的代码。在浏览大型代码库时很有用。

9
aufather

我建议使用Drupal,但实际上不是Drupal特定:从问题跟踪器开始。肯定会有旧的,未公开的错误报告。可以吗?如果是,请更新票证以进行确认;如果否,请关闭票证。通过这种方式,您将发现大量使用该软件的方法,然后可以开始查看崩溃的代码库,也可以开始执行。通过代码并了解它如何到达崩溃的位置,这样您不仅会开始理解代码库,而且会积累大量的业障,您的问题将受到社区的热烈欢迎。

8
chx

要做的重要一件事是使用工具 生成依赖关系图 自上而下地探索代码架构。首先将.NET程序集或jar之间的图形可视化,这将使您了解如何组织要素和图层,然后挖掘到名称空间依赖项(在一个或几个相对的.NET程序集或jar中),以获得更细粒度的代码概念结构,最后您可以查看类依赖关系,以了解一组类如何协作以实现功能。有几种生成依赖关系图的工具,例如 用于.NET的NDepend 生成了下面的图。

enter image description here

我曾经有一个非常出色的软件工程师告诉我,最昂贵的代码分析和维护形式是逐行浏览代码。当然,我们是程序员,而这几乎与工作有关。我认为,很高兴的一种方式是(按此顺序):1.获取一个笔记本,为您理解代码的工作方式创建注释,并随时间推移添加到笔记本中。2.请参阅有关代码的文档3。与支持代码库的作者或其他人交谈。要求他们进行“大脑转储”。4.如果您已经了解了一些细节级别的类关系,请对代码进行逐步调试,以在您认为代码的工作方式与实现之间进行一些综合。代码实际如何工作。

5
Tim Claason

首先了解它的含义-否则可能会变得很乱。与用户交流,阅读手册,无论如何。

然后点击运行,开始浏览似乎是关键功能的代码。

5
Jon Hopkins

分而治之。我查看了每个功能和相关的代码,逐步进行操作,然后继续进行下一个,逐步构建整体图。

如果项目有单元测试,我也喜欢通过它们,它们总是非常启发人和启发性的。

3
aredkid
  1. 运行所有测试(如果有的话),并查看覆盖哪些代码,而不覆盖哪些代码。
  2. 如果您需要更改的代码未包括在内,请尝试编写测试以覆盖它。
  3. 更改代码。不要破坏测试。

参见Michael Feathers的有效处理旧版代码

3
kevin cline

这是我的简短列表:

  1. 如果可能,请某人对代码进行高级介绍。考虑了什么模式,我希望看到什么样的约定,等等。这可能会有一些回合,因为一开始我会得到一个故事,即随着我对代码的更加熟悉,我可能会遇到新的问题在我研究现有项目的过程中问。

  2. 运行代码,看看系统是什么样的。当然,它可能包含多个错误,但这对于了解其功能很有用。这与更改代码无关,而只是查看其运行方式。各个部分如何组合在一起构成一个整体系统?

  3. 寻找基础文档的测试和其他指标,这些指标可能有助于构建代码的内部思维模型。除非很少的文档和测试,否则我可能至少建议几天。

  4. 我对项目中使用的语言和框架的了解程度如何?这里的重要性是区别看待事物和“是的,以前看过十几遍并且相当了解”和“这里尝试了什么?谁认为这是个好主意?”之间的区别。这类问题,虽然我不会大声说出来,但我会特别思考,如果我正在查看可能非常脆弱的旧代码,并且编写该代码的人要么不可用,要么不记得为什么事情按原样完成。对于新领域,可能值得花一些额外的时间来了解什么是结构以及可以在此代码中找到哪些模式。

最后但并非最不重要的一点是:考虑到以下几个可能的预期想法,就应该在每个时间点执行项目的人员的期望:

  • 您要添加新功能吗?
  • 您要修复错误吗?
  • 您要重构代码吗?这些标准对您来说是新的还是很熟悉?
  • 您是否应该只是熟悉代码库?
3
JB King

我会说从文档等开始,但是根据我的经验,文档的深度和本地知识通常与系统的年龄,大小和复杂性成反比。

话虽这么说,我通常会尝试确定几个功能线程。从功能上讲,我的意思是诸如登录,提取客户列表等之类的东西。如果这些模式完全一致,那么一个线程应该为您提供系统的尼斯(不一定是完整的)横截面。确定模式是否一致的最佳方法是分析几个线程。

我认为这毋庸置疑,但我认为最好是从功能的角度而不是技术的角度来理解系统。我通常不会太担心正在使用的工具(ORM,日志记录库等),而将注意力更多地放在正在使用的模式(MVP等)上。以我的经验,工具通常比模式更流畅。

2
Casey

打印出源代码并开始阅读。如果它特别大,请仅打印出其中的部分内容,以更好地理解它,并根据需要进行多次注释。

从程序的执行开始就跟踪程序。如果您被分配给代码库的特定部分,请跟踪该部分中的执行并找出使用了哪些数据结构。

如果您使用的是面向对象的语言,请尝试制作通用的类图。这将为您提供良好的高级概述。

不幸的是,最后,您将不得不阅读尽可能多的代码。如果幸运的话,以前的程序员已经编写了尽可能多的文档,以帮助您了解正在发生的事情。

2
Rudolf Olah

我总是尝试从程序的入口开始,因为所有程序都有一个(例如main方法,main类,init等)。然后,这将为我指出开始的地方,有时是如何链接的。

之后,我进行深入研究。数据库和DAO在某处配置,因此我对事物的存储方式有所了解。也许还启动了某种全局实例类,在那里我可以弄清楚存储了什么。借助出色的折光工具,我可以找出谁叫什么。

然后,我尝试查找该接口的配置和处理位置,因为这是信息的下一个入口点。折射,搜索和调试工具可帮助我进行搜索。然后,我可以找出所有类文件中信息处理的起点和终点。

然后,我尝试将流程记录在纸上,只是为了一开始就把我的头缠在东西上。提交按钮传递到通用验证,然后传递到DAO或数据库,然后存储在数据库中。这是大多数应用程序的过度简化,但这是总的想法。笔和纸在这里非常有帮助,因为您可以快速记下所有内容,而不必担心在本来可以帮助您的程序中进行格式化。

2
TheLQ

我做的一些事.

1)使用 Source Monitor 之类的源代码分析工具来确定各种模块大小,复杂性度量标准等,以便对项目有所了解并帮助确定不重要的领域。

2)在 Eclipse 中从上至下钻取代码(很好的是拥有一个可以浏览引用等的编辑器),直到我了解代码的内容和代码的位置。

3)有时,我在 Visio 中绘制图表以更好地了解体系结构。这对项目中的其他人也可能有帮助。

2
JeffV

学习新的代码库时,您要做的第一件事是了解它应该做什么,如何使用以及如何使用。然后开始查看体系结构文档,以了解代码的布局方式,同时还查看数据库的方式。同时,您正在学习该体系结构,这是回顾任何流程或用例文档的好时机。然后,在您了解了全局之后,开始研究并阅读代码,但是仅涉及与您可能在此代码上所做的任何工作相关的代码,而不仅仅是尝试阅读所有代码。知道代码在何处执行X比确切地完成X更为重要,代码始终在那里告诉您如何找到它。

我发现仅尝试跳入并阅读代码而没有学习代码的目标通常是无济于事的,尝试自己进行一些小的更改或查看他人更改的代码会更有效地利用您的时间。

2
Ryathal

如果代码库很大,则将注意力集中在当前正在处理的部分上。否则,您会感到不知所措,并且可能会爆炸。我认为一些高级概述会有所帮助(如果可用),但是您可能会在调试器中花费大量时间来遵循以下程序流程。概述应用程序并查看其使用是一个好主意,因此您可以了解代码的使用方式/用途/原因。

我通常在代码上运行某种代码复杂性工具,以告诉我问题区域在哪里。得分高的区域可能很难更新。例如,我遇到了一个在圈尺度上得分为450的函数。果然有数百个IF。很难维护或更改它。所以要做好最坏的准备。

另外,不要害怕向现有的开发人员提出问题,尤其是如果他们在系统上工作。保持内心的想法,专注于解决问题。避免发表可能会使其他开发人员感到沮丧的评论。毕竟,这可能是您的孩子,没有人喜欢被告知他们的孩子丑陋。

采取小步骤,即使最小的代码更改也会产生很大的影响。

我发现提出程序代码流是有帮助的,因此,如果我进行更改,则可以进行依赖项搜索以查看哪些方法/函数调用了什么。假设我要更改方法C。

如果只有1个方法/函数调用C,那么这是一个相当安全的更改。如果数百个方法/函数调用C,那么它将产生更大的影响。

希望您的代码库具有良好的架构,编写和维护。如果是这样,将需要一些时间来理解它,但最终将扭转潮流。

如果它是一个大泥球,您可能永远无法理解(或想了解)其内部运作方式。

2
Jon Raynor

我做了很多.

这是我目前针对“某些事情正在工作”的情况的当前方法,您需要使其“以其他方式工作”。

  1. 获取目标,该系统应该解决(如果未编写)-编写它。向经理,其他员工(甚至以前的员工)询问是否有空。询问客户或搜索任何文档。
  2. 获取规格。如果不存在,请将其写入。不值得向某人索要它,好像它不存在一样,那么当您处于其他人不在乎的情况下。所以只有自己写的方法(以后会更容易引用它)。
  3. 获得设计。不存在-写出来。尽量引用任何文档和源代码。
  4. 将详细的设计写到您需要更改的部分。
  5. 定义测试方式。因此,您可以确保新旧代码以相同的方式工作。
  6. 使系统能够一步一步构建。并使用旧代码进行测试。如果尚未将其放入SVC。
  7. 实施更改。不早.
  8. 一个月左右后进行验证,确保没有任何损坏。

在每个步骤之间可能还需要执行另一种可选的操作:f经理(项目所有者)告诉您“这些更改应该已经在昨天完成”。在完成几个项目之后,他甚至可能开始帮助提前获取规格和文档。

但是通常(尤其是脚本)在业务范围内是不可能的(成本太高,而价值却很低)。一种选择是不进行任何更改,直到达到临界质量并且系统停止生产(例如将要使用新系统),或者管理层认为所有这些都值得做。

PS:我记得有一个代码用于5个具有不同设置的客户端。而且,每项更改(新功能)都需要考虑“使用了哪些部件”和“客户端具有的配置”,以免制止任何事情,也不复制粘贴代码。将他们的设置放入项目CV中并编写规范,可以将这种思考时间几乎减少到0。

2
Konstantin Petrukhnov

没有文档,或者文档很少,或者已经过时。查找确实存在的所有文档。如果在团队存储库中,请不要进行复制。如果没有,请将其放到那里,并可能在一些监督下,请您的经理许可进行组织。

将所有内容收集到团队的存储库中,然后添加词汇表。所有基地都有行话;将其记录在词汇表中。制作工具,产品,特定于客户的部分等。

创建/更新软件环境创建文档。所有工具,古怪之处,安装选项等均在此处。

然后上传“ ProductName”入门文档等。让它随时间流逝并随着时间自我组织。然后查看过时的文档,并使其恢复最新状态。其他开发人员将不胜感激,您将在学习代码的同时以独特的方式做出贡献。尤其要记录所有使您难堪或被错误命名或违反直觉的事物。

一旦您的倾斜曲线即将结束,就不必担心更新文档。让下一个新家伙来做。当他到达时,将他指向您的工作。当他不断困扰您寻找答案时,请不要回答他。而是将问题添加到您的文档中,然后将其交给他。钓鱼竿。

副作用是您将制作一个自己可以在几个月后忘记的情况下引用的工具。

尽管它不是文档,但相关的问题是团队伙伴所做的所有古怪的,人工密集的过程。使用批处理,SQL脚本等自动化它们,并共享它们。毕竟,就在新环境中产生生产力而言,过程知识可以说与声明性知识一样大。不管是什么,都不要这样做。而是编写脚本并运行脚本。钓鱼竿再次触击。

1
toddmo

这经常发生。在我开始在开源平台上工作之前,我认为我从来没有开始过一项工作,该工作并非以承认代码有一些“怪癖”开始的。

使用步进调试器和很多韧性,您可以走很长一段路。不幸的是,学习一个特定的大泥球常常需要时间和经验,即使多年之后,仍然会有一些子系统出现,而没人知道。

1
Jeremy French

我认为最重要的事情之一就是采用一个简单的功能,选择您能想到的最简单的功能,并将其实现。如果存在被维护的愿望清单,请使用该清单,否则请与熟悉代码库的人交谈,并让他们提出功能建议。通常我希望这是5〜20 LOC的变化。重要的一点不是您要添加一个非常漂亮的功能,而是要使用代码库(或努力解决:))并遍历整个工作流程。你将不得不

  1. 阅读代码以了解您正在修改的组件
  2. 更改代码并了解其如何影响周围的系统。
  3. 测试更改,从而确定组件之间如何交互
  4. 编写测试用例,并希望破坏一个或两个测试用例,以便您可以修复它们并了解系统的不变性。
  5. 构建事物或查看CI构建它,然后将其运送

清单继续进行,但要指出的是,像这样的小型项目将带您通过检查清单上的所有项目,以熟悉系统,还可以进行富有成效的更改。

1
Osada Lakmal

我想补充一点:

我最近开始使用的针对此类问题的一种工具(已极大帮助)是思维导图。我不会试图在脑海中塞满如何实现某事的所有细节,而是构建一个思维导图来描述我正在经历的系统如何工作。它确实可以帮助我更深入地了解正在发生的事情以及我仍然需要弄清楚的事情。它还可以帮助我以非常精确的比例跟踪需要更改的内容。

我建议在过多的思维导图选择中使用 自由平面

1
c.hughes

我在这个主题上写了一篇很长的文章。这是节选

我考虑了很长时间这个问题。我决定编写自己的个人解决方案作为一般过程。我记录的步骤如下:

  1. 创建词汇表
  2. 了解申请
  3. 浏览可用的文档
  4. 进行假设
  5. 查找第三方库
  6. 分析代码

此过程是在大型桌面应用程序的上下文中编写的,但是常规技术仍然适用于Web应用程序和较小的模块。

摘自: 学习新代码库的过程

1
Lars

我可以分享一些小技巧。

对于现有产品,我开始进行密集测试。如果选择了分配任务,我将重点关注特定功能。

  • 下一步将是找到我可以插入并开始探索的代码,在寻找依赖模块,库,框架等的方式上。

  • 下一步将创建具有职责的简单类图(如CRC卡)

  • 开始进行较小的更改或占用较小的错误以进行修复和提交。这样我们就可以了解项目的工作流程;不只是代码。为了授权和审核,大型产品通常会进行某种形式的记账(例如,医疗项目)

  • 与已经在该项目上工作的人交谈。表达您的想法,想法,作为回报,他们可以长期从事该项目,并获得他们的经验和看法。这非常重要,因为这也可以帮助您与团队融洽相处。

1
sarat

我建议您在更改任何内容之前编写单元测试。并且同时更改足够的代码以使测试通过。重构时,请事先添加单元测试,以便您知道重构并没有破坏业务功能。

对编程是一种选择吗?让另一个人反弹想法是应对这种令人讨厌的好主意。

1
David Weiser

这是我们用于消除重复项的过程。

  • 选择重复的标准注释前缀(我们使用[dupe]在注释标记之后;
  • 与您的团队一起编写规范,说明用于重复过程的名称;
  • 第一轮:每个人都拿一些文件,并添加[dupe][procedure_arbitrary_name]在重复的过程之前;
  • 第二轮:每个人都接受一个过程或过程的子集,并分配一个值,该值指示不同目的的实现的相似性顺序(字符串将为:[dupe][procedure_arbitrary_name][n]);
  • 第三轮:负责每个程序的程序将其重写在相关的类中;
  • 第四轮:grep高兴!
1
cbrandolino

自从我不得不深入研究大型代码库以来,已经有很长时间了。但是在最近几年中,我多次尝试让新开发人员加入我们已经拥有相当大的代码库的团队。

我们成功使用的方法,恕我直言,这是最有效的方法,恕我直言,是结对编程。

在过去的12个月中,我们团队共有4个新成员,每次,新成员都会与另一个熟悉代码库的成员配对。一开始,年龄较大的团队成员将拥有键盘。大约30分钟后,我们会将键盘传递给新成员,新成员将在老团队成员的指导下工作。

事实证明,此过程非常成功。

1
Pete

我研究大型代码项目的方式如下:

  1. 制作项目并使用它。
  2. 使用IDE打开项目。例如:Eclipse或Codelite。然后使用IDE索引项目的所有源代码。
  3. 如果项目的语言支持此功能,请使用IDE生成类图。
  4. 找到主要方法,主要方法是程序的入口,主要方法也是探索项目的好入口。
  5. 找到程序的核心数据结构和功能。看一下实现。
  6. 修改项目的一些代码,制作并使用它,观察它是否正确运行!修改程序会鼓舞您。
  7. 在了解了程序的主要流程和核心系统的实现之后,您可以探索程序的其他模块。

    现在您已经了解了大型代码项目!请尽情享受!

0
Edward Shen