循环复杂度违规: 函数应该具有10或更少的复杂度: 当前复杂度为13 (循环复杂度)

36

我有以下代码,使用Swift3编写,并使用Swift Lint对代码进行检查。 该代码如下:

    func selectedMenuInLoggedOutState(sender: UIButton) {
    switch sender.tag {
    case 1:
      if let menu = LeftGuestMenu(rawValue: 0) {
        self.changeGuestViewController(menu)
      }
    case 2:
      if let menu = LeftGuestMenu(rawValue: 1) {
        self.changeGuestViewController(menu)
      }
    case 3:
      if let menu = LeftGuestMenu(rawValue: 2) {
        self.changeGuestViewController(menu)
      }
    case 4:
      if let menu = LeftGuestMenu(rawValue: 3) {
        self.changeGuestViewController(menu)
      }
    case 5:
      if let menu = LeftGuestMenu(rawValue: 4) {
        self.changeGuestViewController(menu)
      }
    case 6:
      if let menu = LeftGuestMenu(rawValue: 5) {
        self.changeGuestViewController(menu)
      }
    default:
      break
    }
  }

Swift lint生成了一个"Cyclomatic Complexity Violation"警告。这个警告是怎么产生的,如何解决?

enter image description here

5个回答

61

这种方法过于复杂。但是,你可以将switchescyclomatic_complexity计算中排除(因为它们非常易读),而不是重写代码,方法如下:

cyclomatic_complexity:
  ignores_case_statements: true

2
我喜欢这个解决方案。我不想改变我的case语句。 - Ariel Antonio Fundora
你如何发现 Linter 规则提供的选项? - wfbarksdale
如果您键入运行 swiftlint rules,它将列出项目的所有当前规则 - 最后一列应包含选项。 - deanWombourne

23

警告是因为您的函数太复杂,根据 度量标准,它本质上计算需要做出的决策数量。

在这种情况下避免警告的简单方法是使用一些简单的数学:

func selectedMenuInLoggedOutState(sender: UIButton) {
    guard let menu = LeftGuestMenu(rawValue: sender.tag - 1) else { return }
    self.changeGuestViewController(menu)
}

是的,可以提出一个有力的论点,即CC应该忽略switch/case语句,只计算if语句。 - Daniel T.
我同意,使用switch和一堆if/elseif/else语句之间有很大的区别。 - Paulw11
2
反思一下,我认为在这种情况下,“数学”解决方案并不那么糟糕。你可以使用它或尝试我的简化开关;无论哪个你喜欢。 - Paulw11
我更新了一条保护语句来防止错误的标签。是的,@ChelseaShawra,你可以用这个更简单的代码替换整个函数。 - Daniel T.
你的UIButton标签为什么从1开始而不是从0开始呢? - William GP
显示剩余2条评论

19

您可以这样在代码中禁用SwiftLint警告:

// swiftlint:disable cyclomatic_complexity
func selectedMenuInLoggedOutState(sender: UIButton) {
    ...
}
// swiftlint:enable cyclomatic_complexity

或者,如果您想明确地禁用下一个 swiftlint 警告:

// swiftlint:disable:next cyclomatic_complexity
func selectedMenuInLoggedOutState(sender: UIButton) {

2

如果您不想更改您的逻辑,请按照以下步骤操作。 在 .swiftlint.yml 文件中添加 "cyclomatic_complexity:" 属性并设置警告值。

cyclomatic_complexity: warning: 25

注意:这里设置警告值意味着增加线性独立路径的数量。您可以设置自己的值。


2

通过消除重复的if let语句,您可以降低复杂性:

func selectedMenuInLoggedOutState(sender: UIButton) {

    let menu: MenuType?

    switch sender.tag {
    case 1:
     menu = LeftGuestMenu(rawValue: 0)
    case 2:
     menu = LeftGuestMenu(rawValue: 1) 
    case 3:
     menu = LeftGuestMenu(rawValue: 2) 
    case 4:
      menu = LeftGuestMenu(rawValue: 3) 
    case 5:
      menu = LeftGuestMenu(rawValue: 4)   
    case 6:
      menu = LeftGuestMenu(rawValue: 5) 
    default:
      menu=nil
    }

    if let menu = menu {
       self.changeGuestViewController(menu)
    }
  }

它显示了在初始化之前使用的错误常量菜单。 - Chelsea Shawra
1
这段代码的圈复杂度为8,避免了警告,但勉强而已。 :-) - Daniel T.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接