养成好习惯,代码才好看_2

程序代码,首先是给人看的,其次才是给机器运行的。

为了保证代码的可读性,我们需要很多好习惯。

在上期文章里,我分享了见名知意,和层次清晰,这两个好习惯,今天我来分享第3个和第4个好习惯——避免歧义,和减少重复。

3. 避免歧义

所谓歧义,是指大家对同一个事物,出现了不同解读方式的情况。

比如说,在我国古代,人们写字是不加标点符号的,于是,

"无鸡鸭也可",这句话就有2种解读方式:

① 无鸡鸭,也可;

② 无鸡,鸭也可;

在程序代码中,可能也会有类似的情况。

例如,下方这段代码:

var arr = [ 0, 0 ];
var i = 0;
arr[i] = ++i; // 有歧义

首先定义了一个叫 arr 的数组,长度为 2,它的两个元素都等于 0;然后定义一个叫 i 的变量,初始值为 0;这之前都没有歧义,下面就开始有歧义了;

"arr[i] = ++i;" 这一句,可以有两种理解方式:

① arr[i] = i + 1; ++i; 相当于 arr[0] = 1;

② ++i; arr[i] = i; 相当于 arr[1] = 1;

第三行代码,在不同的编程语言里,可能会有不同的运行结果;甚至是同一种编程语言,在不同环境下运行这种代码,有可能也出现不同的结果。

这种情况被称作 "未定义行为" (Undefined Behavior, UB),大家应该避免它。

还有时候,虽然代码运行的结果唯一,但是我们阅读的时候,可能会理解错误。

例如,不同级别的运算符同时出现,我们最好加上小括号:

int len = (right - left) >> 1;

这样看,显然是先计算 right - left,然后进行位移运算,不会有歧义;

而如果写成:

int len = right - left >> 1;

虽然代数运算的优先级高于位运算,但是,有人看到它,可能会误解成,先计算 left 右移 1 位的值,然后用 right 减去这个值,从而产生歧义。

再比如,判断条件同时出现 and 和 or 运算的时候,最好也套括号:

if (x > 1 || (y != null && z < 0)) {
    // ...
}

或者是,把复杂的条件拆分:

if (x > 1) {
    // ...
}
if (y != null && z < 0) {
    // ...
}


4. 减少重复

很多编程初学者,容易出现一个问题,经常有多处相同或相似的代码。这个习惯不好,因为,代码的冗余,会降低可读性,并且也不利于后期的维护。

正确的做法是:

把相同意义的值定义为变量,把相似的逻辑定义为函数,把相似的结构封装为类或结构体。

例如,当我们需要用到圆周率时,不要直接写成 3.14 之类的字面值,而是要定义成变量,即使它在运行过程中,数值一直不变。

如果你用的编程语言支持常变量,那你最好把这种数值定义为常变量,例如 C++:

const double Pi = 3.14;

当我们需要修改圆周率的值时,只修改这一个地方即可,而不需要到处改。

那么,查找替换行不行呢?答案是: 不行 !

如果有另外的变量碰巧也等于 3.14,但它和圆周率没关系,那我们替换的时候,就把不该修改的地方也改了。

对于代码中多次出现的相似的逻辑,我们应该写成函数的形式;

例如,对数组元素求和,我们对比一下:

var arr_1 = [ 1, 0, 5, 7 ];
var arr_2 = [ 8.5, -2, 0.3 ];
var arr_3 = [ 1024, -32, 25 ];
// 好的写法:
function GetSum(arr) {
    var sum = 0;
    for (var i = arr.length; --i >= 0;) {
        sum += arr[i];
    }
    return sum;
}
var res = [ 0, 0, 0 ];
res[0] = GetSum(arr_1);
res[1] = GetSum(arr_2);
res[2] = GetSum(arr_3);
// 差的写法:
res[0] = 0;
for (var i = arr_1.length; --i >= 0;) {
    res[0] += arr_1[i];
}
res[1] = 0;
for (var i = arr_2.length; --i >= 0;) {
    res[1] += arr_2[i];
}
res[2] = 0;
for (var i - arr_3.length; --i >=0;) {
    res[2] += arr_3[i];
}

显然,第一种写法,代码结构清晰,可读性更高;

另外,如果后期需要修改求和的逻辑,我们只需要改动这个函数,而不需要到处改。

至于类和结构体,且听我下回分解。


下期预告:

5. 勤于注释; 6. 善于封装;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值