首页 > 代码库 > 读书报告之《修改代码的艺术》 (II)续2

读书报告之《修改代码的艺术》 (II)续2

这里作为(II)的第二个续篇,继续复杂的嵌套if else 的处理。 为了保持篇幅不会太长,以一篇新的文章形式给出。

化简复杂的if else语句,基本的手段

  1. 针对头重脚轻的if else,使用return快速返回,从而减少嵌套层数。
  2. 合并分支。有些分支的执行内容相同,往往意味着可以合并为一个分支
  3. 扁平化。

这里给出最后一个举例,也是从网上随便搜索摘录的

原始代码


		List<TWorkFlowwork> wfwList=errorProcessingService.findWorkFlowworkByWorkType("7",workbillcode.getId()+"");
		boolean flag=false;
		if(wfwList!=null&&wfwList.size()>0){
			for(int i=0;i<wfwList.size();i++){
				TWorkFlowwork wfw=wfwList.get(i);
				if(wfw!=null){//当前待办是原件校验并且如果已经结束了则激活原件校验待办
					if(wfw.getStatus()!=null&&!"".equals(wfw.getStatus())){
						if("1".equals(wfw.getStatus())){
							flag=true;
							break;
						}
					}
					
				}
			}
			if(!flag){//如果原件校验待办都结束了,则产生一条原件校验待办
				TWorkBillcode wb=errorProcessingService.findWorkBillcodeByParameters(flow.getBussid(),flow.getBusstype());
				wb.setIsmatchpage("1");
				errorProcessingService.updateWorkBillcode(wb);
			}
		}


老规矩,简单点评一下这个代码:唉~~~~~~~
  • 魔幻数字"7",“1”
  • 大量的空对象判断。 这个不是表示严谨,而是代码设计有问题
  • 极深的if else 嵌套,主要都是极端的头重脚轻形式的if 语句
首先,if(wfwList!=null&&wfwList.size()>0){ 超级的头重脚轻,采用return 直接返回
其次,for(int i=0;i<wfwList.size();i++){  TWorkFlowwork wfw=wfwList.get(i);  可以利用java的语法甜头,或者说是惯用法,替换为for (TWorkFlowwork wfw : wfwList)
然后,if (wfw!=null) 又可以用卫语句处理,不过这里不能使用return直接返回,而是应该用continue
最后,后面if status的判断实际都可以合并起来
if(wfw.getStatus()!=null&&!"".equals(wfw.getStatus())
				&& "1".equals(wfw.getStatus())){
						flag=true;
						break;
			}
仔细分析,不难发现wfw.getStatus()!=null&&!"".equals(wfw.getStatus()) 根本是多余的。
于是代码变成这个样子
List<TWorkFlowwork> wfwList=errorProcessingService.findWorkFlowworkByWorkType("7",workbillcode.getId()+"");
		boolean flag=false;
		if(wfwList==null || wfwList.size()==0) { return; }
		for (TWorkFlowwork wfw : wfwList) {
			//当前待办是原件校验并且如果已经结束了则激活原件校验待办
			if (wfw == null) { continue; }
			if("1".equals(wfw.getStatus())){
				flag=true;
				break;
			}
		}
		if(!flag){//如果原件校验待办都结束了,则产生一条原件校验待办
			TWorkBillcode wb=errorProcessingService.findWorkBillcoHideByParameters(flow.getBussid(),flow.getBusstype());
			wb.setIsmatchpage("1");
			errorProcessingService.updateWorkBillcode(wb);
		}


接下来,本来想对第一个循环做一个方法抽取,因为实际操作比较像查询——查询是否所有原件已经校验结束。改成查询之后,不仅含义上清楚到无需注释,而且可以去掉讨厌的标记变量flag以及wfwList为空的判断。
可惜没有全部代码,不知道这样修改是否会产品副作用。因为对最后一段“如果原件校验待办都结束了,则产生一条原件校验待办”这个注释无法拿捏得很准,这个“产生一条”是指产生下一条?
所以说,理想的情况是让代码自注释。如果写了注释,一定要维护代码的同时维护注释,错误的注释比没有注释更糟糕。不管如何,原本复杂的if else 我们已经大大简化了。
最后再啰嗦一下,面试时代码的编写确实是必不可少的一部分:从这份代码就可以看出
  • 原作者对java的基本语法不熟;// 循环语句很拙劣,可能是从C转入没多久
  • 之前系统的培训过或者认真看过相关编码的书; // 大量的魔幻数字,wfwList.size()==0 而不是isEmpty() 
  • 代码量不大。// 这个代码片段不长,却非常费解。而且代码层次感不强,各种高层的接口和底层的接口杂糅在一起


最后的最后,做个简单的总结。

这一部分主要是举例讨论复杂的锯齿形 if else语句的处理。基本方法不外乎三个
  1. 针对头重脚轻的if else,使用return快速返回,从而减少嵌套层数。
  2. 合并分支。有些分支的执行内容相同,往往意味着可以合并为一个分支
  3. 扁平化。
里面的举例,一般我是尽可能按照重构,一步步的列出。
  1. 修改if else 最忌惮的是天马行空,自负自己对代码的理解,直接重新改写条件语句。但另一方面,相信各位看官也注意到了,理解又是必不可少的,完全死死的做逻辑变形是异常繁琐的(这个在第二个例子中尤为明显),具体如何操作,不好意思,这就是"修改代码的艺术"。口才不行,修行还靠个人。
  2. 不要做不成熟的优化。相对来说,代码的清晰度高于性能的优化,而且很多时候两者并不是冲突的,当代码更清新了,往往有更好的优化方案。
  3. 举例中的一些代码风格,比如return快速返回,不是每个人都能接受。求同存异,这也是个人座右铭。
  4. 大千世界,简化 if else的方法肯定不止上面几种。但这几种还是很实用,欢迎个人崇拜,不要怀疑者,不要脑残粉。(玩笑大笑,勿当真,只是想说,"不要怕,不要悔",刚开始时,尽管做,不要太多怀疑)

最后,如果对重构还有兴趣,可以看一看《重构--我的遗留系统改进之路》,这是一个培训ppt,写得不错。这里推荐一下

读书报告之《修改代码的艺术》 (II)续2