七叶笔记 » golang编程 » 如何简化代码循环和逻辑?

如何简化代码循环和逻辑?

简化循环和逻辑

核心思想:把条件、循环以及其他对控制流的改变做得越“自然”越好。运用一种方式使读者不用停下来重读你的代码。

1、简化控制流

1.1 条件语句中参数的顺序

变量通常放在左侧,被比较的值放在右侧。

比如

if (length > 10)

就比

if (10 < length)

要好

1.2 if/else语句块顺序

通常条件语句块的顺序可以自由安排,这里有几种建议可能会让顺序变得更好:

1、首先处理正逻辑而不是负逻辑的情况。例如,用if(debug)而不是if(!debug)

2、先处理掉简单的情况。这种方式可能还会使得if和else在屏幕之内都可见

3、先处理有趣的或者是可疑的情况

有时这些建议可能有冲突,还是要根据实际情况进行选择,总得原则还是看起来易于理解就可以了。

1.3 三目运算符

很多语言支持三目运算符,类似cond?a:b这种写法,其实是if/else的另一种紧凑写法。一个建议是,如果三目运算符中的表达式比较简单易懂,可以使用,例如

就比下面写法更好

但如果表达式复杂,不再是从两个简单的变量中做出选择,那么还是使用if/else比较好。例如:

就不如下面的易懂。

1.4 避免do/while循环

do/while循环总是会执行一边,至于是否会再执行取决于后面的条件。从写法上看,条件总是放在最后,而不是放在开头,这会造成心理“包袱”,当读到循环体的时候,你会一直惦记着条件是什么,看到条件又得回过头来再看一遍。

另外do/while再配合上continue语句,会更让人疑惑,比如下面的语句,你能一下子反应过来他做了什么吗?

1.5 从函数中提前返回

从函数中提前返回有助于让代码更好理解和简单,尤其是配合if语句用于判断一些异常情况,满足了就直接返回。例如:

1.6 避免使用goto

现在流行的语言基本很少有这个语句了。

1.7 最小化嵌套

嵌套很深的代码很难以理解。每个嵌套层次都在读者的“思维栈”上增加了一个条件。当读者见到一个右大括号(})时,可能很难“出栈”来回忆起它背后的条件是什么。

有几个方法可以减少嵌套。

通过提早返回来减少嵌套

通过改变条件和提前返回达到减少嵌套的目的,经过改进,下面的代码明显好于前面的写法。

减少循环内的嵌套

提前返回return可能不一定适用在循环体中,这个时候可以使用continue达到类似的效果。比如:

通过continue和提前返回来简化,效果如下:

2、拆分超长的表达式

核心思想:把你的超长表达式拆分成更容易理解的小块。

2.1 使用解释的变量

拆分表达式最简单的方式就是给它一个变量名,用变量名代替它,这个额外的变量有时叫做“解释变量”,它可以说明表达式的含义

引入一个解释变量,可读性提升。

2.2 总结变量

即使一个表达式不需要解释(因为你可以看出它的含义),把它装入一个新变量中仍然有用。我们把它叫做总结变量,它的目的只是用一个短很多的名字来代替一大块代码,这个名字会更容易管理和思考。

我们把表达式提取出来,专门用一个变量进行表示,更容易理解。

2.3 使用德摩根定理

对于一个布尔表达式,有两种等价的写法:

试着用德摩根定理,把表达换一种写法,可能效果会更好。

转换成等价的写法,这样容易理解多了。

2.4 滥用短路逻辑

在很多编程语言中,布尔操作会做短路计算。例如,语句if(a||b)在a为真时不会计算b。使用这种行为很方便,但有时可能会被滥用以实现复杂逻辑。

上面的写法就不如下面这么下,虽然会增加代码行数,但是更便于理解。

短路逻辑并非没有用武之地,而是避免和复杂的表达式混在一起,但用在恰当的地方也是不错的选择,比如

3、 变量与可读性

本小节主要解决下面三个问题:

1.变量越多,就越难全部跟踪它们的动向。

2.变量的作用域越大,就需要跟踪它的动向越久。

3.变量改变得越频繁,就越难以跟踪它的当前值。

3.1 减少变量

前面提到增加“解释性”和“总结性”变量,这跟减少变量并不冲突,我们的目标是 减少那些不能改进可读性的变量。

没有价值的临时变量

判断是否有价值,可以参考以下几个方面:

它没有拆分任何复杂的表达式

它没有做更多的澄清

它只用过一次,因此它并没有压缩任何冗余代码

now变量在这里就显得多余

减少中间结果

使用前面提到的提前返回技巧,可以减少一些不必须要的中间变量

提前返回,这样代码就显得更简洁易懂,同时不必引入中间变量

减少控制流变量

有时候通过增加done或者flag等控制变量来控制循环,如果仅仅是控制循环,没有其他作用,其实可以通过优化代码结构来消除这样的冗余变量

done这个变量只是用于控制循环,通过改进代码结构,可以不需要引入这个多余的变量。

4、缩小变量的作用域

核心思想:让你的变量对尽量少的代码行可见。

假如有一个很大的类,有一个成员变量只有两个方法用到,如下:

某种意义上讲,成员变量就是一个“小型全局变量”,能尽量不用最好不用。找出这种非必要的成员变量,把他们降格为局部变量。

有些语言有块级作用域(比如if/while等)的概念,比如C/Java/Golang等,如果你的变量只在块级作用域中使用,比如

可以通过if中的条件进行定义

还有一种技巧是通过“闭包”来屏蔽变量,假如你有一个长期存在的变量,只有一个函数会用到它,例如:

通过“闭包”的写法,来“消除”这个变量。

最后,值得一提的是,每种语言作用域各不相同,你要熟悉每种语言的作用域。比如,JavaScript中如果没有用var/const/let定义变量,那么默认就是全局作用域;python中没有块级作用域的概念。

相关文章