SonarQube - 布尔逻辑正确性 -

SonarQube - boolean logic correctness -

我的方法 matches1().

中的逻辑表达式有问题

问题

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

SonarQube: Change this condition so that it does not always evaluate to "true". Conditions should not unconditionally evaluate to "TRUE" or to "FALSE"

我基本上是在做这个逻辑来避免 NPE 在我的 "Block to be executed".

我的代码

匹配1()

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 会告诉我什么,他没有抱怨。 matches2()

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 中,我该如何解决?

问题出在 SonarQube 上。

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

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

它的要点是

Open the Settings (SonarQube General Settings or project Settings) and select the Exclusions category. Switch to the Issues Exclusions and scroll down to “Ignore Issues on Multiple Criteria”. Set squid:S00112 as Rule Key Pattern and **/*Activator.java as File Path Pattern.

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

即使密码正确;严重的是,它让我的眼睛受伤。问题是:很难阅读。这种嵌套条件,本来就不该写的

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

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 ...

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

但如前所述;您最好退后一步,想想是否有办法 避免 首先编写此类代码。

布尔值的典型答案,面向对象编程中的 if/else 链是 多态性 。因此,与其询问有关其状态的信息,不如询问;你转向interfaces/abstract类;并且有不同的实现。然后你有一个工厂为你提供你需要的实现;然后您只需调用方法即可;无需进一步 if/else/whatever.

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

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

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

此时如果两个变量都是 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,删除它会使代码更易于阅读。