【问题标题】:Find unused code in a Rails app在 Rails 应用程序中查找未使用的代码
【发布时间】:2012-04-01 21:07:54
【问题描述】:

我如何找到在生产中运行和未运行的代码

该应用经过良好测试,但有很多测试未使用代码。因此他们在运行测试时得到了覆盖……我想重构和清理这个烂摊子,它一直在浪费我的时间。 我有很多后台工作,这就是为什么我希望生产环境来指导我。在 heroku 上运行时,我可以启动 dynos 来补偿分析器对性能的任何影响。

相关问题How can I find unused methods in a Ruby app? 没有帮助。

奖励:显示一行代码运行频率的指标。不知道为什么我想要它,但我愿意! :)

【问题讨论】:

  • 未使用的意思是:(A) 无法从 Web 应用程序中调用该方法,或者 (B) 访问者不使用它?
  • 两者都有,但我最看重B。谢谢!对 B 有什么建议吗?
  • 如果 B 是您所追求的,听起来您正在寻求分析工具而不是代码覆盖,不是吗?或者某种混合体。不知道是否有人发明了这个,如果我们甚至不能完全命名它。 +1 表示有趣。
  • 这是一个很好的问题。我没有答案,但我很乐意关注这篇文章,看看社区会想出什么。我继承了一个遗留应用程序,如果我有时间,我很想开始清理它。
  • 如果您有功能/系统或至少请求规范,那么仅查看这些更高级别规范的测试覆盖率可能已经很有帮助。如果代码被特性规范所触及,它不太可能死掉。可以检查功能规范未涵盖的所有测试:测试是否丢失,或者它真的死了?

标签: ruby-on-rails ruby refactoring code-coverage


【解决方案1】:

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

首先为了清楚起见:不要相信自动工具。它们只会向您显示您积极测试的结果,仅此而已。

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

假设在测试时间范围内访问了所有相关的代码路径,您可以删除其余的。不幸的是,这个假设很可能不会完全成立。因此,在移除部件时,您仍然需要应用您对应用程序及其内部工作原理的了解。这在删除声明性部分(如模型引用)时更为重要,因为这些部分通常不直接运行,而仅用于配置系统的其他部分。

另一种可以与上述方法相结合的方法是尝试将您的应用程序重构为您可以打开和关闭的显着功能。然后您可以关闭怀疑未使用的功能并检查是否没有人抱怨:)

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

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

【讨论】:

  • 此外,如果您有一个非常好的测试套件,您可能会通过单元测试看到 100% 的代码使用率,但其中很多可能不再用于生产。我之前遇到过这个问题,因为您最终在重构期间维护代码以使其与 api 更改兼容,而实际上代码可以被删除。我对这个问题没有很好的答案,只是想插话并表示同情。
  • 谢谢斯科特。 DRY、SRP、demeter 法则等等——代码删除是必不可少的。好文章霍尔格。
  • 有人有在生产环境中设置 rcov/simplecov 的经验吗?我们使用 1.9.2。哦,它在heroku上运行,添加了只读问题...
【解决方案2】:

也许您可以尝试使用 rails_best_practices 来检查未使用的方法和类。

它在 github 中:https://github.com/railsbp/rails_best_practices

将 'gem "rails_best_practices" ' 放入您的 Gemfile 中,然后运行 ​​rails_best_practices . 以生成配置文件

【讨论】:

    【解决方案3】:

    查看coverband gem,它可以满足您的需求。

    【讨论】:

    • @Dimitry,看起来很有前途,我会在一些应用程序上试一试并报告
    • 如果你需要清理 I18n 语言环境,那么你可以使用这个 gem:github.com/livingsocial/humperdink
    • @oma 使用 Coverband gem 报告任何结果?真诚的, 利益相关方。 :)
    【解决方案4】:

    我遇到了同样的问题,在探索了一些替代方案后,我意识到我拥有所有可用的信息 - 日志文件。我们的日志格式如下

    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
    

    这会产生访问给定控制器#action 的频率的结果。

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

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

    【讨论】:

      【解决方案5】:

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

      我过去做的一个小变化:在所有可疑方法中添加一小段代码来记录它。在我的情况下,这是一个用户弹出窗口“您调用了一个过时的功能 - 如果您真的需要,请联系 IT”。 一年后,我们对真正使用的东西有了一个很好的了解(它是一个业务应用程序,其中的功能一年只需要一次)。

      在您的情况下,您应该只记录使用情况。在一段合理的时间后未记录的所有内容都是未使用的。

      【讨论】:

        【解决方案6】:

        我对 Ruby 和 RoR 不是很熟悉,但我建议一些疯狂的猜测:

        • 添加:after_filter方法,将之前调用的方法的名称(从调用堆栈中获取)记录到文件中
        • 将此部署到生产环境
        • 稍等
        • 删除所有不在日志中的方法。

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

        【讨论】:

        • RubyMine 和 NetBeans 都不了解元编程。它说“未找到用法”并不一定意味着没有用法。这是一个巨大的应用程序,我正在寻找一种更强大且经过验证的方法,而不是编写我自己的生产覆盖工具。
        【解决方案7】:

        元编程

        对象#method_missing

        覆盖Object#method_missing。在内部,将调用 Classmethod 异步记录到数据存储中。然后根据传递给method_missing 的参数,手动调用带有正确参数的原始方法。

        对象树

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

        免责声明:这肯定需要大量的性能和资源考虑。此外,它需要一些修补才能使其工作,但理论上它应该工作。我将把它作为练习留给原始海报来实施。 ;)

        【讨论】:

          【解决方案8】:

          您是否尝试过使用sahi 之类的东西创建一个测试套件,然后您可以使用它记录您的所有用户旅程,并将这些测试与 rcov 或类似的东西联系起来。

          您必须确保您拥有所有用户旅程,但之后您可以查看 rcov 吐出的内容,并至少开始修剪显然从未涵盖过的内容。

          【讨论】:

          • 我为此目的使用 Capybara。只需要注意测试,而不是通过 UI 导航到某些功能,只需访问一个固定的 URL。他们可以通过删除链接来访问生产环境中逐步淘汰的功能。
          【解决方案9】:

          这不是一种非常主动的方法,但我经常使用从 New Relic 收集的结果来查看在过去一个月左右的任何时间里,是否有人在生产中调用了我怀疑未使用的东西。虽然我使用过的应用程序非常小,但对于大型应用程序来说,它的成本相当高。

          我自己从来没有用过,但是this post 关于laser gem 似乎是在谈论解决你的确切问题。

          【讨论】:

            【解决方案10】:

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

            【讨论】:

            • 这与我提到的“没有帮助”的问题之一完全相同。原因见我对 aleksey 的评论。
            【解决方案11】:

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

            【讨论】:

            • 您总是可以在部署到生产环境之前运行测试......虽然我意识到这很乏味并且不能很好地扩展。
            • @BradWerth 任何合理的生产应用程序都应该使用 CI 工具,例如 CircleCITravis 在生产部署之前针对构建运行测试套件。
            • @lacostenycoder,是的,不开玩笑,但这在 9 多年前并不常见......
            猜你喜欢
            • 1970-01-01
            • 2020-10-21
            • 1970-01-01
            • 2015-04-01
            • 1970-01-01
            • 2010-10-20
            • 2014-05-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多