如何给你的函数变量命名
最近在项目中做了几次代码review,发现代码中经常出现变量函数命名不是很完美的情况。有些变量名字,稍为一看,可以很容易看出它要表达的意思,但一样可以取一个更贴切的名字;而有一些名字,就显得特别别扭了。
本文不讨论命名风格(匈牙利风格,还是Linux风格),仅从变量表达的意思上,应该选取什么样的英文词汇进行表达。由于我一直从事Linux开发,因此本文的命名风格是Linux编程风格。但这不妨碍表达如何给变量命名的原则。
原则1:尽量少用泛指词汇,如flag,tmp等,应该使用特指词汇
在初学者眼中,flag是个很常用的命名词汇,它用来表示一个志标。它的值通常是0或1,表示是否已打上标记了。其实打上标记的原因是多种多样的,是由于在链表中查找到指定的结点了,还是某个功能已使能了等。0/1可以任何具有两种状态所有逻辑的抽象,使用flag对这些状态命名都可以行得通,但它的意义过于空泛。在不同的情况下,换成具体状态的词汇可读性更高,如found, successed, created等。
tmp有临时之意,表示该变量是临时了,最终会被遗弃。
在实际的编程过程中,tmp的用法有两个:1.用于存放一次性的临时值;2. 保存中间计算结果,并用于下一环节。可以归纳为:tmp保存中间状态的数据。根椐实际场景,应将tmp转化成可读性更高的词汇。
如果表示红黑树查找,目前找到比key大,更接近的节点,可以使用bigger来代替tmp
如果在链表中删除某个key的节点,需要维前一个节点,可以使用prev来代替tmp
如果在一列表的数据计算过程中的中间结果,应根据算法的约定,根据中间结果的命名,给它一个适合的名字,如expr, binary等
原则2:多重嵌套少用i,j,k变量,多用指示词汇
I,j,k是一种无意义的变量命名方式,它主要出现在for循环变量命名里。如果是多重for循环,应尽量避免少用I,j,k这样的循环变量,很容易搞错,造成死循环,或者循环跳位。
否则,很容易出现类似下面这样的笔误:
for (i = 0; i < NUM; ++i ) {
for (j = i + 1; j < NUM; ++i) {
}
}
应该使用有意义的词汇来代替,如果遍历系统中所有cpu的上的内存分区,可以考虑使用下面的循环变量:
For (cpu = 0; cpu < MAX_CPUS; ++cpu) {
for (bank = 0; bank < banks[cpu]; bank++) {
}
}
原则3:使用业界约定俗成的对仗词汇
开源代码,或者标准的库函数(方法)的命令是我们学习的最好例子。
C++容器的一对方法:begin()和end()
Linux的系统调用: send和recv
List中的两个数据成员:prev和next
如果代码出现自己蹩脚命名方法,可读性会变差,甚致造成曲解。
原则4:一些词汇必须成对出现,来表达一个概念
1. 表示一个地址空间,需要start/end,或者addr/size共同表示
这个想法特突在一次代码review过程中路出来,目前案例很少,容以后增加。
原则5:一组功能相似的对象,命名风格应保持一致
假设你使用状态机对你的程序进行建模,所有的状态事件函数命名应该采用统一的风格,如:
check_state_change()
perform_state_change()
又如Linux内核ext3文件系统的回调函数,均采用统一个命名风络,如:
static const struct address_space_operations ext3_ordered_aops = {
.readpage = ext3_readpage,
.readpages = ext3_readpages,
.writepage = ext3_ordered_writepage,
.sync_page = block_sync_page,
.write_begin = ext3_write_begin,
.write_end = ext3_ordered_write_end,
.bmap = ext3_bmap,
.invalidatepage = ext3_invalidatepage,
.releasepage = ext3_releasepage,
.direct_IO = ext3_direct_IO,
.migratepage = buffer_migrate_page,
.is_partially_uptodate = block_is_partially_uptodate,
.error_remove_page = generic_error_remove_page,
};
原则6:如果想到不简单的名字给函数命名,请重新考虑函数的功能
在实际的编程实践中,有时写完一个函数的功能,想找不到适合的名字为之命名。其实原因很可能是因为函数的职责不单一,所以很难给它取一个好的名字。通常需要对函数进行拆分,让它保持只做一件事情,名字就随手可得了。
小结:
1. 上面仅仅是列了平时思考到的一些原则,其实这些甚至称不上是原则,只是一些想法而已。
2. 在进行代码review时,有更多系统性的思考,但这些想法有时在大脑一闪而过,没有形成笔录。后面有更多的想法,再和大家分享,欢迎大家给更好的建议。
欢迎指正,多讨论,谢谢!