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

发布于 2024-10-13 16:02:02 字数 987 浏览 1 评论 0原文

我有以下代码:

  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!")
    }
  }

您是否看到我可以做某种程度的增强,以便这一大块代码看起来更好。谢谢你的建议,马蒂亚斯。

I have the following code:

  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!")
    }
  }

Do you see some level of enhancement I can do, so that this big chunk of code looks just better. Thanks for your advise, Matthias.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

魂归处 2024-10-20 16:02:02

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

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

检查 pc创建空 pc 后立即显示 .isEmpty 表明您已经裁剪了 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!")
}

One common trick is to wrap the two values (pc and level) into a tuple, giving you a single entity that you can pattern match on:

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

The check pc.isEmpty immediately after creating an empty pc suggests that you've cropped the code for stackoverflow, so the approach may not help you here. But I'll try it anyway:

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!")
  }
}

This is obviously nonsence, as half of those conditions are impossible, but it is a literal translation of the code you originally supplied. I'm also unhappy with the side effects and mutation, but didn't want to change too much in one sitting!

If you can add back in the code you removed, or give a better idea of what you're trying to achieve then I'll happily update my answer :)

UPDATE Prompted by Daniel, here's the next step; rearranging and optimising the cases:

(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!")
}
猫卆 2024-10-20 16:02:02

您当然可以将其重新排列为级别,然后是 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 更新程序对象。

您还可以将 level 和 pc 组合到 Map 中的键中并查找您想要执行的操作。

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

You can certainly rearrange this into levels, then 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.
    }
  }

For the other items, perhaps you can use a Map with pc as the key and behavior functions as the values.

This might suggest that you could have L and H updater objects that you could look up using the level.

You can also combine level and pc into the key in a Map and lookup what you'd like to do.

Your instinct is good: when you see long if/then/else, you should think about polymorphism or lookups to simplify it. Think how you could modify the flow by adding objects rather than rewriting code (open/closed principle).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文