【问题标题】:SonarQube - boolean logic correctness -SonarQube - 布尔逻辑正确性 -
【发布时间】:2017-01-10 21:05:51
【问题描述】:

我的方法 ma​​tches1() 的逻辑表达式有问题。

问题

SonarQube 告诉我有一个错误: (expectedGlobalRule == null && actual != null)

SonarQube: 更改此条件,使其不总是评估为 “真的”。 条件不应无条件地评估为“TRUE”或“FALSE”

我实际上是在执行此逻辑以避免“要执行的块”上出现 NPE

我的代码

ma​​tches1()

private boolean matches1(GbRule actual, GbRule expected) {
     if(actual == null && expected == null) {
        return true;
     } else if((expected == null && actual != null) || (expected != null && actual == null)) {
        return false;
     } else {
       //Block to be executed
     }
}

我颠倒了逻辑,看看 SonarQube 会告诉我什么,他没有抱怨。 ma​​tches2()

private boolean matches2(GbRule actual, GbRule expected) {
      if(actual == null && expected == null) {
         return true;
      } else if(expected != null && actual != null)  {
         //Block to be executed
      } else {
         return false;
      }
}

问题

  1. 问题出在我的布尔逻辑还是 SonarQube 丢失了 他的想法?
  2. 如果问题出在 sonarQube 内部,我该如何解决?

【问题讨论】:

  • 你能说明expectedGlobalRule的定义吗?
  • 您的参数名为 expected,但您的代码使用的是 expectedGlobalRule。所以错字 - 还是故意的?如果是后者 - expeectedGlobalRule 怎么样?
  • @garnulf expectedGlobalRule 不应该在那里,我更正了它
  • 您现在仍然遇到声纳问题吗?
  • 是的,在我的 matcher1() 上仍有 SonarQube 警告

标签: java sonarqube boolean-expression


【解决方案1】:

问题在于 SonarQube。

有关忽略该问题的更多信息,请参阅本文:https://www.bsi-software.com/en/scout-blog/article/ignore-issues-on-multiple-criteria-in-sonarqube.html

您可以将其设置为忽略该文件中的错误。

它的要点是

打开设置(SonarQube 常规设置或项目设置)并 选择排除类别。切换到问题排除和 向下滚动到“忽略多个标准的问题”。鱿鱼套:S00112 作为规则键模式和 **/*Activator.java 作为文件路径模式。

您需要将规则键模式更改为与您的代码违反的规则关联的模式,并将文件模式更改为 .java 文件的路径。

【讨论】:

  • 你为什么认为SonarQube有问题?我不想忽略这个错误。我宁愿纠正这个问题。是否可以修改 squid:S00112 使其正常工作?
  • SonarQube 没有任何问题,至少在这件事上是这样。它的发现是完全有效的,因为您可以与其他答案一起使用。
  • @MarkusMitterauer if((expected == null && actual != null) || (expected != null && actual == null))expected = nullactual = null 时应该为真,但在expected != null && actual != null 时为假。这种情况不属于第一个条件。
  • @nhouser9 详情请见comment by G. Ann
【解决方案2】:

即使代码正确;严重的是,它让我的眼睛受伤。事情是:阅读是困难。这种嵌套条件一开始就不该写。

如果无法避免;至少将其重构为类似

private boolean areActualAnedExpectedBothNull(args ...) {
  return actual == null && expectedGlobalRule == null;
}

请注意;您可以大大简化您的代码:

if (areActualAnedExpectedBothNull(actual, expected)) {
  return true;
}
if (actual == null) {
  return false;
}

if (expected == null) {
  return false;
}

do your thing ...

并在您的其他代码中使用此类方法。当然,你做了很多单元测试;可能有覆盖测量;只是为了确保您的测试真正测试通过这个迷宫的所有可能路径。

但是如前所述;你最好退后一步想想是否有办法避免一开始就编写这样的代码。

OO 编程中布尔值和 if/else 链的典型答案是多态性。所以不要询问它的状态;你转向接口/抽象类;并有不同的实现。然后你有一个工厂给你你需要的实现;然后你只需调用它的方法;不再需要 if/else/whatever。

如果您不知道我在说什么,请观看这​​些videos;尤其是第二个!

【讨论】:

  • 感谢您的关注。我一定会看看视频
  • 我要提高我的代码可读性。不过,我想知道为什么 sonarQube 将我的代码标记为 wrong 而它只是 ugly
【解决方案3】:

问题在于你的逻辑。让我们一块一块地看:

 if(actual == null && expected == null) {
    return true;

此时如果两个变量都是null,那么我们就不再在方法中了。因此,如果我们再进一步,那么其中至少有一个是非空的。

此时可行的选择是:

  • 实际 = null,预期 = 非 null

  • 实际 = 非空,预期 = 空

  • 实际 = 非空,预期 = 非空

现在,让我们看下一段代码:

 } else if((expected == null && actual != null) 

我们已经知道这两个变量都不可能是null,所以只要知道expected == null,就不需要去测试是否是actual != null了。我们已经走到这一步的事实已经证明了这一点。所以actual != null 总是正确的,这就是提出问题的原因。

编辑

这意味着您的代码可以归结为:

private boolean matches1(GbRule actual, GbRule expected) {
  if(actual == null && expected == null) {
    return true;
  } else if(actual == null || expected == null) {
    return false;
  } 

  //Block to be executed
}

请注意,else 不是必需的,删除它会使代码更易于阅读。

【讨论】:

  • 感谢您花时间向我解释我的错误。所以如果我理解得很好,这里的问题是我的一些表达是多余的(无用的)。正确的做法应该是:if((expectedRuleMap == null) || ( actual == null)) 对吧?
  • IMO @GabrielAmyot 代码的第二个版本更清晰/更清晰,因此是最好的。
  • 安 好的,谢谢。我认为声纳提出的信息有点误导。我对消息的理解是,我的 条件 将始终为真,因此我的 else 永远不会达到。
  • 是的,在您的原始代码中 ` && actual != null` 是多余的
  • @GabrielAmyot 这就是为什么我们只突出显示该行的一部分;将您的注意力吸引到需要修复的部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 2011-08-17
  • 1970-01-01
相关资源
最近更新 更多