写好代码不是一件容易的事,代码能够按照预期效果工作只是最低要求,在这个基础上将代码写得简洁,可维护性高,可以说是一门艺术,今天读了一本书:《The art of readable code》,感触颇深,现摘取一例,与大家分享,为了便于阅读,我将代码简化并用JS重写了一下,先看原始代码:
1 | function reply(userResult, permissionResult) { |
很简单的一段代码,就是根据输入参数的不同取值,打印不同的log,但是代码里一个嵌套的if
语句,导致可读性下降,即使经验再丰富的程序员,也要停留思考一下。罗马不是一天建成的,可读性差的代码也不是一天写成的,通常随着功能的增加,维护人员的增多,代码的可读性会越来越差,其实这段代码一开始逻辑很简单。就是根据userResult
的值不同,做不同的处理。
1 | function reply(userResult) { |
然后突然有一天增加了一个需求,需要根据permissionResult
的值来做进一步的处理,于是该函数多了一个参数,处理逻辑也跟着复杂起来,这便有了文章开头那段代码.
那么如何优化这段代码呢?可以看到外层的if
有点头重脚轻的感觉,我们可以采用优先处理negative case
的方式,这样可以减少嵌套,提高代码的可读性。
1 | function reply(userResult, permissionResult) { |
至此,我们就移出了嵌套的if
,使这两个if
变为平级结构,可读性好多了。需要注意的是,因为我们在两个if
中都使用了return
(return early principle
),所以需要将末尾的console.log("done")
上提到每个if
中,否则会导致逻辑丢失。
原书写到这里就结束了,但是我想再进一步,可以改进后的代码里仍然有多个重复的console.log("done")
,我们可以将其提取出来,别忘了那句名言:Don't repeat yourself
。
在改动之前,先讲一个原理。
将 if{..., return}
结构转换为if-else
结构
如果一个函数中有多个if
,每个if
中都有return
,可以考虑将其转换为if-else
结构。
1 | function foo() { |
等同于:
1 | function foo() { |
所以之前的代码可以继续优化为下面的形式
1 | function reply(userResult, permissionResult) { |
最后把重复的console.log("done")
提取出来即可。
1 | function reply(userResult, permissionResult) { |
最后需要注意的是,这种逻辑性的改动,必须经过严密的单元测试才可以。因为只有两个参数,两两组合,所以测试用例有4个:
1 | userResult = "SUCCESS", permissionResult = "SUCCESS"; |