在 Rails 应用程序中查找未使用的代码

如何查找运行 在制作中的代码和不运行 在制作中的代码?

这个应用程序经过了很好的测试,但是还有很多测试用来测试 没用过代码。因此,他们得到覆盖当运行测试... 我想重构和清理这个烂摊子,它一直在浪费我的时间。 我有很多背景工作,这就是为什么我希望制作环境来指导我。在 heroku 中运行时,我可以旋转 dynos 来补偿性能影响。

相关问题 如何在 Ruby 应用程序中找到未使用的方法?没有帮助。

额外收获: 用于显示一行代码运行的频率的指标。不知道我为什么想要,但我就是想要!:)

24152 次浏览

这不是一个完美的解决方案,但是例如在 NetBeans 中,你可以通过右键单击这些方法(或者按 Alt + F7)找到它们的用法。
因此,如果方法未使用,您将看到它。

我对 Ruby 和 RoR 不是很熟悉,但我有个疯狂的猜测:

  • :after_filter方法添加到文件中,该方法将以前调用的方法的名称(从调用堆栈中获取)记录到文件中
  • 将其部署到生产环境
  • 等一会儿
  • 删除所有未记录在日志中的方法。

P.s. 可能在 NetBeans 或 RubyMine 中使用 Alt + F7的解决方案要好得多:)

在正常情况下,方法是使用测试数据进行代码覆盖,但是正如您所说的,您的部分代码已经测试过了,但是没有在生产应用程序中使用,您可以做一些稍微不同的事情。

先说清楚 不要相信自动化工具,它们只会显示你积极测试的东西的结果,仅此而已。

在我们的免责声明之后,我建议您在您的生产应用程序上使用代码覆盖工具(比如用于 Ruby 1.9的 RcovSimplecov) ,并测量用户实际使用的代码路径。虽然这些工具最初是为测量测试覆盖率而设计的,但是您也可以将它们用于生产覆盖率

假设在测试期间访问了所有相关的代码路径,那么您可以删除其余的代码路径。不幸的是,这种假设很可能不会完全成立。所以你仍然必须应用你的知识的应用程序和它的内部工作时删除部分。当删除声明性部分(如模型引用)时,这一点更为重要,因为这些部分通常不直接运行,而只用于配置系统的其他部分。

另一种方法,可以结合以上是尝试重构您的应用程序到可以打开和关闭的显著功能。然后,您可以关闭那些被怀疑未使用的特性,并检查是否没有人抱怨:)

最后一点: 你不会找到一个神奇的工具来完成你的全部分析。这是因为没有工具可以知道某段代码是否被实际用户使用。工具能做的唯一一件事就是创建(或多或少)静态可达性图,告诉您代码是否以某种方式从某个点调用。对于 Ruby 这样的动态语言来说,即使这样也很难实现,因为静态分析并不能带来更多的元编程或动态调用,而这些元编程或动态调用在 Rails 上下文中被大量使用。因此,有些工具实际上运行您的代码,或者尝试从测试覆盖率中获得洞察力。但绝对没有什么魔咒。

因此,考虑到 Rails 应用程序的高内部(大部分是隐藏的)复杂性,您将无法手工完成大部分分析工作。最好的建议可能是尝试模块化您的应用程序,并关闭某些模块来测试它们是否没有被使用。这可以通过适当的集成测试得到支持。

将可疑方法标记为私有。如果这没有破坏代码,检查这些方法是否在类中使用。然后你就可以删东西了

也许您可以尝试使用 ails _ best _ Practices 来检查未使用的方法和类。

在这里,它是在 github: https://github.com/railsbp/rails_best_practices

在 Gemfile 中放入‘ gem“ ails _ best _ Practices”,然后运行 rails_best_practices .生成配置文件

您是否尝试过使用类似 Sahi的东西创建一个测试套件,然后您可以使用它记录所有的用户历程,并将这些测试绑定到 rcov 或类似的东西上。

您必须确保拥有所有的用户记录,但在此之后,您可以查看 rcov 吐出的内容,并至少开始删除显然从未涉及的内容。

这不是一个非常主动的方法,但是我经常使用从 新遗迹收集的结果来查看在过去一个月左右的任何时候生产中是否调用了我怀疑未使用的东西。不过,我使用过的应用程序都非常小,对于大型应用程序来说,它的价格也相当昂贵。

我从来没有用过它自己,但 这篇文章关于 激光宝石似乎谈论解决你的确切问题。

您已经有了将可疑方法标记为 private (可能会破坏您的应用程序)的想法。

我过去做过的一个小变化: 向所有可疑的方法添加一个小段代码来记录它。在我的案例中,它是一个用户弹出窗口“你调用了一个过时的功能-如果你真的需要,请与 IT 联系”。 一年之后,我们对真正使用的是什么有了一个很好的概述(它是一个业务应用程序,其中功能每年只需要一次)。

在您的情况下,您应该只记录使用情况。一个合理的时期后没有记录的所有东西都是未使用的。

元编程

对象 # method _ miss

重写 Object#method_missing。在内部,异步地将调用 同学们方法记录到数据存储区。然后根据传递给 method_missing的参数,使用适当的参数手动调用原始方法。

目标树

然后将数据存储区中的数据与应用程序对象树的内容进行比较。

免责声明: 这肯定需要重大的性能和资源考虑。而且,这需要一些小修小补才能奏效,但理论上应该是可行的。我将把它作为练习留给原始海报来实现它。;)

我也有同样的问题,在探索了一些替代方案之后,我意识到我已经从日志文件中获得了所有可用的信息。我们的日志格式如下

Dec 18 03:10:41 ip-xx-xx-xx-xx appname-p[7776]:   Processing by MyController#show as HTML

所以我创建了一个简单的脚本来解析这些信息

zfgrep Processing production.log*.gz |awk '{print $8}' > ~/tmp/action


sort  ~/tmp/action | uniq -c |sort -g -r > ~/tmp/histogram

它产生的结果是给定的控制器 # 操作被访问的频率。

4394886 MyController#index
3237203 MyController#show
1644765 MyController#edit

下一步是将其与应用程序中所有控制器 # 操作对的列表进行比较(使用 rake 路由输出或者可以为测试套件执行相同的脚本)

检查 带子的宝石,它做你正在寻找什么。