by 崔向阳
参考: 《The practice of programming》-Brian W.Kernighan,Rob Pike
还记得大一刚学C++时老师说,一定要养成良好的编程习惯,做好注释,注意程序的可读性。于是我把要上交的程序排好缩进,不管什么函数,变量都详详细细的写好是干什么用的,再把注释缩排的好看一些。至于自己练手的程序么?当然是不写注释的。这种知其然不知所以然的状态维持了很长一段时间。后来变量的命名方法,程序块的缩进和对齐,各种程序上的习惯写法,注释的写法……各种体会随着时间慢慢增长,但是一直到实际做项目的时候,才更加重视到保持良好的代码风格的重要性,这已经不只是个美观问题,好的代码更不容易出错更加健壮,更容易维护,等等好处不再一一列举。
The practice of programming这本书很好的介绍了写代码各方面各种有益的经验,我在这里只简单列举一下其中一些要点,偶尔添加些自己的看法。另外Google发出了一个不错的C++编码规范,可以作为借鉴参考。
命名规范
- 全局变量使用稍长一些,可以描述清楚变量的名字;局部变量使用较短的名字就好。因为全局变量可能在不同的地方出现,有必要用一个长些的名字来提醒它是做什么用的。局部变量则使用较短的和习惯性常用的名字就已足够,读者也较容易根据上下文判断它的意思。比如如下这个例子:
for (theElementIndex = 0; theElementIndex < number0fElements;theElementIndex++)
elementArray[theElementIndex] = theElementIndex;
和
for (i = 0; i < nelems; i++)
elem[i] = i ;
孰优孰劣一眼就看出来了。
一致性。有一些常用的命名方法,如常量所有字母大写,类和结构体的首字母大写,变量首字母小写。还有骆驼命名法(userName)和用下划线分隔的命名法(user_name)。使用哪种方法可以根据自己的爱好,重要的是在程序里始终坚持一定的习惯,保持一致性。另外相关联的对象或变量的名字要体现他们的关系和区别。
使用有意义的名字,如:#define ONE 1 和 #define INPUT-MODE 1 的区别。
函数名应明确的指出所做的事情,与代码一致,并能一定程度上体现返回值,如: if( is_octal(c) )… 和 if( check_octal(c) )… 相比,更清晰的指出了返回值的类型。
关于中文拼音缩写。在项目中碰到过很多命名是中文拼音缩写,我的观点是可以适当的用。比如业务支撑,使用bs并不能很好的表达意思,business_support在有些地方则过长了,直接使用yz,反而可以让项目相关的人更能明白意思,只要在项目中保持命名一致就好了;但是也看到过些误用的例子,比如听说过有人起的变量名是 zifuchuan 的,也确实是能让风云为之变色了,改为str稍好,但是参照上面的规范,起个有意义的名比如user_name之类的,则更加好了。
表达式和语句
有意识的显示出结构。如:
for(i=0;i ;
和
for(i=0;i
;
的区别。
使用自然的表达方式。如:(! (block-id < actblks) ) 和 (block-id >= actblks) 相比,后者就顺畅多了。
在可能引起歧义的表达式处尽量使用括号,消除歧义。如: if (x&MASK == BITS) 和 if (x& (MASK == BITS) )。
使用简单的表达式。尽量避免使用复杂的表达式,而用多个简单表达式代替。
使代码清晰,不卖弄技巧。如:subkey = subkey >> ( bitoff - ( ( bitoff>>3) << 3)); 和 subkey >>= bitoff & 0x7; 。
一些表达式经常有副作用,需要引起注意。如: array[i++] = i; 在不同的编译环境下可能会有不同的结果。
一致性和习惯用法
使用一致的缩排方式,和一致的花括号使用习惯。缩排方式没什么好说的。花括号有些时候可用可不用,比如if块里只有一行语句的情况,这些地方要保持一致性。
使用约定俗成的习惯用法。例如,应该写成
for(i=0;i
…….
而不是
for(i=0;i
i++;
尽量避免使用宏。
程序中的数字
使用有意义的名字和表达式来代替直接使用数字。例如:
fac = lim / 20; /* set scale factor */
if (fac < 1)
fac = 1; /* generate histogram */
for (i = 0; i < 26; i++) {
………
和
enum{
HEIGHT = 20; /* height of bars */
NLET = 26; /* size of alphabet */
};
fac = lim / HEIGHT; /* set scale factor */
if (fac < 1)
fac = 1; /* generate histogram */
for (i = 0; i < NLET; i++){
以前有段时间和第一段程序一样,程序里的数字很杂乱,自己写完了回头过来看的时候都很头疼,尤其有些参数需要改动的时候,需要一处一处的去改,不但麻烦,而且容易忙中出错。
使用常量来命名数字,而不是宏。
注释
不要过度注释。注释是为了帮助阅读程序,过度注释会使重要的注释信息被淹没。注释应该说明不能直接从程序中看出来的信息。
对函数,全局变量,常量进行注释。
发现代码不合适的时候,改写它,而不是只进行注释。另外改写的时候要注意代码风格与原作者保持一致。
注释要保持和代码的一致性。修改代码以后要及时对注释进行更新。
用简洁的语言注释。当注释不得不冗长啰嗦时,通常是代码写的不好。