【问题标题】:How do you calculate cyclomatic complexity for R functions?你如何计算 R 函数的圈复杂度?
【发布时间】:2011-08-12 13:58:22
【问题描述】:

Cyclomatic complexity 衡量一个函数可以有多少个可能的分支。是否有现有的函数/工具来计算 R 函数?如果没有,我们非常感谢您提出最佳写作方式的建议。

一个廉价的开始是计算你的函数中出现的所有ififelseswitch。但是,要获得真正的答案,您需要了解分支何时开始和结束,这要困难得多。也许一些 R 解析工具可以帮助我们入门?

【问题讨论】:

  • 与此相关,查看实际占用了多少分支会很有用。为此,各种代码覆盖率指标可以提供帮助。不过,我还不知道有任何 R 代码覆盖工具。
  • 可以this question 相关吗? Eclipse 的metrics plugin 可能会让我再次使用 Eclipse,如果这适用于 R。
  • 对于大量的 cmets 感到抱歉,但我更喜欢发布带有答案的答案。 :) 你能解释一下为什么你想要圈复杂度吗?在实践中,我发现处理异常值和不良数据需要在我的代码中使用大量单独的 if 语句,这将运行 cyc。比较很多。这还不错,但是执行(测试和部署)代码的实际覆盖率对于确保处理异常值和异常很重要。
  • 我错了 - 指标插件是 just for Java。希望破灭的声音是什么?
  • 高圈复杂度可以用作“也许我应该重构这段代码”或至少“Richie,你把自己弄得一团糟和过于复杂的事情”的代理。它只是提供了另一种清除 cr*ppy 代码的方法。

标签: r complexity-theory cyclomatic-complexity


【解决方案1】:

您可以使用codetools::walkCode 来遍历代码树。不幸的是,codetools 的文档非常稀少。以下是帮助您入门的说明和示例。

walkCode 接受一个表达式和一个代码漫游器。 Code walker 是您创建的列表,它必须包含三个回调函数:handlercallleaf。 (您可以使用帮助函数 makeCodeWalker 为每个函数提供合理的默认实现。)walkCode 遍历代码树并随时调用代码遍历器。

call(e, w) 在遇到复合表达式时被调用。 e 是表达式,w 是代码步行者本身。默认实现只是简单地递归到表达式的子节点 (for (ee in as.list(e)) if (!missing(ee)) walkCode(ee, w))。

leaf(e, w) 在遇到树中的叶节点时被调用。同样,e 是叶节点表达式,w 是代码遍历器。默认实现就是print(e)

handler(v, w) 为每个复合表达式调用,可用于为某些类型的表达式轻松提供call 的替代行为。 v 是复合表达式的父级的字符串表示形式(有点难以解释——但基本上 <- 如果是赋值表达式,{ 如果是块的开头,if 如果是if 语句等)。如果处理程序返回NULL,则照常调用call;如果你返回一个函数,那就是调用函数而不是函数。

这是一个极其简单的示例,它计算了函数的 ififelse 的出现次数。希望这至少可以帮助您入门!

library(codetools)

countBranches <- function(func) {
  count <- 0
  walkCode(body(func), 
           makeCodeWalker(
             handler=function(v, w) {
               if (v == 'if' || v == 'ifelse')
                 count <<- count + 1
               NULL  # allow normal recursion
             },
             leaf=function(e, w) NULL))
  count
}

【讨论】:

  • 谢谢。 codetools 看起来非常有用,尽管我明白你对稀疏文档的意思。在我弄清楚发生了什么之前,我得先玩一下这个。
  • 不错!我在github.com/hadley/devtools/wiki/Computing-on-the-language 也有一些草稿功能。就我个人而言,我认为 codeWalker 的东西还不够成熟,比手工操作更有优势。
【解决方案2】:

另外,我刚刚发现了一个名为 cyclocomp(2016 年发布)的新包。看看吧!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2011-10-04
    • 1970-01-01
    相关资源
    最近更新 更多