何为条件表达式?很明显这里讲的应该表达的是if语句的问题。那么if语句在我们编程过程中肯定是用的不规范,或者说有违背我们开头所说的自己管好自己的基本原则。根据本章的标题,那么这章就是要让我们写的条件逻辑更加的简单。首先想一下我们都是怎么写if语句的,一般都是
代码语言:javascript复制if(判断标志){
//各种逻辑和操作
}else{
//各种逻辑和操作
}
那么这种动作难道有错,显然书中肯定不是说这个有问题,如果说这个问题,那肯定也是在《代码简洁之道》那里写的,《重构》更加注重的是合纵联壁的战略思维,让我们看到的是各种类的统筹兼顾。算了,这里还是不猜判断语句的具体问题点了。咋直奔主题吧!
1.分解条件表达式
如果我们有一个复杂的条件语句,那么就从if、then、else语句中分别提炼出独立的函数。这里要表达的意思就是说我们写if语句的判断标志要写成一个函数,如果我们的if判断标志特别大的时候。也确实,如果我们的判断语句很长,那么里边肯定包含了很多逻辑,而且这个逻辑可能包含很多步骤的判断,也就是说这个if判断其实是很多的步骤,那么代码的可读性会很差,但是如果我们将其提炼为函数,那么就有了再次提炼的可能。这样我们的条件语句就可以见文知意,而且其判断函数的内部逻辑也一目了然。
2.合并条件表达式
如果有一系列的条件测试,都得到相同的结果,那么就将这些测试合并为一个条件表达式。并将这个条件表达式独立为一个函数。这块的意思大概就是说代码中的判断语句很多,但是其结果都是一样的,对于这种情况就应该使用逻辑与或者或将其合并为一个条件表达式。书中对条件表达式的合并原因也进行了说明。其一,对于一个判断来说结果相同,那么其本身应该是只执行一次的,但是如果单独处理的话就需要多次,也就是多次的结果相同,在逻辑是没有必要的。其二对立成一个函数的好处就是函数可以将做什么转换为为什么这样做,因为函数自有其注释的特效。
3.合并重复的条件片段
如果条件表达式的每个分支上都有相同的代码片段,那么就将这些重复的代码搬移到条件表达式的外边。这就说的很明白了,各个判断语句里都有相同的代码,那你为何不将其提炼出来呐?当然聪明的我自然想到函数呀的什么的,都可以提炼出来。
对本人来说,本人会将if语句中不断的重复代码不断的降低,最好降低都只有一个值或者变量。然后在外边将做处理。感觉这里的例子其实并不好哦!
当然在书中还写到,我们可以使用try....catch...finaly去做一些判断去重的事情,因为finally会在返回值之前执行。
4.移除控制标志
在一系列布尔表达式中,某个变量带有”控制标志“的作用,那么就用break语句或者return语句取代控制标志。这块的控制标识应就是说我们在代码的判断缓存标志,比如boolean flag=isPemission(user);
然后基于这个判断的标志做了很多的逻辑。书中写到,如果我们使用这种判断标志,其实还是在写C语言风格的代码。书中对break和continue存在的意义也进行的说明。就是为了判断语句存在的。这里的两个例子其实也比较无聊,因为相信大家写的代码都没有重构的必要。
5.使用卫语句取代嵌套条件表达式
函数中的条件逻辑使人难以看清正常的执行路径,那么就用卫语句表现所有的特殊情况。这里的卫语句是什么意思?在if语句有两种,一种就是正常的,if一下就得出结果,而第二种就是if里边嵌套if语句的情况,书中对卫语句的定义是这样的:如果某个条件极其罕见,就应该单独检查条件,并在该条件为真时立刻从函数中返回,这样的单独检查常常称为“卫语句”。相当于说对于特殊的复杂的判断语句就不要往if中迭代了,直接新做一个判断语句并独立出来。同时书中也对条件反转做了介绍,就是使用相反的条件来简化现在的情况,为啥怎么做的原因就是正面有多复杂,那么背面就有多简单。
6.使用多态取代条件表达式
如果手里有个条件表达式,它根据对象类型的不同而选择不同的行为,那这个条件表达式的每个分支都可以放进一个子类内的覆写函数中,人后将原始函数申明为抽象函数。在前边的文章中我们多次说到了多态,其实在重构这本书中是提倡使用多态的,多态就是为了解决不同情况的操作的,因此其天然具有判断的标志。也就是使用了多态你根本都不需要写判断或者switch语句。而且使用if或者switch就会有对其他对象的依赖,那么这样是不好的,违背了基本原则。
书中依然采用职位和薪资的示例:
7.引入null对象
what?不是要避免null,怎么还要引入null对象?黑人问号又多了,这块的意思是你需要再三检查某对象是否为null,并将null值替换为null对象。这里的可能还是不太清楚,我来说一下,引入null对象其实就是要避免代码中的if(!Objects.isNull(...))的这种代码,而是写成if(a.isNull())这种方式。但是使用直接判断一个对象是否为null的问题是什么?为啥这种模式不太好?书中写到要判断一个对象是否为null,那么就意味着重新创建对象。而重新创建对象就又是赋值操作。所以说这块引入null对象就是为了避免显式的创建对象,除此之外如果是用==去判断是否为null,就会导致一个对象在项目的很多地方存在,如果需要变化是不好处理的。
如果我们不去显式创建对象,那么就需要在判断 之后进行隐式的创建对象了,也就是赖加载的模式。我们通过空对象去继承原类,然后重新写对其为空的各种情况进行给定默认值。那么我们就可以根据具体的情况来得到不同的解决,因为空对象已经对为空的情况进行处理,因此我们的if条件都可以去掉了。当然如果需要做一些判断,然后再去决定逻辑的,就可以保留if语句。
8.引入断言
如果某一段代码需要对程序的状态做出某种假设,那么以断言的方式表现这种假设。因为断言最终还是为了判断,而且这种判断为false的时候就会向外抛出一个运行时异常,因此使用断言能够让我们很好的定位一些问题。而且断言也不会影响代码的运行。这块书中介绍到我们在使用断言的时候一定要本着的一个原则就是我下边运行的代码,必须要某个条件为true,不能随便断言。那样是没有意义的。