熟悉继承代码库的最佳方法

时间:2008-10-18 05:05:39

标签: language-agnostic legacy-code

Stacker没有人问过most shocking thing new programmers find as they enter the field

列表中的高位,是继承代码库的影响,必须迅速熟悉它。突然发现自己有责任维护N行代码,这些代码已被破坏,知道多长时间,以及在短时间内开始为其做出贡献,这可能会非常震惊。

您如何有效地吸收所有这些新数据?什么可以缓解这种转变?唯一真正的解决方案是否已经为足够的开源项目做出了贡献,而震荡消失了?

这也适用于资深程序员。您使用什么技术来简化向新代码库的过渡?

我在此添加了社区建设标签,因为我也想听一些关于这些过渡的战争故事。随意分享您如何处理特别紧张的学习曲线。

14 个答案:

答案 0 :(得分:13)

铅笔&笔记本(不要分心试图创建一个未经请求的解决方案)

  • 随时记笔记,每个星期一花一小时阅读并安排前几周的笔记

  • 对于大型代码库,第一印象可能是欺骗性的,当您熟悉自己时,问题往往会迅速重新排列。

  • 请记住,您上一个工作环境中的问题在新环境中不一定有效或密切相关。谨防先入为主的观念。

  • 您所做的笔记/观察将帮助您快速了解要问的问题和问题。 希望你一直在收集所有官方(和非官方)利益相关者的名字。

答案 1 :(得分:11)

熟悉继承代码的最佳方法之一就是弄脏自己。从修复一些简单的错误开始,逐步进入更复杂的错误。与试图系统地审查代码相比,这会让你更热衷于代码。

如果有需求或功能规范文档(希望是最新的),您必须阅读它。

如果有高级或详细的设计文档(希望是最新的),您可能应该阅读它。

另一个好方法是安排与熟悉代码的人员进行“信息传递”会议,在那里他们提供高级设计的演示,并且还可以浏览重要/棘手的部分。代码。

答案 2 :(得分:9)

编写单元测试。你会发现疣更快,当你需要更改代码时,你会更自信。

答案 3 :(得分:2)

我的步骤是:

1。)在代码库中设置源洞察(或您使用的任何好的源代码浏览器)工作区/项目以及所有源文件头文件。从最顶层的功能(主要)到最低功能,从更高的水平开始。在此代码浏览期间,在纸张/或文档文档上记录跟踪函数调用的流程。不要在此步骤中进入函数实现细节,保留以供以后的迭代使用。在这一步中,跟踪传递给函数的参数,返回值,如何初始化传递给函数的参数如何修改这些参数集的值,如何使用返回值?

2.。)在步骤1)的一次迭代之后,您在代码库中使用了一定级别的代码和数据结构,根据代码库的编程语言设置MSVC(或任何其他相关的编译器项目) ),编译代码,使用有效的测试用例执行,并从main直到最后一级功能再单步执行代码。在函数调用之间保持驱动传递的值,返回的值,所采用的各种代码路径,避免的各种代码路径等等。

3.)迭代地重复1.)和2.)直到你感到舒服,你可以改变一些代码/添加一些代码/找到现有代码中的错误/修复bug!

-AD

答案 4 :(得分:1)

我不知道这是“最好的方式”,但我在最近的工作中所做的是编写一个代码蜘蛛/解析器(在Ruby中),它经历并构建了一个调用树(和一个反向调用)树,我以后可以查询。这有点不重要,因为我们有一个名为Perl的PHP,它调用了SQL函数/过程。任何其他代码爬行工具都会以类似的方式提供帮助(例如javadoc,rdoc,perldoc,Doxygen等。)

阅读任何单元测试或规格都非常有启发性。

记录事物有助于(无论是为自己,还是为其他队友,当前和未来)。阅读任何现有文档。

当然,不要低估单独询问队友(或老板!)的问题。在早期,我经常询问“我们有一个函数/脚本/ foo做X?”

答案 5 :(得分:1)

浏览核心库并阅读函数声明。如果它是C / C ++,这意味着只有标题。记录任何你不理解的内容。

我最后一次这样做时,我插入的一条评论是“这个类永远不会被使用”。

答案 6 :(得分:1)

尝试通过修复其中的错误来理解代码。纠正或维护文档。不要修改代码本身的注释,这可能会引入新的错误。

在我们的工作中,一般来说,如果没有充分理由,我们不会对生产代码进行任何更改。这包括化妆品的变化;即使这些也会引入错误。

无论一段代码看起来有多恶心,除非你有bug修正或其他改动,否则不要试图重写它。如果您在阅读试图学习它的代码时发现了一个错误(或可能的错误),请记录该错误以便以后进行分类,但不要尝试修复它。

答案 7 :(得分:1)

vi和emacs用户可以做的一件事就是使用标签。标签包含在文件中(通常称为TAGS)。您可以通过命令生成一个或多个标记文件(针对vi的emacs vtags的etags)。然后我们编辑源代码,你会看到一个令人困惑的函数或变量,你加载了标签文件,它将带你到声明函数的位置(不够完美)。我实际上写了一些宏,让你使用Alt-cursor导航源, 有点像popd和pushd在许多版本的UNIX中。

BubbaT

答案 8 :(得分:1)

尝试理解代码背后的业务逻辑。一旦你知道为什么代码是在第一时间写的,它应该做什么,你可以开始阅读它,或者正如有人说的那样,在这里和那里大量修复一些错误

答案 9 :(得分:1)

我多次处理过这个问题。我最后写了一篇关于学习新代码库的一般过程的博客文章:http://www.larsavery.com/blog/a-process-for-learning-a-new-codebase/

答案 10 :(得分:1)

另一个程序......

在阅读了Andy Hunt的"实用思维和学习 - 重构你的Wetware" (它没有直接解决这个问题)后,我选了几个可能值得一提的提示:

观察行为:

如果有用户界面,那就更好了。使用该应用程序并获得关系的心理图(例如链接,模态等)。如果它有帮助,请查看HTTP请求,但不要过分强调它 - 您只需要轻松,友好地了解应用程序。

确认文件夹结构:

再一次,这很轻松。只要知道属于哪里,并希望结构具有足够的语义 - 您可以随时从这里获得一些顶级信息。

分析呼叫堆栈,自上而下:

通过并在纸上或其他媒介上列出,但尽量不要输入它 - 这会使你的大脑的不同部分参与其中(如果必须的话,可以使用Legos构建它) - 函数调用,对象和最接近顶级的变量。查看常量和模块,如果可以帮助,请确保不要深入了解细粒度的功能。

MindMap It!:

也许是最重要的一步。创建非常粗略草图映射,了解当前对代码的理解。确保快速浏览思维导图。这样可以让你大脑的不同部分(甚至是R模式)均匀地传播到地图上。

  1. 创建云,盒子等。无论你最初认为他们应该在论文上。随意表示带有句法符号的框(例如' F' - 功能,' f' -closure,' C' -Constant,' V&#39 ; -Global Var,' v' -low-level var等)。使用箭头:参数的传入数组,返回的传出,或更自然的东西。
  2. 开始绘制连接以表示关系。如果看起来很乱,那就好了 - 这是初稿。
  3. 快速粗略修改。它太难阅读了,做了另一个快速组织,但不要做多个版本。
  4. 打开调试器:

    1. 验证或使映射后的任何概念无效。跟踪变量,参数,回报等。
    2. 跟踪HTTP请求等,以了解数据的来源。请查看标题本身,但不要深入了解请求正文的详细信息。
    3. MindMap再次!:

      现在你应该对大多数顶级功能有一个不错的了解。

      1. 创建一个 MindMap,其中包含您在第一个中遗漏的任何内容。你可以花更多的时间来处理这个,甚至添加一些相对的小细节 - 但不要害怕他们之前可能会发生冲突的想法。
      2. 将此地图与上一张地图进行比较,排除之前遇到的任何问题,记下新问题,并记下相互冲突的观点。
      3. 如果太朦胧,请修改此地图。尽可能多地修改,但要将修订保持在最低限度。
      4. 假装不是代码:

        如果您可以将其置于机械术语中,请执行此操作。其中最重要的部分是为应用程序的行为和/或代码的较小部分提供一个隐喻。认真思考荒谬的事情。如果是动物,怪物,星星,机器人。会是什么样的。如果它是在星际迷航中,他们会用它做什么。想想很多事情来衡量它。

        综合分析:

        现在你想看到的不是什么'但是'怎么样?通过你循环的任何低级部件都可以取出并放入无菌环境(你可以控制它的输入)。你得到什么样的输出。系统比你原先想象的更复杂吗?更简单?它需要改进吗?

        贡献一些东西,伙计!:

        编写测试,修复错误,评论,抽象。你应该有足够的能力开始做出微小的贡献,并且 FAILING IS OK:)!请注意您在提交,聊天,电子邮件中所做的任何更改。如果你做了一些卑鄙的事情,那么你们可以在它投入生产之前抓住它 - 如果 错误,那么这是让队友为你清理事情的好方法。通常听取队友的谈话会让你的MindMaps发生冲突。

        简而言之,最重要的是使用自上而下的方式让尽可能多的大脑参与。如果可能的话,它甚至可能有助于关闭笔记本电脑并面向窗外的座位。研究表明,强制执行最后期限可以创造一个压力宿醉"在截止日期后约2.5天,这就是为什么截止日期通常最好在星期五。所以,放松,没有TIMECRUNCH,现在提供自己的安全失败的环境。大部分内容都可以匆忙完成,直到您了解详细信息。确保您不要绕过对高级主题的理解。

        希望这也有助于你:)

答案 11 :(得分:0)

在进入代码之前,我要做的第一件事就是使用应用程序(如果需要,作为几个不同的用户)来理解所有功能并查看它们如何连接(信息如何在应用程序内部流动)。

之后我会检查构建应用程序的框架,这样我就可以在我看到的所有接口与一些View或UI代码之间建立直接关系。

然后我查看数据库和任何数据库命令处理层(如果适用),以了解该信息(用户操作的信息)的存储方式以及它如何进入和来自应用程序

最后,在了解了数据的来源以及数据的显示方式后,我会查看业务逻辑层,了解数据的转换方式。

我相信每个应用程序架构都可以像这样划分,并且在真正调试它或添加新东西之前知道整个函数(在你的应用程序中谁是谁)可能是有益的 - 也就是说,如果你有足够的时间这样做

是的,与开发当前版本软件的人交谈也很有帮助。但是,如果他/她即将离开公司,请记下他/她的愿望清单(他们想为项目做些什么,但由于预算限制而无法做到)。

答案 12 :(得分:0)

为您从代码库中找到的每件事创建文档。 通过exprimentation了解它是如何工作的 - 在这里和那里改变几行,看看会发生什么。 使用geany可以加速搜索程序中常用的变量和函数,并将其添加到自动完成中。 找出你是否可以通过脸书或通过Google搜索来联系代码库的原始开发者。 找出代码的最初目的,看看代码是否仍然符合这个目的,或者是否应该从头开始重写,以实现预期目的。

找出代码使用了哪些框架,他们使用哪些编辑器来生成代码。

推断代码如何工作的最简单方法是通过实际复制某个部分将如何完成并重新检查代码(如果存在这样的部分)。

它是逆向工程 - 通过尝试重新设计解决方案来找出问题。

大多数计算机程序员都有编码经验,如果代码中存在某些模式,您可以查找这些模式。

有两种类型的代码,面向对象和结构导向。

如果你知道如何做到这两点,那么你很高兴,但如果你不熟悉其中一个,那么你必须重新学习如何以这种方式编程以理解为什么编码那个方式。

在面向对象的代码中,您可以轻松创建记录每个对象类的行为和方法的图表。

如果它是结构导向的,意味着通过函数,创建一个函数列表,记录每个函数的作用以及它在代码中的位置。

我自己没有做过上述任何一种情况,因为我是一名网络开发人员,从index.php开始到其他页面的其他部分相对容易理解。

好运。

答案 13 :(得分:0)

这里所有非常好的答案。只是想添加一些其他内容:

一个人可以将架构理解与闪存卡配对,然后再次访问可以巩固对闪存卡的理解。我发现诸如“ X功能的哪一部分代码具有功能性?”之类的问题,其中X在您的代码库中可能是有用的功能。

我还喜欢在emacs中打开一个缓冲区,然后开始重新编写我想熟悉的代码库的某些部分,并添加自己的注释等。