读书报告之《修改代码的艺术》 (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,写得不错。这里推荐一下

时间: 2024-10-31 22:24:31

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

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

<修改代码的艺术>,英文名<Working Effectively with Legacy Code>,中文翻译的文笔上绝对谈不上"艺术"二字,愧对艺术二字(当然译者不是这个意思).书中第三部分不论是例子还是解说都有点混乱,远不如<重构--改善既有代码设计>一书.此书精华在于第一.二部分. 如何学习这本书,作为一个最底层的码农,作为长期在别人代码上修修补补的苦逼二手货开发人员,我只能给的建议就是:你可以将它看做是如何做定制功能的指导书--从某种意义上

修改代码的艺术笔记

使用单元测试使修改代码变得简单. 在编程的时候考虑测试:使用类的方法来代替方法,这样可以通过在测试中编写继承类,改变相应方法的行为,达到避免执行某些函数的目的,更好的解依赖. 使用包含预处理的头文件来制造接缝.#ifdef TESTING...  endif 通过修改链接时的包含路径,另外的写专门用于测试的类.(最佳,清晰而且便于维护测试代码) 如果是函数调用的内部函数是多态的,通过基类的对象传参,通过测试对象控制内部函数的行为,而不要封装new来的对象在函数内部. 不用static和私有函数,

修改代码的艺术读后感

这本书提到了一个我曾近不知道的概念:遗留代码.所谓遗留代码,指的是随着时间流逝,之前的代码纵使再完美无缺,也不可避免的产生腐化,失去原有的便利而显得腐朽发臭或者说没有编写测试的代码,或者说是遗留代码有许多预防措施,但是它的产生不可避免.如何解决它是整本书的核心. 书的第一部分,介绍了代码的修改机理,包括感知.分离和接缝和工具的使用,同时简要介绍了遗留代码以及测试的重要性.可以说,扭转遗留代码离不开测试. 遗留代码修改算法包括以下几步: (1) 确定改动点:(前提:理解代码) (2) 找出测试点:

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

今天继续从本书的第二章学习, 昨天我们已经总结了下面三个内容 1. 降低修改的风险 2. 需要修改大量相同的代码 3. 时间紧迫,必须修改 今天继续第四点 4. 修改时应当测试哪些方法 作者提出了影响结构图的概念.说穿了,就是CallRelation和ReferenceRelation,就是查看某个方法(变量)被哪些方法引用,以及自身又引用了哪些方法,依次类推.这个复杂的关系网实际就是一颗风险评估树(图).通过这棵树,我们可以知道某个修改会影响到哪些节点.这项参数,既是风险的直接量化指标,同时又

读书报告之《改动代码的艺术》 (I)

<改动代码的艺术>,英文名<Working Effectively with Legacy Code>,中文翻译的文笔上绝对谈不上"艺术"二字.愧对艺术二字(当然译者不是这个意思).书中第三部分不论是样例还是讲解都有点混乱,远不如<重构--改善既有代码设计>一书. 此书精华在于第一.二部分. 怎样学习这本书,作为一个最底层的码农,作为长期在别人代码上修修补补的苦逼二手货开发者,我仅仅能给的建议就是:你能够将它看做是怎样做定制功能的指导书--从某种意义

《编写可读代码的艺术》读书笔记

表面内容 1.代码的写法应当是别人理解他所需的时间最小化.一条注释可以让你更快理解代码.尽管减少代码行数是一个好目标,但是八里街代码所需的时间最小化是一个更好的目标. 2.选择专业的词,比如函数名使用getxxx(),这个get没有表达出很多信息,是从缓存中得到?从数据库中得到?或者从网络得到?如果是网络,可以用更专业的fetchxxx()或者downloadxxx() 3.tmp,retval这样泛泛的名字,可以根据情况命名,比如tmpFile,让人知道变量是一个临时的文件.(tmp这个名字只

《编写可读代码的艺术》——简单总结

上个月好像冥冥中自有安排一样,我在图书馆看到这本 <编写可读代码的艺术> ( The Art of Readable Code) 期间因为工作的原因,停停看看,这几天终于看完了,可以大概总结如下: 1. 把信息装进名字里,给变量起个好名字 2. 审美,把代码分成段落,对齐 3. 应当取个好名字,而不是用注释去粉饰它 4. 用注释记录你的思想,比如当时为什么要这样写,记录开发过程中有哪些思考 5. 将自己代码中的不足和瑕疵记录下来,方便今后别人的维护,不要顾忌别人的看法! 6. 注释应该言简意赅

编写可读代码的艺术笔记

编写可读代码的艺术 表面层次上的改进 命名.注释以及审美--可以用于代码库每一行的小提示. 简化循环和逻辑 在程序中定义循环.逻辑和变量,从而使得代码更容易理解. 重新组织你的代码 在更高层次上组织大的代码块以及在功能层次上解决问题的方法. 精选话题 把"易于理解"的思想应用于测试以及大数据结构代码的例子. 第1章:代码应当易于理解 1.代码应当易于理解. 2.代码的写法应当使别人理解它所需的时间最小化. 第一部分:表面层次的改进 第2章:把信息装到名字里 1.使用专业的单词. 2.避

编写可读性代码的艺术

在做IT的公司里,尤其是软件开发部门,一般不会要求工程师衣着正式.在我工作过的一些环境相对宽松的公司里,很多程序员的衣着连得体都算不上(搞笑的T恤.短裤.拖鞋或者干脆不穿鞋).我想,我本人也在这个行列里面.虽然我现在改行做软件开发方面的咨询工作,但还是改不了这副德性.衣着体面的其中一个积极方面是它体现了对周围人的尊重,以及对所从事工作的尊重.比如,那些研究市场的人要表现出对客户的尊重.而大多数程序员基本上每天主要的工作就是和其他程序员打交道.那么这说明程序员之间就不用互相尊重吗?而且也不用尊重自