APP下载

浅析代码风格*

2013-07-31赵君喆钟良骥卢社阶戴文华

湖北科技学院学报 2013年4期
关键词:阅读者命名语句

赵君喆,钟良骥,卢社阶,闻 彬,戴文华

(湖北科技学院 计算机科学与技术学院,湖北 咸宁 437100)

代码是程序员思维的体现,开发者如何通过代码向维护者传递自己的思路和想法?这需要开发者尽可能地写出让大多数程序员都容易理解的代码,也就是可读性强的代码。代码的可读性包括清晰的思路,流畅的逻辑以及规范的风格。采用公认的设计模式、流行的算法、常见的功能实现套路,避免“聪明”、“微妙”的技巧,都有助于体现代码逻辑和思路,这些方面研究者甚多,本文不作深入讨论。

代码阅读者对一个程序最直观的感受是该程序的代码风格(Coding Style)。代码1是一段C语言程序,有过网络编程经验的开发者大概可以看出这是一个解析并处理网络层数据包的函数。但是对一个没有网络编程经验的开发者来说,这段代码让人感到惊慌。变量pp表示什么?常数14表示什么?没有注释,格式混乱,整段代码无法理解。

相比代码1,具有相同功能的代码2则非常容易理解。从软件工程学的角度出发,任何代码应该可以让任何专业人员来维护。因此,遵循良好的代码风格,是软件高效开发和维护的基础。什么才是良好的代码风格?行业并没有严格的标准,但是大多数的软件维护人员都希望开发人员能注意下面几点。

一、规范地命名

变量、函数、类、源文件的名字会给代码阅读者带来很多信息,包括正面的和负面的。良好的命名习惯,可以大大减少代码维护者的阅读开销。规范地命名一般遵循以下原则:

1.为变量、函数、类和文件起一个有含义的名字。一个有具体含义的名字往往可以告诉人们这个对象是什么、起什么作用。

表1 命名对比

3.用词性和大小写来区分命名对象的种类。代码的含义尽可能符合现实世界,所以名字的词性也尽量符合命名对象的自然属性。例如一般变量和类的名字采用名词,函数的名字采用动词。比如,class Duck{}、Duck greenDuck、greenDuck.Fly()。如例所示,有些名字是由几个单词组成,所以在名字中有的字母大写,是为了界定单词。有些程序员习惯将自定义的类名和函数名的首字母大写,而变量的首字母小写。其主要目的是为了将自定义的类及函数与系统和库的类型及函数区分开。

4.名字携带更多信息。行内有些命名习惯让名字携带更多的信息,如著名的“匈牙利命名法”。该命名法则在变量前面带上类型或属性信息,比如float型变量就以f为名字的开头,指针变量就以为p为名字的开头,成员变量以m_开头,全局变量以 g_开头等等。如:fRate、pWinHandle、m_color、g_nameMap等都是遵循匈牙利命名法的名字。

二、降低代码噪声

代码反映出程序员的思维流,当代码的维护者顺着代码的逻辑行云流水般地阅读下来,他会觉得这段代码就像一篇文章。事实上,有些代码中存在着不少噪声,这些噪声往往会干扰甚至阻断代码阅读者的思维。这些噪声包括以下因素:

1.奇异数(Magic Number)。有些代码中会出现突如其来的数字,这些数字又不带任何字面的意思,所以当代码维护者读到这里的时候,往往会费尽心思来弄清楚这些数字代表着什么。代码1中的14、6、17等数字就是奇异数,当它们被替换成代码3中的ETHER_HEAD_LEN、PROTOCOL_TCP、PROTOCOL_UDP后,代码的可读性大大增强。所以定义有意义的宏常量是避免奇异数的好办法。

2.多函数出口(Multiple Return)。函数作为一个功能性模块体现出逻辑的封装性,既然函数只有一个入口,那么最好只有一个出口。否则的话,代码阅读者还要额外考虑函数异常返回时的上下文安全情况,例如多个出口的函数在资源管理上就颇有不便:

在代码3中,错误情况发生时忘记释放资源就返回了,导致内存泄露。不过也可以在每个return前都写上一段释放资源的代码避免内存泄露,但如果return过多,代码不可避免的冗长重复,同样降低了可读性。因此可以修改为代码4的形式,将函数设置唯一的出口,资源统一在出口前释放,这样的逻辑更加合理。

3.无条件跳转。多年来大量的C开者证实,频繁使用goto等一些无条件跳转语句会导致程序逻辑混乱,很难维护。所以在软件开发中,应该尽量避免goto、setjmp、longjmp等跳转语句。

2)理论与实践相结合,紧跟当前软件技术发展的前沿,熟悉当前软件项目开发流程和开发工具,强化编程能力,培养学生具有扎实的基础理论知识和较强的工程项目应用能力、培养良好的职业素养和创新能力作为人才培养目标的重心,紧跟并培养以大数据为核心,移动互联网等新一代信息技术产业所需的高级应用型软件人才。

4.复杂的逻辑表达式。计算机解析处理大量的“与”、“或”、“非”等逻辑关系很容易,但人脑理解却很难。例如,代码5中的if条件理解起来需要花费很大的代价,但如果将逻辑表达式切分成多个if来处理,如代码6,虽然代码量略增,但可读性更强。

三、合理的代码格式

众所周知,只要语法正确,再凌乱的格式也丝毫不妨碍编译器对代码的理解。但人却不同,混乱不堪的格式总是让代码的阅读者不知所措。井井有条的代码格式不仅让人看上去赏心悦目,更能节省代码的阅读时间。讲究代码格式实际上就是优化代码的排版,程序开发者在长年累月的工作中积累了一些国际认可的代码排版经验。

1.缩进。子模块通过缩进一个单位来体现代码的逻辑层次,这个单位一般是4个空格。有些开发者习惯用tab缩进,但是不同的编辑器显示tab的缩进大小不一定相同,层次结构分明的代码在另一个编辑器里可能显示的很混乱。所以一般建议在编辑器中设置:将tab替换成4个空格。

2.花括号。花括号的格式只有两种习惯,各有优劣,但同一个工程中应该保持一致性。

3.对齐。每个程序块的代码都应该对齐,这样能更清晰地体现出程序块之间的逻辑层次。还有一些常见的对齐习惯,比如变量声明定义对齐、参数对齐等,目的都是为了让代码看起来更清晰。

4.嵌套。大规模的嵌套条件语句会让程序呈现阶梯状缩进形式,如代码4里if语句嵌套if语句。这样的代码虽然有规范地缩进和对齐,但如果if语句很长,阅读者将很难匹配花括号。所以这种情况可将代码4改成代码8。

四、有效的注释

代码注释是代码作者为代码读者提供的辅助信息,这些信息包括对功能的描述、对逻辑的解释以及对易混淆处的提醒等等。

没有注释的代码,即便是代码作者,一个月后去阅读,也会有很大的理解障碍。虽然书写注释是件乏味而麻烦的事情,但是对于代码的维护者来说,好的注释可以大幅提高代码的阅读速度。但是不合时宜或表达不清的注释不但不能帮助代码维护者阅读代码,有时还会干扰或误导代码的读者。

书写注释一般应参考以下几点:

1.注释用语。好的注释应当言简意赅,条理清晰,不应将简单的问题复杂化,亦不可将复杂的问题简单化。此外,如果考虑产品市场的扩展性,注释语言可以采用英语。

2.文件注释。比较规范的文件注释包括:工程信息、版权信息、版权许可信息、工程名、文件描述、作者、版本和修改历史等。

3.类注释。格式类似于文件注释,但是注释内容仅需包括:类名、类功能描述、类接口及使用说明。

4.函数注释。格式类似于类注释,内容包括 :函数名、函数功能、参数说明、返回值说明。

5.变量注释。类的数据成员以及全局变量最好注明其含义和用途,这样的注释一般采用行注释方式放在变量的上一行。

6.实现注释。在代码中一些机巧、晦涩、有趣、重要的地方应该加上实现注释。如果是对程序块注释,一般采用行注释块注释放在程序块的上面;如果是对某语句注释,一般采用行注释紧邻语句末尾。

7.提醒注释。有时候程序员写的一些看上去“不正常”的代码,需要提醒阅读者这是有意为之。比如:未实现的功能需要注释“TODO”,switch的case中有意不用break时需要注释“Flow Down”。

五、结 语

归根结底,无论采用什么样的代码风格,最重要的一点是要保持风格的一致性。一个工程,从开头使用了一种风格,那么后面的所有代码就应该延续之前的风格。遵循软件工程学的思想,应参照以下几个原则来保持代码风格的一致性:

1.软件开发商制订内部统一的代码风格框架,并对所有开发者进行代码规范化培训,从而保证企业内部代码的易维护性。

2.项目启动时制订项目代码风格细则,严格约束参与相同项目成员的代码风格,以此保证项目整体的代码风格一致性。

3.维护项目时,以被维护项目的代码风格为标准,保证被维护项目的代码风格的持续性。

猜你喜欢

阅读者命名语句
阅读者的春天
命名——助力有机化学的学习
“青春阅读者”——教师读书会纪实
重点:语句衔接
为什么有些人能成为终身阅读者
阅读者
有一种男人以“暖”命名
为一条河命名——在白河源
如何搞定语句衔接题
河鲀命名小考