业务背景:
最近有同事在做门禁未生效预警系统。审核提交的代码时,发现了一段熟悉的内容,内容如下。
这段代码看着很眼熟,查阅了一下,发现之前悦荟在之前优化其它服务的时候优化过这段代码,暂时就不追究为什么这段代码竟然存在于多个服务中了,还是尽早改掉就好。通过阅读代码,发现按照上次的经验,从根源处ThresholdInfoData的结构进行重新设计优化,可能不好修改,设计的地方会比较多。于是考虑采用一种简洁快速的方式,先优化掉这种if else过多的情况——表驱动的方式。
修改前代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 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); } } } } |
修改后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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代码,适用表驱动的方式进行解决。即通过某种映射关系,将逻辑表达式用表格的方式表示;再使用表格查找的方式,找到某个输入所对应的处理函数,适用这个处理函数进行运算。除表驱动的方式,还可以考虑使用反射、策略模式+注解等多种方式处理。
当然,最好的方式还是在最初设计的时候,就做好充分的考虑和结构设计,从根源上避免产生这样的代码。
标签:
【Java】 -- 重构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2021-05-06 【数据库】Oracle -- 一文了解Oracle数据库开发知识地图