Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8608639
  • 博文数量: 1413
  • 博客积分: 11128
  • 博客等级: 上将
  • 技术积分: 14685
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-13 10:03
个人简介

follow my heart...

文章分类

全部博文(1413)

文章存档

2013年(1)

2012年(5)

2011年(45)

2010年(176)

2009年(148)

2008年(190)

2007年(293)

2006年(555)

分类: C/C++

2006-08-10 12:57:07

编码标准定义了代码的外观应该是什么样子的。对于大多数项目来说,编码标准能够发挥很大的作用,对于某些项目,这甚至是必须的。这一点对于开发代码项目来说更是重要。

关于本文
本文的主要目的是展示编码标准对一个开发项目有怎样的完善作用。我们使用eZ系统()的C++编码标准作为一个编码标准的例子,但是本文所阐述的概念同样适用于其它程序设计语言。我们在PHP开发中同样使用这个标准。

编码标准是什么?
一个编码标准是这样的一个准则集合,它描述了你的代码应该是什么样子的,你需要使用哪些程序设计语言的特性和如何使用这些特性,以及应该使用哪些工具编写代码。当然,你可以按照自己的意愿定义编码标准。

它的好处是什么?
人与人是不同的。我们有不同的爱好,穿不同的衣服,在编写代码时使用不同的编码风格。如果我们仅仅为自己写一些小的程序或脚本的话,一切都没问题。但当许多人合作完成一个项目时,不同的编码风格会使成员之间产生分歧,使代码的可读性变差。这些都妨碍了合作效能,影响了项目的效益。一个简单但普遍存在的分歧的例子就是缩排问题。应该使用多大的缩进量?在哪缩进?应该使用空格还是tab?很可能每个程序员对此都有自己的一套看法,并且每个人都认为自己是正确的。(在C++中,正确的缩进应该是4个空格的宽度,不使用tab——如果你关心的话。另外,别忘了把每个大括号放在单独的行中,否则你会至少7年无法从麻烦中抽身。)这个问题在开放代码的工程中尤为突出,因为可能会有几百名来自世界各地的程序员参与软件的开发,但对于某个企业内部的小项目,这也是不可忽视的。即使是仅仅为自己写一个小程序,你也迟早会陷入困境无法自拔,除非你总是使用相似的编码标准。

标准的自然性
你个人的程序设计风格本身也是一种编码标准。你总不会随便使用大小写字母定义常量,你也应该不会混用几种不同风格的while循环,你更不会使用不同的缩排格式(至少我希望你不至于此)。标准是很自然的。不幸的是,由此引发争论也是很自然的事情。记住,当你加入一个开放代码工程组时,最好还是遵守工程组的标准。如果你试图将你的那一套标准强加于人,那你就会失去尽早完成编码工作的机会。如果你将开始一个新的工程,那么你最大的优势就是可以按照自己的习惯编写代码。

我们的例子
我不会过多的讲述这个标准多么伟大(当然它很可能是最好的标准,不过,就像我所说的,我不会过多的讲述它),而是着重于如何从根本上形成标准。几乎所有的标准都强于没有标准。而且,这虽然是一个C++的例子,但其中的原理和概念适用于所有——或者说大部分程序设计语言。

文件
所有的文件名都小写。头文件以“.hpp”为后缀,实现文件以“.cpp”为后缀。文件名全部使用小写字母的好处对于那些大小写敏感的操作系统如Linux来说是很明显的。而使用“.hpp”后缀使我们可以区别C和C++的头文件。
每一对cpp/hpp文件只包含一个类,除非我们使用私有的类。如果一个头文件包含一部分不会被外部引用的常量和声明,同时也包含一部分需要被外部引用的声明,那么最好将这个文件分成几部分,这样可以简化文件之间的依赖关系。
如果一个实现文件在各个平台上的实现不同,那么最好将这个文件分为两部分,一个文件包含与平台无关的实现代码,另一个包含平台相关的实现代码(每个平台都有一个这样的文件)。
在下一节,我们将要讨论宏、缩进和大括号的问题。


第二章 基本约定

编码标准定义了代码的外观应该是什么样子的。对于大多数项目来说,编码标准能够发挥很大的作用,对于某些项目,这甚至是必须的。这一点对于开发代码项目来说更是重要。在这一章中,我将讲述eZ系统编码标准中对宏、缩进和大括号的规定。


除了#include和头文件中必须的#ifndef/#define/#endif组合,除非有很好的理由,其它宏和#命令应尽量不予使用。

缩进
使用四个字符宽度的缩进,这样可以很容易的识别缩进级别。使用空格替代TAB,这样可以保证代码在所有的编辑器上都是一样的。

大括号
将前大括号和后大括号和“拥有”这对大括号的语句放在同一列中。
例如:
int meaning( int x, int y )
{
    if ( x == y )
    {
        ..
    }
    else if ( x > y )
    {
        ..
    }
    else
    {
        ..
    }
    return 42;
}

小括号、大括号和逗号
在每个逗号后加入一个空格。在前小括号后和后小括号前各加入一个空格。但在方括号中不要加入空格。在类型名后加入并且仅加入一个空格。让指针符号*和引用符号&紧邻其相关的变量。
将逻辑上相关的变量和代码以空行分成组。以这种方式成组的变量首列要对齐。空行必须是真正的空行,不能包含空格或TAB。
如果你对某个表达式的运算优先级不太清楚,使用小括号。当你能够清楚的解释优先级时,去掉不必要的小括号。

if语句和while循环
嵌套if语句必须使用大括号{}。如果你有许多连续的if和else if语句,考虑使用case语句取代之,或者使用一个面向对象的方法重新设计。
if语句和while循环只计算布尔表达式,不要在其中赋值或改变数据。

本文的下一章有一点长,也更复杂些,我将会进一步讨论关于命名规则、函数、类和名字空间等主题。


第三章 更多内容

在本文的第三章(也是最后一章)中,我们将探索命名规则、函数、名字空间、类、注释和异常等内容。

命名规则
所有名字必须使用英语,而且必须保证语法的正确。避免使用那些毫无意义的名字,如foo和tmp。名字中的所有数字必须使用英文,而不是数字,除非有很好的理由。
例如:ValueOne(而不是Value1——译注)
函数名可以由多个单词组成,每个单词的首字母大写,其它字母小写。第一个单词必须全为小写。尽量不要采用首字母缩写方式。
例如:
void setText( const QString &text );

常量全部使用大写,单词之间使用下划线分隔。
例如:const float PI = 3.1415;
      const int MAGIC_NUMBER = 42;
枚举项和成员变量名可以由多个单词组成,每个单词的首字母大写,其它字母小写。通常它们的长度不应超过三个单词。如果含义清楚,可以使用首字母缩写形式。
enum DayType
    {
    Monday,
    Tuesday,
    ...
    };

private:
    int Len;
    int X,Y;
局部变量名可以由多个单词构成,所有字母都使用小写。用下划线来分隔单词。包含尽可能少的单词,需要时使用首字母缩写形式。允许使用特殊的首字母缩写如i(index)和x、y(位置)。形参采用和局部变量相同的命名法则。
int i, index, x, y;
int x_add;
类的名字可以由多个单词构成,每个单词的首字母大写,其它字母小写。所有eZ系统创建的类的名字都必须以eZ为前缀。
class eZDialog;
class eZModuleManager;
静态变量采用和成员变量相同的命名法则,但要以下划线为结尾。
static int RefCount_;
绝不使用全局变量,需要时以成员变量或静态变量取代之。

函数
除了main函数、类间的接口函数和C API函数,其它函数都必须置于类内。函数要短小,并且只完成一件工作。函数的长度取决于它的复杂程度。函数越复杂,则函数的长度应越短。太长的函数应该分成几个小函数,每个函数完成一部分任务。一个函数的长度不应该超过30-40行。
函数中使用的变量越少越好,如果你的函数有过多的变量,那么就分解这个函数。如果某个函数可以清晰的分为几个部分,你可以在其中多使用几个变量,但每段代码不应超过七个变量。某些对速度要求很高的数学运算可以不遵守这条规则。
如果一个函数有很多形参,那么最好分几行书写,每行放置几个相互之间关系紧密的形参。形参太多也说明你的函数或许太庞大,试着把它分解成几个小函数。
尽可能的将函数声明为const。避免使用inline函数,如果你必须使用inline函数,那么在这个类已经被认为完成的时候,再加上inline。这样做的目的是,尽量减少重新编译的次数。小心函数的参数默认值,尽可能明确的表示出其含义。

名字空间
为了避免不好的或太长的类名,使用名字空间分隔、组合类和函数。就是说,在不同的名字空间里的两个类可以具有相同的名字,你也就可以使用更直观的名字。但是,在你使用名字空间之前,先确认一下项目组所使用的所有平台都支持它。


类应该只完成一个任务,并且要把这个任务做好。如果某个类过大,就把它分解为几个小类。尽量少使用多重继承,试试使用一个对象指针(这通常被成为组合)代替继承。
所有成员变量必须是私有的。如果需要,通过函数访问成员变量,绝不要使用公有或保护成员变量。
辅助函数应该成为私有函数。

注释
为每个函数写一个注释,说明函数的功能,以及所有难以理解的形参。这些注释必须按照Doxygen()都语法书写。在类的范围内也要编写注释。函数应在注释后另起一行书写。
不要编写多余的注释。如果你必须编写很多的注释才能让你的代码可读,那说明你的代码编写得过于低劣,需要重新编写。

异常
用异常控制那些预期不会发生的事,例如参数具有一个不应该具有的值。经常的使用异常。不要使用异常来跳出循环和函数递归调用,也不要使用异常标志一个预期的输出。使用异常的过程中小心经常可能发生的内存泄漏问题(Bjarne Stroustrup的《The C++ Programming Language》一书中有关于这个问题的很好的阐述)。
使用异常的函数必须在文档中有明确的描述。如果一个函数中使用了异常,一定要使用try/catch语句来处理。在main()函数中使用try/catch语句来告诉用户/开发者产生了某个致命错误。

这就是所有内容
现在你看到了eZ系统的C++编码标准。如果你喜欢它,那么就使用它,如果你不喜欢,你可以编写自己的编码标准或者在网络上寻找其它现成的标准。如果你只是自己写写程序,并且不打算和其他人共享代码,那么你就不需要编写一个明确的标准,而对于其它情况,一个明确的标准可以给你的项目带来更高的一致性和可读性。

 
阅读(1370) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~