当前位置: 首页 > 后端技术 > Java

【代码拯救行动】10月CodeReview案例+重构

时间:2023-04-01 15:59:07 Java

CodeReview问题汇总案例1先来看一段代码//根据Y01,Y03匹配公募基金一年三年的数据为(ProfitRelativeprofitRelative:publicFund.getProfitRelativeList()){if("Y01".equals(profitRelative.getDuration())){profitsRelative.getProfitRate();}if(profitRelative.getProfitRank()==null||profitRelative.getProfitRank()==0||profitRelative.getProfitRankTotal()==null||profitRelative.getProfitRankTotal()==0){exceedRank[0]=null;}else{exceedRank[0]=100-(profitRelative.getProfitRank()*100/profitRelative.getProfitRankTotal());}}elseif("Y03".equals(profitRelative.getDuration())){profitsRelative.getProfitRate();如果(profitRelative.getProfitRank()==null||profitRelative.getProfitRank()==0||profitRelative.getProfitRankTotal()==空||profitRelative.getProfitRankTotal()==0){exceedRank[1]=null;}else{exceedRank[1]=100-(profitRelative.getProfitRank()*100/profitRelative.getProfitRankTotal());}}}一开始看起来很吓人。让我们一步步重构它。重复是万恶之源重复1:分支Y01和分支Y03的逻辑完全一致。此时,我们实现了第一个重构方法,将相同的逻辑提取到一个方法中。privatestaticdoublewinPercent(){if(profitRelative.getProfitRank()==null||profitRelative.getProfitRank()==0||profitRelative.getProfitRankTotal()==null||profitRelative.getProfitRankTotal()==0){返回=空;}else{返回100-(profitRelative.getProfitRank()*100/profitRelative.getProfitRankTotal());}}重复2:判断int是否非空。此时我们执行相同的重构方法privatestaticbooleananyNullOrZero(Integer...values){for(Integervalue:values){if(value==null||value==0){returntrue;}}返回错误;}privatestaticdoublewinPercent(ProfitRelativeprofitRelative){if(anyNullOrZero(profitRelative.getProfitRank(),profitRelative.getProfitRankTotal())){return=null;}else{return100-(profitRelative.getProfitRank()*100/getProfitRankTotal());}}反转判断,减少分支,尽量不要用!在if语句中,尽可能突出核心逻辑。下面进行第二种重构手段。一、publicclassXXUtils{//如果需要取反,直接加一个方法,比在判断语句中使用`!`好太多了publicstaticbooleannoneNullOrZero(Integer...values){return!anyNullOrZero(值);}privatestaticbooleananyNullOrZero(Integer...values){for(Integervalue:values){if(value==null||value==0){returntrue;}}返回假;}}privatestaticdoublewinPercent(ProfitRelativeprofitRelative){//翻转,删除无用的else分支if(XXUtils.noneNullOrZero(profitRelative.getProfitRank(),profitRelative.getProfitRankTotal())){return100-(profitRelative.getProfitRank()*100/profitRelative.getProfitRankTotal());}返回空值;}方法下沉,字段拥塞getWinPercent()应该作为成员方法下沉到类ProfitRelative中。这里需要强调一下,很多同学喜欢在服务中堆砌逻辑,导致代码贫血甚至失血。其实只要把逻辑放在领域对象中,就可以让逻辑清晰很多,代码也可以不拥挤。publicclassProfitRelative{privateIntegerprofitRank;privateIntegerprofitRankTotal;publicIntegergetWinPercent(){if(noneNullOrZero(profitRank,profitRankTotal)){return100-(profitRank*100/profitRankTotal);}返回空值;代码变成这样://根据Y01,Y03,匹配公募基金一年和三年的数据())){利润[0]=profitRelative.getProfitRate();exceedRank[0]=profitRelative.getWinPercent();}elseif("Y03".equals(profitRelative.getDuration())){profits[1]=profitRelative.getProfitRate();exceedRank[1]=profitRelative.getWinPercent();}}上面的代码还有改进的余地,可以继续重构的方式。这里只是展示重构是如何一步步实现的:小修、测试、修改。案例2看到这个案例,第一反应就是难以理解。主要有几个问题:java8stream的滥用导致代码难以理解ListtoMap,其实还是O(n),不如直接遍历理解重复null判断publicvoidchangeRateByManager(){if(CollUtil.isNotEmpty(rateTypeList)){Map>collect=rateTypeList.stream().collect(Collectors.groupingBy(RateType::getRateType));BigDecimaly031=可选。ofNullable(collect).map(ra->ra.get("Y03")).map(y03->y03.get(0)).map(RateType::getRate).orElse(null);if(rate.compareTo(BigDecimal.ZERO)<0){if(null==y031||y031.compareTo(BigDecimal.valueOf(-100))==0){BigDecimalYBG=Optional.of(collect).map(ra->ra.get("YBG")).map(y03->y03.get(0)).map(RateType::getRate).orElse(null);if(YBG!=null&&YBG.compareTo(BigDecimal.valueOf(-100))!=0){rateDescription="成立以来的收益率";率=YBG;}}else{rate=y031;rateDescription="过去3年的收益率";}}}}开始重构从列表中取出对应的RateType,抽取一个方法getRateType()需要注意的是,这里不返回null。这样可以避免每次获取RateType时都进行null判断。具体做法是把空判断方法放在RateType里面,然后用一个工厂方法返回一个没有灵魂的RateType。//注意,没有返回nullprivateRateTypegetRateType(Stringspan){if(rateTypeList==null||span==null)returnRateType.empty();for(RateTypert:rateTypeList){if(span.equals(rt.getRateType()))返回rt;}返回RateType.empty();}privatebooleanisNegative(){returnrate.compareTo(BigDecimal.ZERO)<0;}privatevoidsetRateAndDescription(BigDecimalrate,Stringdescription){setRate(rate);setRateDescription(描述);}//修改后publicvoidchangeRateByManagerV2(){if(CollUtil.isEmpty(rateTypeList))return;if(isNegative()){RateTypey03=getRateType("Y03");if(y03.isNotEmpty()){setRateAndDescription(y03.getRate(),"近3年收益率");}else{RateTypeybg=getRateType("YBG");如果(ybg.isEmpty()){setRateAndDescaption(ybg.getRate(),"成立以来收益率");}}}}publicclassRateType{privateBigDecimalrate;私有字符串速率类型;booleanisEmpty(){返回率==null||rate.compareTo(BigDecimal.valueOf(-100))==0;}booleanisNotEmpty(){return!isEmpty();}//工厂方法,避免返回nullpublicstaticRateTypeempty(){returnnewRateType();}}