如何为Scala中的长if-else语句编写更少的代码(代码审查)

时间:2011-01-22 13:35:10

标签: scala

我有以下代码:

  def updateProgrammcounter(element: Name) {
    val level = findSecurityLevelOfNameInSymboltable(element.toString.trim)
    var pc = new HashSet[String]
    println("LEVEL: " + level)
    if (pc.isEmpty && level != "N") {
      // the pc is empty so add the level
      pc += level
    } else if (pc.contains("H") && level == "L") {
      // giving high information to low is not allowed
      errorReject()
    } else if (pc.contains("L") && level == "L") {
      // nothing to change because the pc is the same
      println("okay")
    } else if (pc.contains("H") && level == "H") {
      println("okay")
    } else if (pc.contains("L") && level == "H")
      // we have to raise the pc
    pc += level
    else if (level == "N") {
      println("We have a not valid operation!")
    } else {
      println("Something went terribly wrong!")
    }
  }

您是否看到了我可以做的一些增强级别,因此这一大块代码看起来更好。谢谢你的建议,马蒂亚斯。

2 个答案:

答案 0 :(得分:8)

一个常见的技巧是将两个值(pclevel)包装到一个元组中,为您提供一个可以模式匹配的单个实体:

(pc,level) match {
  case (a,b) if condition => ...
  case _ => ...
}

创建空pc.isEmpty后立即检查pc表示您已经裁剪了stackoverflow的代码,因此这种方法可能对您没有帮助。但无论如何我都会尝试:

def updateProgrammcounter(element: Name) {
  val level = findSecurityLevelOfNameInSymboltable(element.toString.trim)
  var pc = new HashSet[String]
  println("LEVEL: " + level)

  (pc, level) match {
    case (pc, level) if pc.isEmpty && level != "N" => pc += level
    case (pc, "L") if pc.contains("H") => errorReject()
    case (pc, "L") if pc.contains("L") => println("okay")
    case (pc, "H") if pc.contains("H") => println("okay")
    case (pc, "H") if pc.contains("L") => pc += level
    case (_,  "N") => println("We have a not valid operation!")
    case _ => println("Something went terribly wrong!")
  }
}

这显然是不存在的,因为这些条件中的一半是不可能的,但 是您最初提供的代码的字面翻译。我也对副作用和变异不满意,但不想一次性改变太多!

如果你可以添加你删除的代码,或者更好地了解你想要实现的目标,那么我很乐意更新我的答案:)

更新丹尼尔提示,这是下一步;重新整理和优化案例:

(pc, level) match {
  case (_,  "N") => println("We have a not valid operation!")
  case (pc, level) if pc.isEmpty => pc += level
  case (pc, level) if pc.contains(level) => println("okay")
  case (pc, "L") if pc.contains("H") => errorReject()
  case (pc, "H") if pc.contains("L") => pc += level
  case _ => println("Something went terribly wrong!")
}

答案 1 :(得分:2)

你当然可以将其重新排列为等级,然后是pc:

def updateProgrammcounter(element: Name) {
    val level = findSecurityLevelOfNameInSymboltable(element.toString.trim)
    var pc = new HashSet[String]
    println("LEVEL: " + level)
    if (level == "L") {
    } else if (level == "H") {
        // All the "H" stuff in here
    } else {
       // Put the "N" case at the top here - it looks like your fall through default.
    }
  }

对于其他项目,也许您可​​以使用带有pc的Map作为键,行为用作值。

这可能表明您可以使用该级别查找L和H更新程序对象。

您还可以将关卡和电脑组合到地图中的关键字中,然后查找您想要做的事情。

你的直觉很好:当你看到if / then / else时,你应该考虑多态或查找来简化它。想想如何通过添加对象而不是重写代码来修改流程(开放/封闭原则)。