自表达的代码(命名篇)
你一定读过很多糟糕的代码,包括但不限于:
- 鼠标滚轮测试程序(方法太长)
- 脑筋急转弯程序(逻辑判定复杂)
- 记忆力测验程序(一大堆常量)
- 眼神测验程序(类似的变量名)
- 逻辑思维测验程序(循环引用式的包含关系)
读这些代码是痛苦的(指不停的翻代码,画流程图),写这些代码也是痛苦的(写着写着就想推翻重写)。
那么怎么有效降低这种痛苦呢?写出一目了然,简洁明了,不言自明的代码就好了,这就是这篇文章介绍的 自表达代码
WHY
写注释写文档自然是一种不错的解决办法,但是最近跑论文代码的 Epi 发现了一个事实:跟着 README 一步一步配置环境有 95% 的可能性会在某一布因为莫名其妙的错误崩掉。
注释,文档,README 都会骗人,只有代码不会骗人。
因为只有代码是最新的最有时效的,一旦代码更新后没有及时更新文档和注释,结果就是灾难的。更何况文档可没有 debug 功能,读的时候甚至会觉得很对。
所以说:文档也要写,代码也要干净,这样才叫健全。
WHAT
想一想:如果要建立一个班级 Grade
类,那么获取学生数量的方法怎么命名才算合适呢?
1 | getStudentsCount(); |
看起来好像都不错,不过仔细分析的话 ——
1 | grade.getStudentsCount(); // get 是多余的 |
对比之下 studentCount()
的命名最直观易懂。
阅读下面的两段代码:
1 | switch (keyCode) { |
1 | bool onKeyDown(int keyCode, const KeyEvent& event) { |
虽然第一种代码有很完整的注释,但是似乎还是第二种代码更好读一点,这就是自表达代码的优秀之处。
HOW
首先能做到的就是命名的改进了。
命名的基础原则:
- 不仅要考虑声明和定义的情况,还要考虑代码被调用的情况
- 尽量使用合适易懂无歧义的英文名命名,辅以数字和下划线
- 比如
EISU_KANA
(英数かな) 就不如ALPHABET_NUMBER_KANA
- 比如
fasten
就不如accelerate
,reSearch
就不如searchAgain
- 比如
- 虽然有代码补全,但是名称长度不要过长
- 不要采用无意义的变量名(循环变量除外)
- 无意义的变量名:
a,b,c,tmp,retVal
等
- 无意义的变量名:
- 单词间要有合适的分割
- 如
fireWall
,created_person
- 如
- 除常量外,大小写混合拼写
- 即使是 FTP 这样的缩写也要写成
Ftp
- 即使是 FTP 这样的缩写也要写成
- 命名和行为要一致
接口的命名原则:
- 不要用
I
开头 - 以
able
结尾表示具备某种能力,但并不是所有的接口都能以able
结尾。
类的命名
- 基类不用
Base
开头或结尾,这并没有意义,使用更有意义的Model, View, Control
等 - 子类的命名最好与父类建立起某种推测关系
- 抽象类可以增加
Abstract
开头,但是如果类本身就够抽象就不用加 - 兄弟类要有明显的区别词语
方法的命名
- 动名型:动词是方法的灵魂要选的合适,把条件移到参数中会让代码更具有扩展性。
- 比如
filterStudents(subject)
就比listMathStudents(),listGeoStudents()
要合适。
- 比如
- 与返回值的联系:
- 返回值是列表就尽量用复数名词
- 返回值是真假就用
is,has
等词开头 - 如果返回值不确定,就用
Object
或者其父类名称 - 如果是 Getter,就使用 get 的对象作为名词
- 考虑被调用时的样子
- 执行类动词的使用:
do,process,execute,run
等名词很抽象,最好选用其他的词来代替。除非这是一个抽象类的实现方法,之后会被子类实现。- 比如
doLogin
就是authenticate
,doRegister
就是createUser
- 比如
- 适当使用介词会提高可读性
- 不要加下划线
- 不要夹带无意义的临时字符
- 比如不要因为域变量名称为
mAbortKey
就把方法命名成getMAbortKey
- 比如不要因为域变量名称为
变量的命名
- 域变量:可以适当加前缀但是不要无脑加
- 比如
pos.x, pos.y
很清楚,写成pos.mX, pos.mY
就有点如鲠在喉的感觉。
- 比如
- 参数变量:避免与域变量相同造成混淆
- 循环变量:下标循环用
ijk
,forEach
循环采用元素内容命名。 - 局部变量:不要使用
temp
,tmp
,result
,list
,map
等意义不明的词,采用其真实意思命名。
常量的命名
- 全大写命名,多单词采用下划线分割
- 不要序号式命名,要利用开头词进行分组
- 比如
LAYER_ROMAJI, LAYER_HIRAGANA,LAYER_KANJI
显然比LAYER_0, LAYER_1, LAYER_2
更好
- 比如
相似的命名
- 类和内容的重复:包装的容器和包装的内容重名,寻找合适的集合名词。
- 比如
Questionaire
比Questions
更好
- 比如
- 整体和部分:只有量的差异导致的重名,可以通过前缀
matched,grouped
区分。 - 类型转换:可以通过连续的调用略去中间变量,如
list.ketSet().iterator()
ok 暂时就说到这,这个话题还有不少东西可以说,比如注释的风格,代码风格,代码结构,设计模式,测试代码,甚至英语能力。之后可能会继续更新(挖坑)~
先生、人生相談です。
今天放的歌是这个:
ヒッチコック
「胸が痛んでも嘘がつけるのは何でなんでしょうか。
「即使心中很痛也要撒谎是为什么呢。
悪い人ばかりが得をしてるのは何でなんでしょうか。
总是坏人得到好处是为什么呢。
幸せの文字が¥を含むのは何でなんでしょうか。
幸福的文字中包含¥是为什么呢。
一つ線を抜けば辛さになるのはわざとなんでしょうか。」
去掉一条线就会变成辛苦是故意的吗。」
青春って値札が背中に貼られていて
后背被贴上了名为青春的标签
ヒッチコックみたいなサスペンスをどこか期待していた
内心某处期待着希区柯克般的悬疑
「先生、どうでもいいんですよ。
「老师,怎样都可以了啊。
生きてるだけで痛いんですよ。
只是活着就很痛苦了啊。
ニーチェもフロイトもこの穴の埋め方は書かないんだ。
尼采和弗洛伊德都没有写填住这个洞口的方法啊。
ただ夏の匂いに目を瞑って、
只是在夏天的味道里闭上双眼、
雲の高さを指で描こう。
用手指描绘云的高度。
想い出だけが見たいのは我儘ですか。」
只想看着回忆是一种任性吗。」
感谢你的阅读~