【问题标题】:How to reduce the cognitive complexity of sonar for the below code?如何为以下代码降低声纳的认知复杂度?
【发布时间】:2021-08-04 23:29:41
【问题描述】:

以下是我的代码,Sonar 正在抱怨它。要求制作 15,现在是 19。重构此方法以将其认知复杂性从 19 降低到允许的 15。我尝试使用不起作用的枚举。并且它的 transactionId 为 RequestParam。是否有任何 eclipse 工具可以提取这个或者我们需要手动完成。

@GetMapping(value = "display",produces = APPLICATION_JSON_VALUE)
    @ResponseBody
    public List<RspNotification> display(@RequestParam(name = Constants.TRANSACTION_ID) final String transactionId)
    {
        List<RspNotification> list = new ArrayList<>();
        if (manageProductOrderCISStore.get(transactionId) != null)
        {
            list.add(manageProductOrderCISStore.get(transactionId));
        }
        else if (manageAppointmentWWMStore.get(transactionId) != null)
        {
            list.add(manageAppointmentWWMStore.get(transactionId));
        }
        else if (manageAppointmentHWMStore.get(transactionId) != null)
        {
            list.add(manageAppointmentHWMStore.get(transactionId));
        }
        else if (manageAppointmentUnifyStore.get(transactionId) != null)
        {
            list.add(manageAppointmentUnifyStore.get(transactionId));
        }
        else if (manageAppointmentUnifyXmlStore.get(transactionId) != null)
        {
            list.add(manageAppointmentUnifyXmlStore.get(transactionId));
        }
        else if (manageProductOrderFLSStore.get(transactionId) != null)
        {
            list.add(manageProductOrderFLSStore.get(transactionId));
        }
        else if (manageProductOrderHFSStore.get(transactionId) != null)
        {
            list.add(manageProductOrderHFSStore.get(transactionId));
        }
        else if (fulfilmentQuoteEEStore.get(transactionId) != null)
        {
            list.add(fulfilmentQuoteEEStore.get(transactionId));
        }
        else if (manageInventoryHFSStore.get(transactionId) != null)
        {
            list.add(manageInventoryHFSStore.get(transactionId));
        }
        else if (manageInventoryFLSStore.get(transactionId) != null)
        {
            list.add(manageInventoryFLSStore.get(transactionId));
        }
        else if (manageBillingDocumentStore.get(transactionId) != null)
        {
            list.add(manageBillingDocumentStore.get(transactionId));
        }
        else if (serviceHealthStore.get(transactionId) != null)
        {
            list.add(serviceHealthStore.get(transactionId));
        }
        else if (fulfilmentOrderEEStore.get(transactionId) != null)
        {
            list.add(fulfilmentOrderEEStore.get(transactionId));
        }
        else if (manageWorkOrderUnifyStore.get(transactionId) != null)
        {
            list.add(manageWorkOrderUnifyStore.get(transactionId));
        }
        else if (manageDiagnosticAssuranceStore.get(transactionId) != null)
        {
            list.add(manageDiagnosticAssuranceStore.get(transactionId));
        }
        else if (materialsSupplyUnifyStore.get(transactionId) != null)
        {
            list.add(materialsSupplyUnifyStore.get(transactionId));
        }
        ///////// more if statement

        return list;
    }

非常感谢任何帮助,枚举将不起作用。

【问题讨论】:

  • 相同的代码副本粘贴了 3000 次;这显然是错误的。因此,分解重复的内容。似乎您重复了一个清晰的模式-这意味着拉出一种方法。但签名并不是那么简单——你需要一个 lambda。一旦你有了一个 lambda,你就可以静态存储它,因为它是对行为而不是数据的引用……一旦你可以静态存储它。枚举!!
  • 你知道你的列表总是有 0 或 1 个元素,对吧?

标签: java spring-boot sonarqube java-11


【解决方案1】:

列出地图并循环遍历它们

List<Map<String, RspNotification>> maps = Arrays.asList(
    manageProductOrderCISStore,
    manageAppointmentWWMStore,
    manageAppointmentHWMStore,
    manageAppointmentUnifyStore
    //the rest
);

List<RspNotification> list = new ArrayList<>();
for (Map<String, RspNotification> map : maps) {
    RspNotification notification = map.get(transactionId);
    if (notification != null) {
        list.add(notification);
        return;
    }
}
return list;

你可以进一步简化为

return Stream.of(
        manageProductOrderCISStore,
        manageAppointmentWWMStore,
        manageAppointmentHWMStore,
        manageAppointmentUnifyStore
        //the rest
    )
    .map(map -> map.get(transactionId))
    .filter(Objects::nonNull)
    .findFirst()
    .map(Collections::singletonList)
    .orElse(Collections.emptyList());

【讨论】:

  • 这些已经声明如下: protected final Map manageAppointmentHWMStore = new HashMap(); protected final Map manageAppointmentWWMStore = new HashMap(); protected final Map manageAppointmentUnifyStore = new HashMap(); protected final Map fulfilmentQuoteEEStore = new HashMap(); protected final Map manageInventoryFLSStore = new HashMap(); protected final Map manageInventoryHFSStore = new HashMap();
  • @AritChakraborty 不知道你在做什么。我知道他们是这样宣布的,这不会改变我的答案。
【解决方案2】:

将所有这些字典放在一个列表中。运行一个循环,尝试从每个项目中提取密钥并将其添加到列表中。

【讨论】:

    【解决方案3】:

    我看到了 3 种可能性:

    1. 遍历商店列表,如果里面只有一个 - 如果您可以有一个通用的超类/接口,那可能是最好的
    2. 拆分 ifs:假设在 10 之后,您调用 else {another method with the rest of the ifs}
    3. 告诉声纳接受这个(是的,你可以这样做)

    我认为实际上可以为声纳添加一个关于这个的异常,因为在我看来,另一个会使代码更难阅读。

    【讨论】:

      猜你喜欢
      • 2020-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多