[toc]
概 述
这本书是很多人推荐的,我看完的真实感觉是,没有太多立竿见影的效果。可能等我写了几年代码,做了很多项目再从头来看,会有更多的体会。
总体来看,这本书最关心的两个字就是——理解。
好代码,就是简洁的,容易被读者理解的代码。当然这个读者也有可能是几个月后的作者。
第一部分主要介绍了两点:1. 如何用 更好的名字自注释 2. 如何写注释
友情提示:有一些常识和自觉使用的技巧,这里就不放进来了。有可能会直接忽略一整章。
参考文献:The Art of Readable Code by Dustin Boswell, and Trevor Foucher.
第二章 把信息装到名字里
使用更专业,更有表现力的词(效果欠佳)
笔者指出get这样的词太宽泛了,可以尝试更精确的,比如Fectch或者Download等等。
类似的,Size可以替换成具体的信息,比如Height或者MemoryBytes。
相同的,stop可以换成Pause和Resume的配合。
这里还提供了一个表格:
单词 | 更多选择 |
---|---|
send | deliver, dispatch, announce, distribute, route |
find | search, extract, locate, recover |
start | launch, create, begin, open |
start | create, set up, build, generate, compose, add, new |
个人评价,这个东西就纯看英语使用水平。如果能使用更合适的词当然更好。
但问题也很明显,我们工作是在国内,并不是一个项目的所有同事都能把英语单词掌握的这么精确,起码我不行,我觉得我英语学的还凑活了,但是你让我想send的代替词,我照样想不出来上表的这些东西。
如果你写一套我写一套,那很容易产生不同的风格。为了风格一致性,大家最后又会回到set,get,start,stop,因为这个东西反而理解起来成本最低,实在不行来两条注释就行了。
避免使用temp和retval 空泛的词(有用)
如果只是为了实现swap这种功能,temp完全可以胜任。不过如果是稍微复杂的函数,如果出现了temp,会让读者看了有点蒙圈,可能要思考几秒钟这个temp代表了啥,所以应该用更精确的名字来代替。
多重循环迭代索引,使用更贴切的名字 (值得推广)
大家刷Leetcode题的时候估计都有过这种体会,因为i, j, k这种不明确的循环索引把自己绕晕了,结果在循环中写错了i j k 的位置,这样的错误往往需要debug一会才能找出来,如果一开始就使用非常明确的索引,那正确率会大大增加。
名字加入更多信息 & 带单位的值 & 附加其他属性(有用)
顾名思义,比如一个变量是十六进制的而且很重要,那么可以命名为hexId
。
如果变量带单位,比如字节,分钟,秒,最好加上单位。
如果变量安全或者不安全,可以加上safe,unsafe
小作用域使用短名字 & 首字母缩写(效果不佳)
第一点,我认为每个人潜意识都是这样做的,小函数的名字就是很简短,所以不用强调。
笔者建议,首字母是否缩写取决于新员工能否看懂缩写。这是一句废话。因为实际上业务变化很大的,刚来做新业务的员工肯定看不懂,都得看文档或者和老员工请教,而且我认为代码整洁性很重要,不能因为照顾新员工就把缩写给写全了,那样有的函数或者变量会极长。
第三章 不会误解的名字
使用begin和end来表示包含、排除范围(未知)
end这个词有二义性,我读到这本书的end部分了,这里面end是包含,但有些时候end是排除的。遗憾的是,英语里面没有一个合适的词来表示“刚好超过一个值”。个人感觉这个要统一,用end的话就要先说明,到底是包含还是排除。
与使用者的期望相匹配 (值得推广)
很多程序员都适应了 get()这种 轻量级访问器 ,但是如果一个消耗很大资源的访问函数,也被命名为get,并且没有注释,那么会给读者一种可以随意调用的印象,这样可能在后面的开发种引发重大问题。
所以要么使用更严肃的词,要么使用注释介绍这个函数需要的资源或者复杂度。
第五章 该写什么样的注释
注释的思想,是帮助读者了解的和作者的一样多。
这里我就不说什么注释要适当的废话了,不该加的我不会在这里写。我写的都是觉得应该加的。
加入导演评论 (极其推荐)
你应该在代码中加入注释,来记录你对代码独特的价值见解。
比如:
//出乎意料,对于这些数据用二叉树比用哈希表快40%。
//哈希运算的代价比 左/右树大得多
这类注释教会了读者一些事情,并且防止他们做无谓的优化。
//作为整体可能丢掉几个词,这没有问题,100%解决太难了
没有这个注释,读者可能以为这是个bug,然后浪费时间尝试找到它失败的测试用例。
//这个类越来越乱,我们应该要考虑建立一个新类来重构
这句话像ToDo一样,鼓励下一个人改正,并且给出具体建议。
写代码的时候,作为作者肯定会有各种各样的发现和独特的理解。我认为如果每个作者都能把自己的小心思写在注释上面,那么就能帮助后来者快速的理解思想,或者是找到改进方法。至少能鼓励我自己,以后觉得哪里写的不好,需要改进,就大大方方写出来,前人栽树后人乘凉嘛。
总体上来说,好多代码的作者在这方面还是有些欠缺,一个概念或者思想要后来者自己去思索,造成了资源的浪费。
给常量加注释 (有用)
NUM_THREADS = 8
这一行看起来不需要注释,但很可能选择用这个值的程序员知道的比这个要多。
NUM_THREADS = 8 // as long as it's >= 2 * num_processors, that's good enough
现在,读代码的人就有了调整这个值的指南,(比如,设置成1就太低了,设置成50又太夸张了)
有时常量的值并不重要,有的常量的值却是高度精细调整过的值,不宜大幅改动,这些都可以注释出来。
我自己看代码的时候经常,会迷糊于各种常量的值为什么用xx值,如果能有这样的注释会好的多。
站在读者的角度 (值得推广)
我自己在看代码的时候,经常会有这样的疑问:“为啥这个地方要这么写?用XX函数或者变量不行么?”
如果作者在写代码的时候,使用了某些奇技淫巧,那么真的希望能够用注释的方式写出来,不然后面的读者真的会很懵逼,都在想,ta为啥不用简单的办法做?是ta太厉害了,还是写的有问题?
所以当我们自己在写代码的时候,就要想到,读者读到这个地方的时候会不会有疑问,用户会不会误用我的代码?如果是,那么请加上注释。
克服“作者心理阻滞”(值得推广)
说到底,很多程序员不喜欢写代码是因为这个东西没有绩效,因为领导关注的是绩效,是交付,只要功能正常实现且稳定运行,那就万事大吉了,谁管后面的人能不能看懂。
这个东西没办法要求别人,只能从自己做起,直接把内心的想法写下来就行了,先动笔写,再去把你心里想的句子做一个同义句转换。
比如你的内心描写:“wtf,这个东西这个地方有问题啊。”
然后再提炼具体的问题,你说不定能改成:“如果这个函数处理xx问题,那么会运行的非常慢”。
只要开始动笔,就会发现这东西其实不难,而且越写越熟练,还能锻炼咱们的总结能力。至少把自己写的东西解释清楚点,可以不用在某月某年后,被新员工顺着工号夺命call你,哈哈哈哈。
第六章 写出言简意赅的注释
避免使用不明确的代词 & 精确描述函数行为(有用)
不明确代词,就是少用 “它”。
函数行为,比如有个函数统计文件中的行数,// return the number of lines in this file
问题来了,行数具体是啥,这个概念有点模糊,所以可以改成 : 统计 \n 的个数,这样子就很精确。
用输入、输出例子来说明特别的情况(值得推广)
简单的讲就是,使用一个example来描述这个函数的功能,比如我输入进去是什么,输出后得到啥,这就是举个栗子。