什么是理解代码库整体结构的好方法?

计算科学 软件 文件
2021-12-05 10:04:29

有时在我的工作中修改其他人的开源代码或了解如何为自己的应用程序开发特定的东西很有用。但是,并非所有软件都有良好的文档。

什么是理解代码库整体结构的好方法?

例如,哪些例程调用哪些例程等。我自己可能会为此目的使用文档工具(例如 Doxygen),但是,我想知道是否有更好的策略?

2个回答

以下线程是切线相关的:

在我论文的第一部分,我花了 18 个月的时间修改未记录的 Fortran 代码,首要任务之一是尝试理解代码库的整体结构。我建议你做的最重要的事情是在你想出一些东西时在文本文件中做笔记。在这个耗时且令人沮丧的过程中,您不想重新学习或重新发现事物。

就我而言,没有“API”可言,因为函数的参数不是自记录的,因为以前的程序员使用类似 Fortran 77 的风格,因此,短标识符几乎没有暗示什么他们的意思。没有测试,因为它是 Fortran,所以没有标题。更有趣的是,这里和那里有几个用 C 或 C++ 编写的函数。

对我有用的东西(假设你在 Linux 中工作):

  • grep. 学会爱grep您将在 shell 中使用它来查找函数的声明和调用位置,输出将告诉您要查看哪些文件。
  • 您最喜欢的代码编辑器或 IDE 中的“查找”命令。一旦您知道要查找的文件,“查找”命令将节省您寻找函数调用的时间。
  • 如果可以更改代码库,则进行积极的重构。我让变量名自我记录,这样我就不必花费脑力去重新学习我已经弄清楚的东西。我还简化了代码的设计,因为我弄清楚了,所以它不那么混乱。不再有 1000 行长的主程序!
  • 激进的评论。同样,如果您可以更改代码库,请对内容进行注释,以便您知道自己发现了什么。我没有使用 Doxygen,但 Doxygen 对此很有用。
  • nm. 如果您没有库的源代码,但想知道您遇到的函数是否在该库中,它可能对库很有用。但是,它仅在库的符号没有被剥离的情况下才有效。
  • 使用调试器单步执行代码。它比使用print语句更有效。ddd并且gdb很棒,几乎可以在所有的 Linux 系统上使用。随意使用您最喜欢的调试器。
  • 开发人员的错误。这个选项非常适合非常有针对性的问题。如果你去找他们(就像我一样),说“我不明白这里发生了什么”,他们可能会同情你,并试图详细解释事情,但这在从长远来看。您将不得不做腿部工作,因为开发人员并没有为您编写文档并以书面形式解释其代码库的结构。当你真的被小事困住时(如果他们记得他们做了什么),开发人员真的很适合。

我希望我早点想到的事情,或者对我来说不是选择:

  • 多氧。如果您调整 Doxyfile 选项,Doxygen 会自动为您生成大量文档,即使没有特殊的 Doxygen 注释语法,这可能是一个不错的起点;我在后来遇到的项目中使用了它,它非常有帮助。
  • 单元测试。如果您可以更改代码库,并且您对它应该做什么有所了解,请为各种功能编写单元测试。(无论如何,这是一项有用的技能。)
  • 如果您使用 C/C++,请查看标题。
  • 编写示例程序。在那个 Fortran 项目上对我来说不是一个选项,但它对我在获取第三方 API 时很有用。另外,看看他们的示例程序,如果有的话。
  • 如果您有示例或可执行文件可供使用,请使用gcovlcov对代码的典型运行进行覆盖率分析。如果有示例应该执行大部分代码库,这两个工具结合起来会告诉你每行代码被访问了多少次。启用调试标志时最有用。如果代码的一部分根本没有被访问,那么立即理解它可能就不那么重要了。如果代码的一部分被大量访问,那么可能值得了解它是什么。也许代码被执行了很多,因为它是一个不重要的循环,或者它可能是许多其他函数所依赖的关键函数。您不能仅凭覆盖率分析来判断,但覆盖率分析可以让您了解将时间集中在哪里。
  • 静态代码分析工具splint可以告诉您代码中是否有问题,例如某些变量从未使用过。
  • 分析。再次,为您提供的数据不会立即告诉您什么是重要的或不重要的,而是建议什么可能是重要的。如果大量 CPU 时间用于调用一个函数,您可能需要查看它并查看它的作用。您还可以将分析输出与dot和一起使用graphviz来生成调用图,并查看函数被调用的次数,例如覆盖率分析。对于复杂的代码,图形分析可能会更有帮助。
  • 如果您使用 C 语言工作,Frama-C应该有助于分析代码,但我从未使用过它,因为它看起来太复杂了,不值得努力。我用纯 C 做一些工作,但主要是我编写的代码;我从未使用过未记录的 C 代码。

我总是告诉我的学生从下往上阅读代码:你从 main() 开始,看看它调用了什么。通常这只是少数功能。然后查看从 main() 调用的函数,这些函数通常定义算法的整体流程(时间步进循环、汇编、求解器、输出等)。深入两层左右,从 30,000 英尺处获得算法的概览。其余部分通常可以从 doxygen 文档等中收集。

但正如我所说,信息是:从下往上阅读代码。