提高代码可读性的技巧

Published: 2015-12-15 Category: 重构

为什么要提高代码可读性

Bob大叔在《代码整洁之道》(英文版《Clean Code》)提到过他曾做过一个类似竞技游戏(魔兽、Dota、LOL等)中“第一视角”的视频,去查看自己编码工作时到底大部分时间都在做什么,结果发现自己80%(甚至更多)的时间都是在屏幕相关代码类、代码行之间跳来跳去的观看并理解代码所做的事情,只有20%的时间是动手编码,即二八原则在此处依旧成立。

除了上述Bob大叔的例子外,程序员大部分时候也都是在维护(别人写的或者自己写的)代码,而维护的前提当然是先确保自己充分理解代码的意图和作用,方可更得心应手的修改扩展,一个具有高可读性的好代码往往比一个“不知道在做什么”的烂代码更好维护和扩展!

烂代码的好处和坏处

或许有些人会嗤之以鼻:业务(能多挣钱)才是王道,代码写得好不好没人关心!对此其实做过程序员的应该都有体会,确实或许牛逼的产品,其代码不一定多好,因为好的产品是实战中经历了各种考验打磨出来的,N次改版重做;N次临时推翻重构;也可能是N次在“期限”这个时间压力下被“逼”出来的,谁还在乎代码质量,只要在“期限”前能运行正确就行。。。毕竟软件行业中正真不变的是变化(变化是一直在变的)!或许烂代码唯一的好处就是:先这样吧,先正确按时上线没大问题再说。。。

但考虑到为了能挣更多钱(推出更多新颖产品),很多功能都是在之前功能基础上做调整增强的:

  • 假如之前的代码质量很烂,中后期的修改扩展就会出现各种怨声载道:为什么之前这么写(代码作者当时是怎么想的)?这个是谁写的烂代码(查看提及记录看到自己的名字时别震惊)?我被之前的代码坑了(前人挖坑后人跳/填,出来混迟早要还的,算是之前烂代码所欠下的债)。。。
  • 假如之前的代码可读性还不错的话,那修改起来就比较省心,如果配上可读的单元测试的话就再好不过了(但Unit Test和TDD在中国市场环境下好像少得可怜?),如此一来程序员们即能开心的挣钱,有省出多余的时间去做自己喜欢的事情了

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

这里记录下《编写可读代码的艺术》里面提到的建议技巧,结合之前阅读《重构》《代码整洁之道》以及工作中的一些经历,记录下自己的理解,毕竟“好记性不如烂笔头”

book0

第1章——代码应该易于理解

主题思想——代码应该易于理解

这个思想类似于《点石成金》(英文版《Don't Make Me Think》),即一段功能代码,我看到它的时候最好立即明白它在做什么,别让我去想:为什么变量名叫openOrClose或者tmp?为什么那么别扭、拐弯抹角的去做一些事情?不能更直接一点吗?从此也衍生出了一条关键思想:

关键思想——代码的写法应该是别人理解它所需的时间最小化

即找一个人过来,让他看下你的代码,你觉得他多久能完全理解?这样的情况有点结对编程的意思,2个人结对编程,1人编写另一人看下是否自己容易理解,对可以改进的地方提出自己的建议,2人一起互相提建议令代码更好。

结对编程的替代

但实际情况是结对编程在90%公司根本不可能有,但可以在提交代码测试前2至3人一起review代码,可以让编码者口述功能实现流程,其它人听并一起过一下代码,有更好的建议可以提出来,而且在编码者口述过程中,自己有说不清楚想不明白的地方,在经过大脑转换成口语表达的过程中达到理清思路的作用,很有可能发现隐藏的bug

代码总是越短小越好吗?

当然对理解一个上万行的类来说,理解200至300行的类相对来说较容易。但代码并非越短越好,单纯的追求短小很有可能造成Make Me Think的停滞:

assertThat(((bucket=findBucket(key) != null)) && !bucket.isOccupied());

上面主要多了一条赋值bucket的内部语句,会导致读者需要花心思关注一下,而下面就比较直白了:

bucket = findBucket(key);
if(bucket != null){
    assertThat(!bucket.isOccupied());
}

还有一个经常让我纠结的,到底是使用三元操作符呢还是if else:

return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);

上面的版本更紧凑短小,但是下面这个更直白:

if(exponent >= 0){
    return mantissa * (1 << exponent);
}else{
    return mantissa / (1 << -exponent);
}

去看看哈希算法\各种位运算如何实现就发现原来也存在短小的代码根本不知道在做什么。。。如此一来注释往往是理解晦涩代码的最好方式了,记住:

尽管减少代码数是一个好目标,但是吧理解代码所需要的时间最小化是一个更好的目标

(未完待续。。。)

  • 版权声明:自由转载-非商用-非衍生-保持署名 | BY-NC-SA
  • 文章作者:「whg」
  • 发表日期:2015年12月15日