Java 我如何减少;圈复杂度“;以下代码的

Java 我如何减少;圈复杂度“;以下代码的,java,code-complexity,Java,Code Complexity,我想知道如何降低以下代码的圈复杂度,这是否是我应该担心的问题 请参考ValuePojo.getSomething()方法 (请不要担心变量的命名,为了清楚起见,在这个问题中已经重新编写了这个变量) 圈复杂度由代码中执行分支的数量决定if-else块、switch语句—所有这些都增加了代码的圈复杂度,也增加了确保适当代码覆盖率所需的测试用例数量 为了降低代码的复杂性,我建议您删除没有定义行为的case语句,并在switch语句中用default行为替换它 这是解决这个问题的另一个堆栈溢出。 如果你

我想知道如何降低以下代码的圈复杂度,这是否是我应该担心的问题

请参考ValuePojo.getSomething()方法 (请不要担心变量的命名,为了清楚起见,在这个问题中已经重新编写了这个变量)


圈复杂度由代码中执行分支的数量决定
if-else
块、
switch
语句—所有这些都增加了代码的圈复杂度,也增加了确保适当代码覆盖率所需的测试用例数量

为了降低代码的复杂性,我建议您删除没有定义行为的
case
语句,并在
switch
语句中用
default
行为替换它


这是解决这个问题的另一个堆栈溢出。

如果你真的需要把圈复杂度降低,你可以考虑使用一个映射。显然,在您的实现中,应该只创建和初始化一次

  public BigDecimal getSomething() {
      if (this.type == null) {
          return null;
      }
      Map<Type,BigDecimal> map = new HashMap<Type,BigDecimal>();
      map.put(TYPE_A, value1);
      map.put(TYPE_B, value1);
      map.put(TYPE_C, value1);
      map.put(TYPE_D, value1);
      map.put(TYPE_E, value2);
      map.put(TYPE_F, value2);
      map.put(TYPE_G, value2);
      map.put(TYPE_H, value2);
      map.put(TYPE_I, value3);
      map.put(TYPE_J, value3);

      return map.get(type);
  }
public BigDecimal getSomething(){
if(this.type==null){
返回null;
}
Map Map=newhashmap();
地图放置(类型A,值1);
地图放置(类型B,值1);
地图放置(类型C,值1);
地图放置(类型D,值1);
地图放置(类型E,值2);
地图放置(F型,值2);
地图放置(类型G,值2);
map.put(类型H,值2);
map.put(I型,值3);
地图放置(类型_J,值3);
返回map.get(类型);
}

所报告的圈复杂度是什么?11我认为,高到足以触发Sonar中的条件,但不会达到疯狂的程度。您可以将逻辑推到枚举中。感谢您的回答,我确实查看了该线程,但找不到一个“解决方案”来充分解决我的问题。我也不确定是否有问题。我认为圈复杂度是一个相当主观的度量。只要代码是可读的并且能够完成任务,就不必担心更改代码。高度圈复杂度可能会指出对象模型中的问题,但我认为这与您的示例无关。好的。感谢您在本回答中所做的努力问题在于多个值遵循相同的执行路径,但典型的圈复杂度计算将所有“case”语句视为单独的执行路径(因为这样计算很容易)。要么找一个对执行路径要求更严格(即正确)的CC工具,要么对switch语句使用自己的判断,即如果它们正常,就决定不使用它们,但CC表示不正确。如果你曾在谷歌上搜索Java如何“在引擎盖下”工作,你会收到很多人的责骂,因为“预优化iz 4 n00bsz!11!“,但这是了解Java需要付出代价的众多案例之一:……TLDR(以及Luhar的评论):是否删除额外的case语句是武断和主观的,因为我大约90%确信编译器会对lookupswitch语句进行优化(我还没有测试过这个例子,知道100%,因此是90%),但不管怎样,差异会给你带来什么?奇怪的解决方案,谢谢你的想法。不幸的是,在我的例子中,值可能会改变,所以映射必须一直重复。如果你重构value1…3来使用getter和setter(你可能无论如何都应该这样做),这不是问题。这并不是真正降低程序的复杂度,只是通过将逻辑从开关盒移动到映射来隐藏它,使其不受代码分析器的影响。但是开关盒有什么问题,为什么开关被认为是圈复杂度的一部分?据我所知,开关在运行时比其他开关工作得好得多,这与if else相反,切换不需要太多内存地址操作就可以跳转到适当的大小写。切换和映射与二进制代码的编译版本几乎相同。@satellite779,它确实降低了复杂性。当我们看到一行,如
dataRetentionPeriodMap.get(forEmployeeType)
,我们立即了解映射的用途,并可以继续阅读代码。如果这是一个If-else梯形图或switch语句,我们将被迫查看映射(同时也要小心,不要错过任何可能潜入的其他逻辑)如果我们对它感兴趣的话,那么现在。当它是一张地图时,你只能在需要的时候去看地图。这当然会减少我的认知负荷。
  public BigDecimal getSomething() {
      if (this.type == null) {
          return null;
      }
      Map<Type,BigDecimal> map = new HashMap<Type,BigDecimal>();
      map.put(TYPE_A, value1);
      map.put(TYPE_B, value1);
      map.put(TYPE_C, value1);
      map.put(TYPE_D, value1);
      map.put(TYPE_E, value2);
      map.put(TYPE_F, value2);
      map.put(TYPE_G, value2);
      map.put(TYPE_H, value2);
      map.put(TYPE_I, value3);
      map.put(TYPE_J, value3);

      return map.get(type);
  }