业务背景:

最近有同事在做门禁未生效预警系统。审核提交的代码时,发现了一段熟悉的内容,内容如下。

这段代码看着很眼熟,查阅了一下,发现之前悦荟在之前优化其它服务的时候优化过这段代码,暂时就不追究为什么这段代码竟然存在于多个服务中了,还是尽早改掉就好。通过阅读代码,发现按照上次的经验,从根源处ThresholdInfoData的结构进行重新设计优化,可能不好修改,设计的地方会比较多。于是考虑采用一种简洁快速的方式,先优化掉这种if else过多的情况——表驱动的方式。

修改前代码:

private void setThresholdValue(ThresholdInfoData thresholdInfoData, net.sf.json.JSONArray thresholds) {
    if (thresholds.isEmpty()) {
        logger.info("thresholds is null");
        return;
    }  
    int thresSize = thresholds.size();
    for (int j = 0; j < thresSize; j++) {
        if (thresholds.getJSONObject(j).has(Constant.VALUE)) {
            String threshold_desc = thresholds.getJSONObject(j).getString(Constant.THRESHOLD_DESC);
            double value = Double.parseDouble(thresholds.getJSONObject(j).getString(Constant.VALUE));
            int validityValue = Constant.ZERO;
            validityValue = thresholds.getJSONObject(j).get("validity") == null ? validityValue : thresholds.getJSONObject(j).getInt("validity");
            value = validityValue == 1 ? Constant.TEN_THOUSAND : value;
            if (threshold_desc.equals(Constant.OPENINGRATE)) {
                thresholdInfoData.setOpeningRate(value);
            } else if (threshold_desc.equals(Constant.COMPLE_TOTAL_ERROR_THRESHOLD)) {
                thresholdInfoData.setCompileError(value);
                thresholdInfoData.setCompileValidity(validityValue);
            } else if (threshold_desc.equals(Constant.CMTRICS_UNSAFE_FUNC_THRESHOLD)) {
                   thresholdInfoData.setCscheckerUnsafe(value);
                   thresholdInfoData.setCscheckerUnsafeValidity(validityValue);
            } else if (threshold_desc.equals(Constant.CMETRICS_REDUNDANT_CODE_TOATL_THRESHOLD)) {
                 thresholdInfoData.setCscheckerIf0(value);
                 thresholdInfoData.setCscheckerIf0Validity(validityValue);
        } else if (threshold_desc.equals(Constant.STATIC_ERROR)) {
                 thresholdInfoData.setStatiError(value);
                 thresholdInfoData.setStatiErrorValidity(value);
        } else if (threshold_desc.equals(Constant.SOURCEMONITOR_NEW_METHOD_COMPLEXITY_THRESHOLD)) {
                 thresholdInfoData.setSourcemonitorComplexity(value);
        } else if (threshold_desc.equals(Constant.SOURCEMONITOR_NEW_METHOD_STATEMENT_THRESHOLD)) {
                thresholdInfoData.setSourcemonitorStatement(value);
        } else if (threshold_desc.equals(Constant.CMETRICS_CODE_DUPLICATION_RATIO_THRESHOLD)) {
                thresholdInfoData.setSimianDuplicationpercent(value);
                thresholdInfoData.setSimianDuplicationpercentValidity(validityValue);
        } else if (threshold_desc.equals(Constant.CMETRICS_FILE_DUPLICATION_RATIO_THRESHOLD)) {
                thresholdInfoData.setMetricRepeatFilesRate(value);
                thresholdInfoData.setMetricRepeatFilesRateValidity(validityValue);
        } else if (threshold_desc.equals(Constant.LLT_TC_CHANGED_COVERAGE_THRESHOLD)) { 
             thresholdInfoData.setLltChangedCoverage(value);
        } else if (threshold_desc.equals(Constant.LLT_TC_PASS_PERCENT_THRESHOLD)) {
            thresholdInfoData.setLltPassPercent(value);
        }
        }
    }
}                    

修改后的代码:

private void setThresholdValue(ThresholdInfoData thresholdInfoData, net.sf.json.JSONArray thresholds) {
        if (thresholds.isEmpty()) {
                logger.info("thresholds is null");
                return;
        }
        int thresSize = thresholds.size();
        for (int j = 0; j < thresSize; j++) {
            if (thresholds.getJSONObject(j).has(Constant.VALUE)) {
                String threshold_desc = thresholds.getJSONObject(j).getString(Constant.THRESHOLD_DESC);
                double value = Double.parseDouble(thresholds.getJSONObject(j).getString(Constant.VALUE));
                 int validityValue = Constant.ZERO;
                 validityValue = thresholds.getJSONObject(j).get("validity") == null ? validityValue : thresholds.getJSONObject(j).getInt("validity");
                 value = validityValue == 1 ? Constant.TEN_THOUSAND : value;
                 Map<String, BiConSumer<Double, Integer>> actionMappings = getComparisionTable(thresholdInfoData);
                 try {
                        actionMappings.get(threshold_desc).accept(value, validityValue);
                } catch (NullPointerException e) {
                        logger.warn("get" + threshold_desc + " is null");
                }
            }
        }
}


// 生成阈值描述和不同赋值方法的对照表
private Map<String, BiConsumer<Double, Integer>> getComparisionTable(ThresholdInfoData thresholdInfoData) {
    Map<String, BiConsumer<Double, Integer>> actionMappings = new HashMap<>();
    actionMappings.put(Constant.OPENNINGRATE, (a, b) -> {thresholdInfoData.setOpeningRate(a);});
 actionMappings.put(Constant.COMPILE_TOTAL_ERROR_THRESHOLD, (a, b) -> {
    thresholdInfoData.setCompileError(a);
    thresholdInfoData.setCompileValidity(b);
 });
  actionMappings.put(Constant.CSCHECKER_UNSAFE_FUNC_THRESHOLD, (a, b) -> {
    thresholdInfoData.setCscheckUnsafe(a);
    thresholdInfoData.setCscheckerUnsafeValidity(b);
 });
actionMappings.put(Constant.CMTRICS_REDUNDANT_CODE_TOATL_THRESHOLD, (a, b) -> {
    thresholdInfoData.setCscheckerIf0(a);
    thresholdInfoData.setCscheckerIf0Validity(b);
 });
actionMappings.put(Constant.STATIC_ERROR, (a, b) -> {
    thresholdInfoData.setStatiError(a);
    thresholdInfoData.setStatuErrorValidity(b);
 });
actionMappings.put(Constant.SOURCEMONITOR_NEW_METHOD_COMPLEXITY_THRESHOLD, (a, b) -> {
    thresholdInfoData.setSourcemonitorComplexity(a);
 });
actionMappings.put(Constant.SOURCEMONITOR_NEW_METHOD_STATEMNET_THRESHOLD, (a, b) -> {
    thresholdInfoData.setSourcemonitorStatement(a);
 });
actionMappings.put(Constant.CMETRICS_CODE_DUPLICATION_RATIO_THRESHOLD, (a, b) -> {
    thresholdInfoData.setSimianDuplicationpercent(a);
    thresholdInfoData.setSimianDuplicationpercentValidity(b);
 });
actionMappings.put(Constant.CMETRICS_FILE_DUPLICATION_RATIO_THRESHOLD, (a, b) -> {
    thresholdInfoData.setMetricRepeatFilesRate(a);
    thresholdInfoData.setMetricRepeatFilesRateValidity(b);
 });
actionMappings.put(Constant.LLT_TC_CHANGED_COVERAGE_THRESHOLD, (a, b) -> {
    thresholdInfoData.setLltChangedCoverage(a);
 });
actionMappings.put(Constant.LLT_TC_PASS_PERCENT_THRESHOLD, (a, b) -> {
    thresholdInfoData.setLltPassPercent(a);
 });
  return actionMappings;
}

  

总结:

对于上述这种逻辑表达模式固定的if else代码,适用表驱动的方式进行解决。即通过某种映射关系,将逻辑表达式用表格的方式表示;再使用表格查找的方式,找到某个输入所对应的处理函数,适用这个处理函数进行运算。除表驱动的方式,还可以考虑使用反射、策略模式+注解等多种方式处理。

当然,最好的方式还是在最初设计的时候,就做好充分的考虑和结构设计,从根源上避免产生这样的代码。

posted on 2023-05-06 00:40  人无名,则可专心练剑  阅读(51)  评论(0编辑  收藏  举报