华为,百度,腾讯编码风格和个人编码风格

华为,腾讯,百度编码风格和个人编码风格

华为编码风格:
C语言
1.排版
1-1:程序块要采用缩进风格编写,缩进的空格数为4个。
1-2:相对独立的程序块之间、变量说明之后必须加空行。
1-3:较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。
1-4:不允许把多个短语句写在一行中,即一行只写一条语句。
1-5:if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}。
1-6:对齐只使用空格键,不使用TAB键。
1-7:函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。
1-8:程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。
1-9:一行程序以小于80字符为宜,不要写得过长。
2.注释
2-1:一般情况下,源程序有效注释量必须在20%以上。
2-2:文件头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、修改日志等。
2-3:函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。
2-4:边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。
2-5:注释的内容要清楚、明了,含义准确,防止注释二义性。
2-6:注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。
2-7:对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或右方。示例:
2-8:数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。
2-9:全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。
2-10:注释与所描述内容进行同样的缩排。
说明:可使程序排版整齐,并方便注释的阅读与理解。
2-11:避免在一行代码或表达式的中间插入注释。
说明:除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。
2-12:通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的。
说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。
2-13:在代码的功能、意图层次上进行注释,提供有用、额外的信息。
说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。
2-14:在程序块的结束行右方加注释标记,以表明某程序块的结束。
说明:当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。
2-15:注释格式尽量统一,建议使用“/* …… */”。
2-16:注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。
说明:注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。
3.标识符命名
3-1:标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。
说明:较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。
3-2:命名中若使用特殊约定或缩写,则要有注释说明。
说明:应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。
3-3:自己特有的命名风格,要自始至终保持一致,不可来回变化。
说明:个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风格)。
3-4:对于变量命名,禁止取单个字符(如i、j、k…),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k 作局部循环变量是允许的。
说明:变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i 写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。
3-5:命名规范必须与所使用的系统风格保持一致,并在同一项目中统一,比如采用UNIX的全小写加下划线的风格或大小写混排的方式,不要使用大小写与下划线混排的方式,用作特殊标识如标识成员变量或全局变量的m_和g_,其后加上大小写混排的方式是允许的。
3-6:除非必要,不要用数字或较奇怪的字符来定义标识符。
3-7:在同一软件产品内,应规划好接口部分标识符(变量、结构、函数及常量)的命名,防止编译、链接时产生冲突。
说明:对接口部分的标识符应该有更严格限制,防止冲突。如可规定接口部分的变量与常量之前加上“模块”标识等。
3-8:用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。
3-9:除了编译开关/头文件等特殊应用,应避免使用EXAMPLE_TEST之类以下划线开始和结尾的定义。
4.可读性
4-1:注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。
说明:防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。
4-2:避免使用不易理解的数字,用有意义的标识来替代。
涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的枚举或宏来代替。
4-3:源程序中关系较为紧密的代码应尽可能相邻。
说明:便于程序阅读和查找。
4-4:不要使用难懂的技巧性很高的语句,除非很有必要时。
说明:高技巧语句不等于高效率的程序,实际上程序的效率关键在于算法。
5.变量、结构
5-1:去掉没必要的公共变量。
说明:公共变量是增大模块间耦合的原因之一,故应减少没必要的公共变量以降低模块间的耦合度。
5-2:仔细定义并明确公共变量的含义、作用、取值范围及公共变量间的关系。
说明:在对变量声明的同时,应对其含义、作用及取值范围进行注释说明,同时若有必要还应说明与其它变量的关系。
5-3:明确公共变量与操作此公共变量的函数或过程的关系,如访问、修改及创建等。
说明:明确过程操作变量的关系后,将有利于程序的进一步优化、单元测试、系统联调以及代码维护等。这种关系的说明可在注释或文档中描述。
5-4:当向公共变量传递数据时,要十分小心,防止赋与不合理的值或越界等现象发生。
说明:对公共变量赋值时,若有必要应进行合法性检查,以提高代码的可靠性、稳定性。
5-5:防止局部变量与公共变量同名。
说明:若使用了较好的命名规则,那么此问题可自动消除。
5-6:严禁使用未经初始化的变量作为右值。
说明:特别是在C/C++中引用未经赋值的指针,经常会引起系统崩溃。
5-7:结构的功能要单一,是针对一种事务的抽象。
说明:设计结构时应力争使结构代表一种现实事务的抽象,而不是同时代表多种。结构中的各元素应代表同一事务的不同侧面,而不应把描述没有关系或关系很弱的不同事务的元素放到同一结构中。
5-8:不要设计面面俱到、非常灵活的数据结构。
说明:面面俱到、灵活的数据结构反而容易引起误解和操作困难。
5-9:不同结构间的关系不要过于复杂。
说明:若两个结构间关系较复杂、密切,那么应合为一个结构。
5-10:结构中元素的个数应适中。若结构中元素个数过多可考虑依据某种原则把元素组成不同的子结构,以减少原结构中元素的个数。
说明:增加结构的可理解性、可操作性和可维护性。
5-11:仔细设计结构中元素的布局与排列顺序,使结构容易理解、节省占用空间,并减少引起误用现象。
说明:合理排列结构中元素顺序,可节省空间并增加可理解性。
5-12:编程时,要注意数据类型的强制转换。
说明:当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化,而这些细节若考虑不周,就很有可能留下隐患。
5-13:对编译系统默认的数据类型转换,也要有充分的认识。
5-14:尽量减少没有必要的数据类型默认转换与强制转换。
5-15:合理地设计数据并使用自定义数据类型,避免数据间进行不必要的类型转换。
5-16:对自定义数据类型进行恰当命名,使它成为自描述性的,以提高代码可读性。注意其命名方式在同一产品中的统一。
说明:使用自定义类型,可以弥补编程语言提供类型少、信息量不足的缺点,并能使程序清晰、简洁。
6.函数、过程
6-1:对所调用函数的错误返回码要仔细、全面地处理。
6-2:明确函数功能,精确(而不是近似)地实现函数设计。
6-3:编写可重入函数时,应注意局部变量的使用(如编写C/C++语言的可重入函数时,应使用auto 即缺省态局部变量或寄存器变量)。
说明:编写C/C++语言的可重入函数时,不应使用static 局部变量,否则必须经过特殊处理,才能使函数具有可重入性。
6-4:编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。
说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态。
6-5:在同一项目组应明确规定对接口函数参数的合法性检查应由函数的调用者负责还是由接口函数本身负责,缺省是由函数调用者负责。
说明:对于模块间接口函数的参数的合法性检查这一问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这一必要的处理过程,造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。
6-6:函数的规模尽量限制在200行以内。
说明:不包括注释和空格行。
6-7:一个函数仅完成一件功能,不要设计多用途面面俱到的函数。
说明:多功能集于一身的函数,很可能使函数的理解、测试、维护等变得困难。
6-8:函数的功能应该是可以预测的,也就是只要输入数据相同就应产生同样的输出。
说明:带有内部“存储器”的函数的功能可能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态。这样的函数既不易于理解又不利于测试和维护。在C/C++语言中,函数的static 局部变量是函数的内部存储器,有可能使函数的功能不可预测,然而,当某函数的返回值为指针类型时,则必须是STATIC的局部变量的地址作为返回值,若为AUTO类,则返回为错针。
6-9:尽量不要编写依赖于其他函数内部实现的函数。
说明:此条为函数独立性的基本要求。由于目前大部分高级语言都是结构化的,所以通过具体语言的语法要求与编译器功能,基本就可以防止这种情况发生。但在汇编语言中,由于其灵活性,很可能使函数出现这种情况。
6-10:检查函数所有参数输入的有效性。
6-11:检查函数所有非参数输入的有效性,如数据文件、公共变量等。
说明:函数的输入主要有两种:一种是参数输入;另一种是全局变量、数据文件的输入,即非参数输入。函数在使用输入之前,应进行必要的检查。
6-12:函数名应准确描述函数的功能。
6-13:使用动宾词组为执行某操作的函数命名。如果是OOP方法,可以只有动词(名词是对象本身)。
6-14:避免使用无意义或含义不清的动词为函数命名。
说明:避免用含义不清的动词如process、handle 等为函数命名,因为这些动词并没有说明要具体做什么。
6-15:函数的返回值要清楚、明了,让使用者不容易忽视错误情况。
说明:函数的每种出错返回值的意义要清晰、明了、准确,防止使用者误用、理解错误或忽视错误返回码。
6-16:除非必要,最好不要把与函数返回值类型不同的变量,以编译系统默认的转换方式或强制的转换方式作为返回值返回。
6-17:让函数在调用点显得易懂、容易理解。
6-18:在调用函数填写参数时,应尽量减少没有必要的默认数据类型转换或强制数据类型转换。
说明:因为数据类型转换或多或少存在危险。
6-19:避免函数中不必要语句,防止程序中的垃圾代码。
说明:程序中的垃圾代码不仅占用额外的空间,而且还常常影响程序的功能与性能,很可能给程序的测试、维护等造成不必要的麻烦。
6-20:防止把没有关联的语句放到一个函数中。
说明:防止函数或过程内出现随机内聚。随机内聚是指将没有关联或关联很弱的语句放到同一个函数或过程中。随机内聚给函数或过程的维护、测试及以后的升级等造成了不便,同时也使函数或过程的功能不明确。使用随机内聚函数,常常容易出现在一种应用场合需要改进此函数,而另一种应用场合又不允许这种改进,从而陷入困境。在编程时,经常遇到在不同函数中使用相同的代码,许多开发人员都愿把这些代码提出来,并构成一个新函数。若这些代码关联较大并且是完成一个功能的,那么这种构造是合理的,否则这种构造将产生随机内聚的函数。
6-21:如果多段代码重复做同一件事情,那么在函数的划分上可能存在问题。
说明:若此段代码各语句之间有实质性关联并且是完成同一件功能的,那么可考虑把此段代码构造成一个新的函数。
6-22:功能不明确较小的函数,特别是仅有一个上级函数调用它时,应考虑把它合并到上级函数中,而不必单独存在。
说明:模块中函数划分的过多,一般会使函数间的接口变得复杂。所以过小的函数,特别是扇入很低的或功能不明确的函数,不值得单独存在。
6-23:设计高扇入、合理扇出(小于7)的函数。
说明:扇出是指一个函数直接调用(控制)其它函数的数目,而扇入是指有多少上级函数调用它。扇出过大,表明函数过分复杂,需要控制和协调过多的下级函数;而扇出过小,如总是1,表明函数的调用层次可能过多,这样不利程序阅读和函数结构的分析,并且程序运行时会对系统资源如堆栈空间等造成压力。函数较合理的扇出(调度函数除外)通常是3-5。扇出太大,一般是由于缺乏中间层次,可适当增加中间层次的函数。扇出太小,可把下级函数进一步分解多个函数,或合并到上级函数中。当然分解或合并函数时,不能改变要实现的功能,也不能违背函数间的独立性。
扇入越大,表明使用此函数的上级函数越多,这样的函数使用效率高,但不能违背函数间的独立性而单纯地追求高扇入。公共模块中的函数及底层函数应该有较高的扇入。较良好的软件结构通常是顶层函数的扇出较高,中层函数的扇出较少,而底层函数则扇入到公共模块中。
6-24:减少函数本身或函数间的递归调用。
说明:递归调用特别是函数间的递归调用(如A->B->C->A),影响程序的可理解性;递归调用一般都占用较多的系统资源(如栈空间);递归调用对程序的测试有一定影响。故除非为某些算法或功能的实现方便,应减少没必要的递归调用。
6-26:改进模块中函数的结构,降低函数间的耦合度,并提高函数的独立性以及代码可读性、效率和可维护性。优化函数结构时,要遵守以下原则:
(1)不能影响模块功能的实现。
(2)仔细考查模块或函数出错处理及模块的性能要求并进行完善。
(3)通过分解或合并函数来改进软件结构。
(4)考查函数的规模,过大的要进行分解。
(5)降低函数间接口的复杂度。
(6)不同层次的函数调用要有较合理的扇入、扇出。
(7)函数功能应可预测。
(8)提高函数内聚。(单一功能的函数内聚最高)
说明:对初步划分后的函数结构应进行改进、优化,使之更为合理。
6-27:在多任务操作系统的环境下编程,要注意函数可重入性的构造。
说明:可重入性是指函数可以被多个任务进程调用。在多任务操作系统中,函数是否具有可重入性是非常重要的,因为这是多个进程可以共用此函数的必要条件。另外,编译器是否提供可重入函数库,与它所服务的操作系统有关,只有操作系统是多任务时,编译器才有可能提供可重入函数库。如DOS 下BC和MSC 等就不具备可重入函数库,因为DOS 是单用户单任务操作系统。
6-28:避免使用BOOL参数。
说明:原因有二,其一是BOOL参数值无意义,TURE/FALSE的含义是非常模糊的,在调用时很难知道该参数到底传达的是什么意思;其二是BOOL参数值不利于扩充。还有NULL也是一个无意义的单词。
6-29:对于提供了返回值的函数,在引用时最好使用其返回值。
6-30:当一个过程(函数)中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替。
说明:这样可以增加编程效率和程序的可读性。
7.程序效率
7-1:编程时要经常注意代码的效率。
说明:代码效率分为全局效率、局部效率、时间效率及空间效率。全局效率是站在整个系统的角度上的系统效率;局部效率是站在模块或函数角度上的效率;时间效率是程序处理输入任务所需的时间长短;空间效率是程序所需内存空间,如机器代码空间大小、数据空间大小、栈空间大小等。
7-2:在保证软件系统的正确性、稳定性、可读性及可测性的前提下,提高代码效率。
说明:不能一味地追求代码效率,而对软件的正确性、稳定性、可读性及可测性造成影响。
7-3:局部效率应为全局效率服务,不能因为提高局部效率而对全局效率造成影响。
7-4:通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率。
说明:这种方式是解决软件空间效率的根本办法。
7-5:循环体内工作量最小化。
说明:应仔细考虑循环体内的语句是否可以放在循环体之外,使循环体内工作量最小,从而提高程序的时间效率。
7-6:仔细分析有关算法,并进行优化。仔细考查、分析系统及模块处理输入(如事务、消息等)的方式,并加以改进。
7-7:对模块中函数的划分及组织方式进行分析、优化,改进模块中函数的组织结构,提高程序效率。
说明:软件系统的效率主要与算法、处理任务方式、系统功能及函数结构有很大关系,仅在代码上下功夫一般不能解决根本问题。
7-8:编程时,要随时留心代码效率;优化代码时,要考虑周全。
7-9:不应花过多的时间拼命地提高调用不很频繁的函数代码效率。
说明:对代码优化可提高效率,但若考虑不周很有可能引起严重后果。
7-10:要仔细地构造或直接用汇编编写调用频繁或性能要求极高的函数。
说明:只有对编译系统产生机器码的方式以及硬件系统较为熟悉时,才可使用汇编嵌入方式。嵌入汇编可提高时间及空间效率,但也存在一定风险。
7-11:在保证程序质量的前提下,通过压缩代码量、去掉不必要代码以及减少不必要的局部和全局变量,来提高空间效率。
说明:这种方式对提高空间效率可起到一定作用,但往往不能解决根本问题。
7-12:在多重循环中,应将最忙的循环放在最内层。
说明:减少CPU切入循环层的次数。
7-13:尽量减少循环嵌套层次。
7-14:避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。
说明:目的是减少判断次数。循环体中的判断语句是否可以移到循环体外,要视程序的具体情况而言,一般情况,与循环变量无关的判断语句可以移到循环体外,而有关的则不可以。
7-15:尽量用乘法或其它方法代替除法,特别是浮点运算中的除法。
说明:浮点运算除法要占用较多CPU资源。
7-16:不要一味追求紧凑的代码。
说明:因为紧凑的代码并不代表高效的机器码。
8.质量保证
8-1:在软件设计过程中构筑软件质量。
8-2:代码质量保证优先原则
(1)正确性,指程序要实现设计要求的功能。
(2)稳定性、安全性,指程序稳定、可靠、安全。
(3)可测试性,指程序要具有良好的可测试性。
(4)规范/可读性,指程序书写风格、命名规则等要符合规范。
(5)全局效率,指软件系统的整体效率。
(6)局部效率,指某个模块/子模块/函数的本身效率。
(7)个人表达方式/个人方便性,指个人编程习惯。
8-3:只引用属于自己的存贮空间。
说明:若模块封装的较好,那么一般不会发生非法引用他人的空间。
8-4:防止引用已经释放的内存空间。
说明:在实际编程过程中,稍不留心就会出现在一个模块中释放了某个内存块(如C语言指针),而另一模块在随后的某个时刻又使用了它。要防止这种情况发生。
8-5:过程/函数中分配的内存,在过程/函数退出之前要释放。
8-6:过程/函数中申请的(为打开文件而使用的)文件句柄,在过程/函数退出之前要关闭。
说明:分配的内存不释放以及文件句柄不关闭,是较常见的错误,而且稍不注意就有可能发生。这类错误往往会引起很严重后果,且难以定位。
8-7:防止内存操作越界。
说明:内存操作主要是指对数组、指针、内存地址等的操作。内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心。
8-8:认真处理程序所能遇到的各种出错情况。
8-9:系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。
8-10:系统运行之初,要对加载到系统中的数据进行一致性检查。
说明:使用不一致的数据,容易使系统进入混乱状态和不可知状态。
8-11:严禁随意更改其它模块或系统的有关设置和配置。
说明:编程时,不能随心所欲地更改不属于自己模块的有关设置如常量、数组的大小等。
8-12:不能随意改变与其它模块的接口。
8-13:充分了解系统的接口之后,再使用系统提供的功能。
8-14:编程时,要防止差1错误。
说明:此类错误一般是由于把“<=”误写成“<”或“>=”误写成“>”等造成的,由此引起的后果,很多情况下是很严重的,所以编程时,一定要在这些地方小心。当编完程序后,应对这些操作符进行彻底检查。
8-15:要时刻注意易混淆的操作符。当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误。
说明:形式相近的操作符最容易引起误用,如C/C++中的“=”与“==”、“|”与“||”、“&”与“&&”等,若拼写错了,编译器不一定能够检查出来。
8-16:有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支。
8-17:Unix下,多线程的中的子线程退出必需采用主动退出方式,即子线程应return出口。
8-18:不要滥用goto语句。
说明:goto语句会破坏程序的结构性,所以除非确实需要,最好不使用goto语句。
8-19:精心地构造、划分子模块,并按“接口”部分及“内核”部分合理地组织子模块,以提高“内核”部分的可移植性和可重用性。
说明:对不同产品中的某个功能相同的模块,若能做到其内核部分完全或基本一致,那么无论对产品的测试、维护,还是对以后产品的升级都会有很大帮助。
8-20:精心构造算法,并对其性能、效率进行测试。
8-21:对较关键的算法最好使用其它算法来确认。
8-22:时刻注意表达式是否会上溢、下溢。
8-23:使用变量时要注意其边界值的情况。
8-24:留心程序机器码大小(如指令空间大小、数据空间大小、堆栈空间大小等)是否超出系统有关限制。
8-25:为用户提供良好的接口界面,使用户能较充分地了解系统内部运行状态及有关系统出错情况。
8-26:系统应具有一定的容错能力,对一些错误事件(如用户误操作等)能进行自动补救。
8-27:对一些具有危险性的操作代码(如写硬盘、删数据等)要仔细考虑,防止对数据、硬件等的安全构成危害,以提高系统的安全性。
8-28:使用第三方提供的软件开发工具包或控件时,要注意以下几点:
(1)充分了解应用接口、使用环境及使用时注意事项。
(2)不能过分相信其正确性。
(3)除非必要,不要使用不熟悉的第三方工具包与控件。
说明:使用工具包与控件,可加快程序开发速度,节省时间,但使用之前一定对它有较充分的了解,同时第三方工具包与控件也有可能存在问题。
8-29:资源文件(多语言版本支持),如果资源是对语言敏感的,应让该资源与源代码文件脱离,具体方法有下面几种:使用单独的资源文件、DLL 文件或其它单独的描述文件(如数据库格式)
9.代码编辑、编译、审查
9-1:打开编译器的所有告警开关对程序进行编译。
9-2:在产品软件(项目组)中,要统一编译开关选项。
9-3:通过代码走读及审查方式对代码进行检查。
说明:代码走读主要是对程序的编程风格如注释、命名等以及编程时易出错的内容进行检查,可由开发人员自己或开发人员交叉的方式进行;代码审查主要是对程序实现的功能及程序的稳定性、安全性、可靠性等进行检查及评审,可通过自审、交叉审核或指定部门抽查等方式进行。
9-4:测试部测试产品之前,应对代码进行抽查及评审。目组最好采用相同的智能语言编辑器,如Muiti Editor,Visual Editor 等,并设计、使用一套缩进宏及注释
9-5:编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢失。
9-6:同产品软件(项目组)内,最好使用相同的编辑器,并使用相同的设置选项。
说明:同一项宏等,将缩进等问题交由编辑器处理。
9-7:合理地设计软件系统目录,方便开发人员使用。
说明:方便、合理的软件系统目录,可提高工作效率。目录构造的原则是方便有关源程序的存储、查询、编译、链接等工作,同时目录中还应具有工作目录—-所有的编译、链接等工作应在此目录中进行,工具目录—-有关文件编辑器、文件查找等工具可存放在此目录中。
9-8:某些语句经编译后产生告警,但如果你认为它是正确的,那么应通过某种手段去掉告警信息。
说明:在BorlandC/C++中,可用“#pragma warn”来关掉或打开某些告警。
9-9:使用代码检查工具(如C 语言用PC-Lint)对源程序检查。
10.代码测试、维护
10-1:单元测试要求至少达到语句覆盖。
10-2:单元测试开始要跟踪每一条语句,并观察数据流及变量的变化。
10-3:清理、整理或优化后的代码要经过审查及测试。
10-4:代码版本升级要经过严格测试。
10-5:使用工具软件对代码版本进行维护。
10-6:正式版本上软件的任何修改都应有详细的文档记录。
10-7:发现错误立即修改,并且要记录下来。
10-8:关键的代码在汇编级跟踪。
10-9:仔细设计并分析测试用例,使测试用例覆盖尽可能多的情况,以提高测试用例的效率。
10-11:尽可能模拟出程序的各种出错情况,对出错处理代码进行充分的测试。
10-12:仔细测试代码处理数据、变量的边界情况。
10-13:保留测试信息,以便分析、总结经验及进行更充分的测试。
10-14:不应通过“试”来解决问题,应寻找问题的根本原因。
10-15:对自动消失的错误进行分析,搞清楚错误是如何消失的。
10-16:修改错误不仅要治表,更要治本。
10-17:测试时应设法使很少发生的事件经常发生。
10-18:明确模块或函数处理哪些事件,并使它们经常发生。
10-19:坚持在编码阶段就对代码进行彻底的单元测试,不要等以后的测试工作来发现问题。
10-20:去除代码运行的随机性(如去掉无用的数据、代码及尽可能防止并注意函数中的“内部寄存器”等),让函数运行的结果可预测,并使出现的错误可再现。
11.宏
11-1:用宏定义表达式时,要使用完备的括号。
11-2:将宏所定义的多条表达式放在大括号中。
C++
1.排版
1-1:程序块要采用缩进风格编写,缩进的空格数为4个。说明:对于由开发工具自动生成的代码可以有不一致。
1-2:相对独立的程序块之间、变量说明之后必须加空行。
1-3:较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。
1-4:循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。
1-5:若函数或过程中的参数较长,则要进行适当的划分。
1-7:if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}。
1-8:对齐只使用空格键,不使用TAB键。说明:以免用不同的编辑器阅读程序时,因TAB键所设置的空格数目不同而造成程序布局不整齐,不要使用BC作为编辑器合版本,因为BC会自动将8个空格变为一个TAB键,因此使用BC合入的版本大多会将缩进变乱。
1-9:函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求。
1-10:程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。
1-11:在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。说明:采用这种松散方式编写代码的目的是使代码更加清晰。由于留空格所产生的清晰性是相对的,所以,在已经非常清晰的语句中没有必要再留空格,如果语句已足够清晰则括号内侧(即左括号后面和右括号前面)不需要加空格,多重括号间不必加空格,因为在C/C++语言中括号已经是最清晰的标志了。在长语句中,如果需要加的空格非常多,那么应该保持整体清晰,而在局部不加空格。给操作符留空格时不要连续留两个以上空格。
2.注释
2-1:一般情况下,源程序有效注释量必须在20%以上。说明:注释的原则是有助于对程序的阅读理解,在该加的地方都加了,注释不宜太多也不能太少,注释语言必须准确、易懂、简洁。
2-2:说明性文件(如头文件.h文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。
2-3:源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。说明:Description一项描述本文件的内容、功能、内部各部分之间的关系及本文件与其它文件关系等。History是修改历史记录列表,每条修改记录应包括修改日期、修改者及修改内容简述。
2-4:函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。
2-6:注释的内容要清楚、明了,含义准确,防止注释二义性。说明:错误的注释不但无益反而有害。
2-7:避免在注释中使用缩写,特别是非常用缩写。 说明:在使用缩写时或之前,应对缩写进行必要的说明。
2-8:注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。
2-9:对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或右方。
2-10:数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。
2-11:全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。
2-12:注释与所描述内容进行同样的缩排。
2-13:将注释与其上面的代码用空行隔开。
2-14:对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。
说明:这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。
2-15:对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,必须在该case语句处理完、下一个case语句前加上明确的注释。
说明:这样比较清楚程序编写者的意图,有效防止无故遗漏break语句。
2-16:避免在一行代码或表达式的中间插入注释。
说明:除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。
2-17:通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的。
说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。
2-18:在代码的功能、意图层次上进行注释,提供有用、额外的信息。
说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。
2-19:在程序块的结束行右方加注释标记,以表明某程序块的结束。
说明:当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。
2-20:注释格式尽量统一,建议使用“/* …… */”。
2-21:注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。说明:注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。
3 .标识符命名
3-1:标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。
说明:较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。
3-2:命名中若使用特殊约定或缩写,则要有注释说明。说明:应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。
3-3:自己特有的命名风格,要自始至终保持一致,不可来回变化。说明:个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风格)。
3-4:对于变量命名,禁止取单个字符(如i、j、k…),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k作局部循环变量是允许的。说明:变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间
3-5:命名规范必须与所使用的系统风格保持一致,并在同一项目中统一,比如采用UNIX的全小写加下划线的风格或大小写混排的方式,不要使用大小写与下划线混排的方式,用作特殊标识如标识成员变量或全局变量的m_和g_,其后加上大小写混排的方式是允许的。
4. 可读性
4-1:注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。说明:防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错。
4-2:避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的枚举或宏来代替。
5.变量、结构
5-1:去掉没必要的公共变量。
说明:公共变量是增大模块间耦合的原因之一,故应减少没必要的公共变量以降低模块间的耦合度。
5-2:仔细定义并明确公共变量的含义、作用、取值范围及公共变量间的关系。说明:在对变量声明的同时,应对其含义、作用及取值范围进行注释说明,同时若有必要还应说明与其它变量的关系。
5-3:明确公共变量与操作此公共变量的函数或过程的关系,如访问、修改及创建等。说明:明确过程操作变量的关系后,将有利于程序的进一步优化、单元测试、系统联调以及代码维护等。这种关系的说明可在注释或文档中描述。
5-4:当向公共变量传递数据时,要十分小心,防止赋与不合理的值或越界等现象发生。说明:对公共变量赋值时,若有必要应进行合法性检查,以提高代码的可靠性、稳定性。
5-5:防止局部变量与公共变量同名。说明:若使用了较好的命名规则,那么此问题可自动消除。
5-6:严禁使用未经初始化的变量作为右值。说明:特别是在C/C++中引用未经赋值的指针,经常会引起系统崩溃。
5-7:构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的公共变量,防止多个不同模块或函数都可以修改、创建同一公共变量的现象。说明:降低公共变量耦合度。
5-8:使用严格形式定义的、可移植的数据类型,尽量不要使用与具体硬件或软件环境关系密切的变量。说明:使用标准的数据类型,有利于程序的移植。
5-9:结构的功能要单一,是针对一种事务的抽象。说明:设计结构时应力争使结构代表一种现实事务的抽象,而不是同时代表多种。结构中的各元素应代表同一事务的不同侧面,而不应把描述没有关系或关系很弱的不同事务的元素放到同一结构中。
5-10:不要设计面面俱到、非常灵活的数据结构。说明:面面俱到、灵活的数据结构反而容易引起误解和操作困难。
5-11:不同结构间的关系不要过于复杂。说明:若两个结构间关系较复杂、密切,那么应合为一个结构。
5-12:结构中元素的个数应适中。若结构中元素个数过多可考虑依据某种原则把元素组成不同的子结构,以减少原结构中元素的个数。说明:增加结构的可理解性、可操作性和可维护性。
5-13:仔细设计结构中元素的布局与排列顺序,使结构容易理解、节省占用空间,并减少引起误用现象。说明:合理排列结构中元素顺序,可节省空间并增加可理解性。
5-14:结构的设计要尽量考虑向前兼容和以后的版本升级,并为某些未来可能的应用保留余地(如预留一些空间等)。说明:软件向前兼容的特性,是软件产品是否成功的重要标志之一。如果要想使产品具有较好的前向兼容,那么在产品设计之初就应为以后版本升级保留一定余地,并且在产品升级时必须考虑前一版本的各种特性。
5-15:留心具体语言及编译器处理不同数据类型的原则及有关细节。说明:如在C语言中,static局部变量将在内存“数据区”中生成,而非static局部变量将在“堆栈”中生成。这些细节对程序质量的保证非常重要。
5-16:编程时,要注意数据类型的强制转换。说明:当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化,而这些细节若考虑不周,就很有可能留下隐患。
5-17:对编译系统默认的数据类型转换,也要有充分的认识。
5-18:尽量减少没有必要的数据类型默认转换与强制转换。
5-19:合理地设计数据并使用自定义数据类型,避免数据间进行不必要的类型转换。
5-20:对自定义数据类型进行恰当命名,使它成为自描述性的,以提高代码可读性。注意其命名方式在同一产品中的统一。说明:使用自定义类型,可以弥补编程语言提供类型少、信息量不足的缺点,并能使程序清晰、简洁。
5-21:当声明用于分布式环境或不同CPU间通信环境的数据结构时,必须考虑机器的字节顺序、使用的位域及字节对齐等问题 。说明:比如IntelCPU与68360 CPU,在处理位域及整数时,其在内存存放的“顺序”正好相反。
6 .函数、过程
6-1:对所调用函数的错误返回码要仔细、全面地处理。
6-2:明确函数功能,精确(而不是近似)地实现函数设计。
6-3:编写可重入函数时,应注意局部变量的使用(如编写C/C++语言的可重入函数时,应使用auto即缺省态局部变量或寄存器变量)。说明:编写C/C++语言的可重入函数时,不应使用static局部变量,否则必须经过特殊处理,才能使函数具有可重入性。
6-4:编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。说明:若对所使用的全局变量不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使有关全局变量变为不可知状态
6-5:在同一项目组应明确规定对接口函数参数的合法性检查应由函数的调用者负责还是由接口函数本身负责,缺省是由函数调用者负责。说明:对于模块间接口函数的参数的合法性检查这一问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这一必要的处理过程,造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。
6-6:防止将函数的参数作为工作变量。说明:将函数的参数作为工作变量,有可能错误地改变参数内容,所以很危险。对必须改变的参数,最好先用局部变量代之,最后再将该局部变量的内容赋给该参数。
6-7:函数的规模尽量限制在200行以内。说明:不包括注释和空格行。
6-8:一个函数仅完成一件功能。
6-9:为简单功能编写函数。说明:虽然为仅用一两行就可完成的功能去编函数好象没有必要,但用函数可使功能明确化,增加程序可读性,亦可方便维护、测试。
6-10:不要设计多用途面面俱到的函数。说明:多功能集于一身的函数,很可能使函数的理解、测试、维护等变得困难。
6-11:函数的功能应该是可以预测的,也就是只要输入数据相同就应产生同样的输出。说明:带有内部“存储器”的函数的功能可能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态。这样的函数既不易于理解又不利于测试和维护。在C/C++语言中,函数的static局部变量是函数的内部存储器,有可能使函数的功能不可预测,然而,当某函数的返回值为指针类型时,则必须是STATIC的局部变量的地址作为返回值,若为AUT6-7:尽量不要编写依赖于其他函数内部实现的函数说明:此条为函数独立性的基本要求。由于目前大部分高级语言都是结构化的,所以通过具体语言的语法要求与编译器功能,基本就可以防止这种情况发生。但在汇编语言中,由于其灵活性,很可能使函数出现这种情况。
6-12:避免设计多参数函数,不使用的参数从接口中去掉。说明:目的减少函数间接口的复杂度。
6-13:非调度函数应减少或防止控制参数,尽量只使用数据参数。说明:本建议目的是防止函数间的控制耦合。调度函数是指根据输入的消息类型或控制命令,来启动相应的功能实体(即函数或过程),而本身并不完成具体功能。控制参数是指改变函数功能行为的参数,即函数要根据此参数来决定具体怎样工作。非调度函数的控制参数增加了函数间的控制耦合,很可能使函数间的耦合度增大,并使函数的功能不唯一。
6-14:检查函数所有参数输入的有效性。
6-15:检查函数所有非参数输入的有效性,如数据文件、公共变量等。
说明:函数的输入主要有两种:一种是参数输入;另一种是全局变量、数据文件的输入,即非参数输入。函数在使用输入之前,应进行必要的检查。
6-16:函数名应准确描述函数的功能。
6-17:使用动宾词组为执行某操作的函数命名。如果是OOP方法,可以只有动词(名词是对象本身)。
6-18:除非必要,最好不要把与函数返回值类型不同的变量,以编译系统默认的转换方式或强制的转换方式作为返回值返回。
6-19:让函数在调用点显得易懂、容易理解。
6-20:在调用函数填写参数时,应尽量减少没有必要的默认数据类型转换或强制数据类型转换.说明:因为数据类型转换或多或少存在危险。
6-21:避免函数中不必要语句,防止程序中的垃圾代码。说明:程序中的垃圾代码不仅占用额外的空间,而且还常常影响程序的功能与性能,很可能给程序的测试、维护等造成不必要的麻烦。
6-22:防止把没有关联的语句放到一个函数中。说明:防止函数或过程内出现随机内聚。随机内聚是指将没有关联或关联很弱的语句放到同一个函数或过程中。随机内聚给函数或过程的维护、测试及以后的升级等造成了不便,同时也使函数或过程的功能不明确。使用随机内聚函数,常常容易出现在一种应用场合需要改进此函数,而另一种应用场合又不允许这种改进,从而陷入困境。在编程时,经常遇到在不同函数中使用相同的代码,许多开发人员都愿把这些代码提出来,并构成一个新函数。若这些代码关联较大并且是完成一个功能的,那么这种构造是合理的,否则这种构造将产生随机内聚的函数。
6-23:如果多段代码重复做同一件事情,那么在函数的划分上可能存在问题。说明:若此段代码各语句之间有实质性关联并且是完成同一件功能的,那么可考虑把此段代码构造成一个新的函数。
6-24:功能不明确较小的函数,特别是仅有一个上级函数调用它时,应考虑把它合并到上级函数中,而不必单独存在说明:模块中函数划分的过多,一般会使函数间的接口变得复杂。所以过小的函数,特别是扇入很低的或功能不明确的函数,不值得单独存在。
6-25:设计高扇入、合理扇出(小于7)的函数。说明:扇出是指一个函数直接调用(控制)其它函数的数目,而扇入是指有多少上级函数调用它。扇出过大,表明函数过分复杂,需要控制和协调过多的下级函数;而扇出过小,如总是1,表明函数的调用层次可能过多,这样不利程序阅读和函数结构的分析,并且程序运行时会对系统资源如堆栈空间等造成压力。函数较合理的扇出(调度函数除外)通常是3-5。扇出太大,一般是由于缺乏中间层次,可适当增加中间层次的函数。扇出太小,可把下级函数进一步分解多个函数,或合并到上级函数中。当然分解或合并函数时,不能改变要实现的功能,也不能违背函数间的独立性。
扇入越大,表明使用此函数的上级函数越多,这样的函数使用效率高,但不能违背函数间的独立性而单纯地追求高扇入。公共模块中的函数及底层函数应该有较高的扇入。
较良好的软件结构通常是顶层函数的扇出较高,中层函数的扇出较少,而底层函数则扇入到公共模块中。
6-26:减少函数本身或函数间的递归调用。说明:递归调用特别是函数间的递归调用(如A->B->C->A),影响程序的可理解性;递归调用一般都占用较多的系统资源(如栈空间);递归调用对程序的测试有一定影响。故除非为某些算法或功能的实现方便,应减少没必要的递归调用。
6-27:仔细分析模块的功能及性能需求,并进一步细分,同时若有必要画出有关数据流图,据此来进行模块的函数划分与组织。说明:函数的划分与组织是模块的实现过程中很关键的步骤,如何划分出合理的函数结构,关系到模块的最终效率和可维护性、可测性等。根据模块的功能图或/及数据流图映射出函数结构是常用方法之一。
6-28:改进模块中函数的结构,降低函数间的耦合度,并提高函数的独立性以及代码可读性、效率和可维护性。优化函数结构时,要遵守以下原则:
(1)不能影响模块功能的实现。
(2)仔细考查模块或函数出错处理及模块的性能要求并进行完善。
(3)通过分解或合并函数来改进软件结构。
(4)考查函数的规模,过大的要进行分解。
(5)降低函数间接口的复杂度。
(6)不同层次的函数调用要有较合理的扇入、扇出。
(7)函数功能应可预测。
(8)提高函数内聚。(单一功能的函数内聚最高)
6-29:在多任务操作系统的环境下编程,要注意函数可重入性的构造。说明:可重入性是指函数可以被多个任务进程调用。在多任务操作系统中,函数是否具有可重入性是非常重要的,因为这是多个进程可以共用此函数的必要条件。另外,编译器是否提供可重入函数库,与它所服务的操作系统有关,只有操作系统是多任务时,编译器才有可能提供可重入函数库。如DOS下BC和MSC等就不具备可重入函数库,因为DOS是单用户单任务操作系统。
6-30:避免使用BOOL参数。说明:原因有二,其一是BOOL参数值无意义,TURE/FALSE的含义是非常模糊的,在调用时很难知道该参数到底传达的是什么意思;其二是BOOL参数值不利于扩充。还有NULL也是一个无意义的单词。
6-31: 对于提供了返回值的函数,在引用时最好使用其返回值。
6-32:当一个过程(函数)中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替。 说明:这样可以增加编程效率和程序的可读性。
7 .可测性
7-1:在同一项目组或产品组内,要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数,并且要有详细的说明。说明:本规则是针对项目组或产品组的。
7-2:在同一项目组或产品组内,调测打印出的信息串的格式要有统一的形式。信息串中至少要有所在模块名(或源文件名)及行号。说明:统一的调测信息格式便于集成测试。
7-3:编程的同时要为单元测试选择恰当的测试点,并仔细构造测试代码、测试用例,同时给出明确的注释说明。测试代码部分应作为(模块中的)一个子模块,以方便测试代码在模块中的安装与拆卸(通过调测开关)。说明:为单元测试而准备。
7-4:在进行集成测试/系统联调之前,要构造好测试环境、测试项目及测试用例,同时仔细分析并优化测试用例,以提高测试效率。说明:好的测试用例应尽可能模拟出程序所遇到的边界值、各种复杂环境及一些极端情况等。
7-5:使用断言来发现软件问题,提高代码可测性。说明:断言是对某种假设条件进行检查(可理解为若条件成立则无动作,否则应报告),它可以快速发现并定位软件问题,同时对系统错误进行自动报警。断言可以对在系统中隐藏很深,用其它手段极难发现的问题进行定位,从而缩短软件问题定位时间,提高系统的可测性。实际应用时,可根据具体情况灵活地设计断言。
7-6:用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况。
7-7:不能用断言来检查最终产品肯定会出现且必须处理的错误情况。
说明:断言是用来处理不应该发生的错误情况的,对于可能会发生的且必须处理的情况要写防错程序,而不是断言。如某模块收到其它模块或链路上的消息后,要对消息的合理性进行检查,此过程为正常的错误检查,不能用断言来实现。
7-8:对较复杂的断言加上明确的注释。说明:为复杂的断言加注释,可澄清断言含义并减少不必要的误用。
7-9:用断言确认函数的参数。
7-10:用断言保证没有定义的特性或功能不被使用。
7-11:用断言对程序开发环境(OS/Compiler/Hardware)的假设进行检查。说明:程序运行时所需的软硬件环境及配置要求,不能用断言来检查,而必须由一段专门代码处理。用断言仅可对程序开发环境中的假设及所配置的某版本软硬件是否具有某种功能的假设进行检查。如某网卡是否在系统运行环境中配置了,应由程序中正式代码来检查;而此网卡是否具有某设想的功能,则可由断言来检查。对编译器提供的功能及特性假设可用断言检查,原因是软件最终产品(即运行代码或机器码)与编译器已没有任何直接关系,即软件运行过程中(注意不是编译过程中)不会也不应该对编译器的功能提出任何需求。
7-12:正式软件产品中应把断言及其它调测代码去掉(即把有关的调测开关关掉)。说明:加快软件运行速度。
7-13:在软件系统中设置与取消有关测试手段,不能对软件实现的功能等产生影响。说明:即有测试代码的软件和关掉测试代码的软件,在功能行为上应一致。
7-14:用调测开关来切换软件的DEBUG版和正式版,而不要同时存在正式版本和DEBUG版本的不同源文件,以减少维护的难度。
7-15:软件的DEBUG版本和发行版本应该统一维护,不允许分家,并且要时刻注意保证两个版本在实现功能上的一致性。
7-16:编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码如打印函数等。说明:程序的调试与测试是软件生存周期中很重要的一个阶段,如何对软件进行较全面、高率的测试并尽可能地找出软件中的错误就成为很关键的问题。因此在编写源代码之前,除了要有一套比较完善的测试计划外,还应设计出一系列代码测试手段,为单元测试、集成测试及系统联调提供方便。
7-17:调测开关应分为不同级别和类型。说明:调测开关的设置及分类应从以下几方面考虑:针对模块或系统某部分代码的调测;针对模块或系统某功能的调测;出于某种其它目的,如对性能、容量等的测试。这样做便于软件功能的调测,并且便于模块的单元测试、系统联调等。
7-18:编写防错程序,然后在处理错误之后可用断言宣布发生错误。
8 .程序效率
8-1:编程时要经常注意代码的效率。
说明:代码效率分为全局效率、局部效率、时间效率及空间效率。全局效率是站在整个系统的角度上的系统效率;局部效率是站在模块或函数角度上的效率;时间效率是程序处理输入任务所需的时间长短;空间效率是程序所需内存空间,如机器代码空间大小、数据空间大小、栈空间大小等。
8-2:在保证软件系统的正确性、稳定性、可读性及可测性的前提下,提高代码效率。说明:不能一味地追求代码效率,而对软件的正确性、稳定性、可读性及可测性造成影响。
8-3:局部效率应为全局效率服务,不能因为提高局部效率而对全局效率造成影响。
8-4:通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率.说明:这种方式是解决软件空间效率的根本办法。
8-5:循环体内工作量最小化。说明:应仔细考虑循环体内的语句是否可以放在循环体之外,使循环体内工作量最小,从而提高程序的时间效率。
8-6:仔细分析有关算法,并进行优化。
8-7:仔细考查、分析系统及模块处理输入(如事务、消息等)的方式,并加以改进。
8-8:对模块中函数的划分及组织方式进行分析、优化,改进模块中函数的组织结构,提高程序效率。说明:软件系统的效率主要与算法、处理任务方式、系统功能及函数结构有很大关系,仅在代码上下功夫一般不能解决根本问题。
8-9:编程时,要随时留心代码效率;优化代码时,要考虑周全。
8-10:不应花过多的时间拼命地提高调用不很频繁的函数代码效率。
说明:对代码优化可提高效率,但若考虑不周很有可能引起严重后果。
8-11:要仔细地构造或直接用汇编编写调用频繁或性能要求极高的函数。说明:只有对编译系统产生机器码的方式以及硬件系统较为熟悉时,才可使用汇编嵌入方式。嵌入汇编可提高时间及空间效率,但也存在一定风险。
8-12:在保证程序质量的前提下,通过压缩代码量、去掉不必要代码以及减少不必要的局部和全局变量,来提高空间效率。说明:这种方式对提高空间效率可起到一定作用,但往往不能解决根本问题。
8-13:在多重循环中,应将最忙的循环放在最内层。说明:减少CPU切入循环层的次数。
8-14:尽量减少循环嵌套层次。
8-15:避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。说明:目的是减少判断次数。循环体中的判断语句是否可以移到循环体外,要视程序的具体情况而言,一般情况,与循环变量无关的判断语句可以移到循环体外,而有关的则不可以。
8-16:尽量用乘法或其它方法代替除法,特别是浮点运算中的除法。说明:浮点运算除法要占用较多CPU资源。
8-17:不要一味追求紧凑的代码。说明:因为紧凑的代码并不代表高效的机器码。
9 .质量保证
9-1:在软件设计过程中构筑软件质量。
9-2:代码质量保证优先原则
     (1)正确性,指程序要实现设计要求的功能。
     (2)稳定性、安全性,指程序稳定、可靠、安全。
     (3)可测试性,指程序要具有良好的可测试性。
     (4)规范/可读性,指程序书写风格、命名规则等要符合规范。
     (5)全局效率,指软件系统的整体效率。
     (6)局部效率,指某个模块/子模块/函数的本身效率。
     (7)个人表达方式/个人方便性,指个人编程习惯。
9-3:只引用属于自己的存贮空间。说明:若模块封装的较好,那么一般不会发生非法引用他人的空间。
9-4:防止引用已经释放的内存空间。说明:在实际编程过程中,稍不留心就会出现在一个模块中释放了某个内存块(如C语言指针),而另一模块在随后的某个时刻又使用了它。要防止这种情况发生。
9-5:过程/函数中分配的内存,在过程/函数退出之前要释放。
9-6:过程/函数中申请的(为打开文件而使用的)文件句柄,在过程/函数退出之前要关闭。
说明:分配的内存不释放以及文件句柄不关闭,是较常见的错误,而且稍不注意就有可能发生。这类错误往往会引起很严重后果,且难以定位。
9-7:防止内存操作越界。
说明:内存操作主要是指对数组、指针、内存地址等的操作。内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心。
9-8:认真处理程序所能遇到的各种出错情况。
9-9:系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。
9-10:系统运行之初,要对加载到系统中的数据进行一致性检查。
说明:使用不一致的数据,容易使系统进入混乱状态和不可知状态。
9-11:严禁随意更改其它模块或系统的有关设置和配置。
说明:编程时,不能随心所欲地更改不属于自己模块的有关设置如常量、数组的大小等。
9-12:不能随意改变与其它模块的接口。
9-13:充分了解系统的接口之后,再使用系统提供的功能。
9-14:编程时,要防止差1错误。
说明:此类错误一般是由于把“<=”误写成“<”或“>=”误写成“>”等造成的,由此引起的后果,很多情况下是很严重的,所以编程时,一定要在这些地方小心。当编完程序后,应对这些操作符进行彻底检查。
9-15:要时刻注意易混淆的操作符。当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误。
说明:形式相近的操作符最容易引起误用,如C/C++中的“=”与“==”、“|”与“||”、“&”与“&&”等,若拼写错了,编译器不一定能够检查出来。
9-16:有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支。
9-17:Unix下,多线程的中的子线程退出必需采用主动退出方式,即子线程应return出口。
9-18:不要滥用goto语句。
说明:goto语句会破坏程序的结构性,所以除非确实需要,最好不使用goto语句。
9-19:不使用与硬件或操作系统关系很大的语句,而使用建议的标准语句,以提高软件的可移植性和可重用性。
9-20:除非为了满足特殊需求,避免使用嵌入式汇编。
说明:程序中嵌入式汇编,一般都对可移植性有较大的影响。
9-21:精心地构造、划分子模块,并按“接口”部分及“内核”部分合理地组织子模块,以提高“内核”部分的可移植性和可重用性。
说明:对不同产品中的某个功能相同的模块,若能做到其内核部分完全或基本一致,那么无论对产品的测试、维护,还是对以后产品的升级都会有很大帮助。
9-22:精心构造算法,并对其性能、效率进行测试。
9-23:对较关键的算法最好使用其它算法来确认。
9-24:时刻注意表达式是否会上溢、下溢。
9-25:使用变量时要注意其边界值的情况。
9-26:留心程序机器码大小(如指令空间大小、数据空间大小、堆栈空间大小等)是否超出系统有关限制。
9-27:为用户提供良好的接口界面,使用户能较充分地了解系统内部运行状态及有关系统出错情况。
9-28:系统应具有一定的容错能力,对一些错误事件(如用户误操作等)能进行自动补救。
9-29:对一些具有危险性的操作代码(如写硬盘、删数据等)要仔细考虑,防止对数据、硬件等的安全构成危害,以提高系统的安全性。
9-30:使用第三方提供的软件开发工具包或控件时,要注意以下几点:
(1)充分了解应用接口、使用环境及使用时注意事项。
(2)不能过分相信其正确性。
(3)除非必要,不要使用不熟悉的第三方工具包与控件。
说明:使用工具包与控件,可加快程序开发速度,节省时间,但使用之前一定对它有较充分的了解,同时第三方工具包与控件也有可能存在问题。
9-31:资源文件(多语言版本支持),如果资源是对语言敏感的,应让该资源与源代码文件脱离,具体方法有下面几种:使用单独的资源文件、DLL文件或其它单独的描述文件(如数据库格式)
10. 代码编辑、编译、审查
10-1:打开编译器的所有告警开关对程序进行编译。
10-2:在产品软件(项目组)中,要统一编译开关选项。
10-3:通过代码走读及审查方式对代码进行检查。
说明:代码走读主要是对程序的编程风格如注释、命名等以及编程时易出错的内容进行检查,可由开发人员自己或开发人员交叉的方式进行;代码审查主要是对程序实现的功能及程序的稳定性、安全性、可靠性等进行检查及评审,可通过自审、交叉审核或指定部门抽查等方式进行。
10-4:测试部测试产品之前,应对代码进行抽查及评审。
10-5:编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢失。
10-6:同产品软件(项目组)内,最好使用相同的编辑器,并使用相同的设置选项。
说明:同一项目组最好采用相同的智能语言编辑器,如Muiti Editor,VisualEditor等,并设计、使用一套缩进宏及注释宏等,将缩进等问题交由编辑器处理。
10-7:要小心地使用编辑器提供的块拷贝功能编程。
说明:当某段代码与另一段代码的处理功能相似时,许多开发人员都用编辑器提供的块拷贝功能来完成这段代码的编写。由于程序功能相近,故所使用的变量、采用的表达式等在功能及命名上可能都很相近,所以使用块拷贝时要注意,除了修改相应的程序外,一定要把使用的每个变量仔细查看一遍,以改成正确的。不应指望编译器能查出所有这种错误,比如当使用的是全局变量时,就有可能使某种错误隐藏下来。
10-8:合理地设计软件系统目录,方便开发人员使用。
说明:方便、合理的软件系统目录,可提高工作效率。目录构造的原则是方便有关源程序的存储、查询、编译、链接等工作,同时目录中还应具有工作目录—-所有的编译、链接等工作应在此目录中进行,工具目录—-有关文件编辑器、文件查找等工具可存放在此目录中。
10-9:某些语句经编译后产生告警,但如果你认为它是正确的,那么应通过某种手段去掉告警信息。
说明:在BorlandC/C++中,可用“#pragma  warn”来关掉或打开某些告警。
10-10:使用代码检查工具(如C语言用PC-Lint)对源程序检查。
10-11:使用软件工具(如 LogiSCOPE)进行代码审查。
11. 代码测试、维护
11-1:单元测试要求至少达到语句覆盖。
11-2:单元测试开始要跟踪每一条语句,并观察数据流及变量的变化。
11-3:清理、整理或优化后的代码要经过审查及测试。
11-4:代码版本升级要经过严格测试。
11-5:使用工具软件对代码版本进行维护。
11-6:正式版本上软件的任何修改都应有详细的文档记录。
11-7:发现错误立即修改,并且要记录下来。
11-8:关键的代码在汇编级跟踪。
11-9:仔细设计并分析测试用例,使测试用例覆盖尽可能多的情况,以提高测试用例的效率。
11-10:尽可能模拟出程序的各种出错情况,对出错处理代码进行充分的测试。
11-11:仔细测试代码处理数据、变量的边界情况。
11-12:保留测试信息,以便分析、总结经验及进行更充分的测试。
11-13:不应通过“试”来解决问题,应寻找问题的根本原因。
11-14:对自动消失的错误进行分析,搞清楚错误是如何消失的。
11-15:修改错误不仅要治表,更要治本。
11-16:测试时应设法使很少发生的事件经常发生。
11-17:明确模块或函数处理哪些事件,并使它们经常发生。
11-18: 坚持在编码阶段就对代码进行彻底的单元测试,不要等以后的测试工作来发现问题。
11-19:去除代码运行的随机性(如去掉无用的数据、代码及尽可能防止并注意函数中的“内部寄存器”等),让函数运行的结果可预测,并使出现的错误可再现。
12 .宏
12-1:用宏定义表达式时,要使用完备的括号。
12-2:将宏所定义的多条表达式放在大括号中。
12-3:使用宏时,不允许参数发生变化。
java
1.排版
1-1程序块要采用缩进风格编写,缩进的空格数为4个。 
1-2分界符(如大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类和接口的定义、以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。
1-3较长的语句、表达式或参数(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。
1-4不允许把多个短语句写在一行中,即一行只写一条语句 
1-5if, for, do, while, case, switch,default 等语句自占一行,且if,for, do, while等语句的执行语句无论多少都要加括号{}。 
1-6相对独立的程序块之间、变量说明之后必须加空行。
1-7对齐只使用空格键,不使用TAB键。
1-8在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如.),后不应加空格。
2.注释规范
2-1.一般情况下,源程序有效注释量必须在30%以上。 
2-2.包的注释:包的注释写入一个名为 package.html 的HTML格式的说明文件放入当前路径。
2-3.包的注释内容:简述本包的作用、详细描述本包的内容、产品模块名称和版本、公司版权。 
2-4.文件注释:文件注释写入文件头部,包名之前的位置。
2-5.文件注释内容:版权说明、描述信息、生成日期、修改历史。 
2-6.类和接口的注释:该注释放在 package 关键字之后,class 或者 interface 关键字之前。
2-7.类和接口的注释内容:类的注释主要是一句话功能简述、功能详细描述,
2-8.类属性、公有和保护方法注释:写在类属性、公有和保护方法上面。
2-9. 成员变量注释内容:成员变量的意义、目的、功能,可能被用到的地方。
2-10.公有和保护方法注释内容:列出方法的一句话功能简述、功能
2-11.对于方法内部用throw语句抛出的异常,必须在方法的注释中标明,对于所调用的其他方法所抛出的异常,选择主要的在注释中说明。 对于非RuntimeException,即throws子句声明会抛出的异常,必须在方法的注释中标明。 
2-12.注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。 
2-13.注释与所描述内容进行同样的缩排。 
2-14.将注释与其上面的代码用空行隔开。 
2-15.对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。 
2-16.对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,必须在该case语句处理完、下一个case语句前加上明确的注释。 
2-17.边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。 
2-18.注释的内容要清楚、明了,含义准确,防止注释二义性。 
2-19.避免在注释中使用缩写,特别是不常用缩写。详细描述、输入参数、输出参数、返回值、违例等。
3.命名规范 
3-1.包名采用域后缀倒置的加上自定义的包名,采用小写字母。在部门内部应该规划好包名的范围,防止产生冲突。部门内部产品使用部门的名称加上模块名称。产品线的产品使用产品的名称加上模块的名称。 
3-2.类名和接口使用类意义完整的英文描述,每个英文单词的首字母使用大写、其余字母使用小写的大小写混合法。 
3-3.方法名使用类意义完整的英文描述:第一个单词的字母使用小写、剩余单词首字母大写其余字母小写的大小写混合法。 
3-4.方法中,存取属性的方法采用setter 和 getter方法,动作方法采用动词和动宾结构。
3-5.属性名使用意义完整的英文描述:第一个单词的字母使用小写、剩余单词首字母大写其余字母小写的大小写混合法。属性名不能与方法名相同。 
3-6.常量名使用全大写的英文描述,英文单词之间用下划线分隔开,并且使用 final static 修饰。 
3-7.属性名可以和公有方法参数相同,不能和局部变量相同,引用非静态成员变量时使用 this 引用,引用静态成员变量时使用类名引用。
4.编码规范
4-1.明确方法功能,精确(而不是近似)地实现方法设计。一个函数仅完成一件功能,即使简单功能也应该编写方法实现。 
4-2.应明确规定对接口方法参数的合法性检查应由方法的调用者负责还是由接口方法本身负责,缺省是由方法调用者负责。
4-3.明确类的功能,精确(而不是近似)地实现类的设计。一个类仅实现一组相近的功能。  
4-4.所有的数据类必须重载toString() 方法,返回该类有意义的内容。
4-5.数据库操作、IO操作等需要使用结束close()的对象必须在try -catch-finally 的finally中close()。
4-6.异常捕获后,如果不对该异常进行处理,则应该纪录日志或者ex.printStackTrace() 。 
4-7.自己抛出的异常必须要填写详细的描述信息。
4-8.运行期异常使用RuntimeException的子类来表示,不用在可能抛出异常的方法声明上加throws子句。非运行期异常是从Exception继承而来的,必须在方法声明上加throws子句。 
4-9.在程序中使用异常处理还是使用错误返回码处理,根据是否有利于程序结构来确定,并且异常和错误码不应该混合使用,推荐使用异常。 
4-10.注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。
4-11.避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的静态变量来代替。 
4-12.数组声明的时候使用 int[] index ,而不要使用 int index[] 。 
4-13.调试代码的时候,不要使用 System.out 和 System.err 进行打印,应该使用一个包含统一开关的测试类进行统一打印。
4-14.用调测开关来切换软件的DEBUG版和正式版,而不要同时存在正式版本和DEBUG版本的不同源文件,以减少维护的难度。
5.JTEST规范
5-1.在switch 中每个 case 语句都应该包含 break 或者 return 。 
5-2.不要使用空的for 、if  、while 语句。 
5-3.在运算中不要减小数据的精度。 
5-4.switch 语句中的 case 关键字要和后面的常量保持一个空格,switch 语句中不要定义case 之外的无用标签。 
5-5.不要在if 语句中使用等号= 进行赋值操作。 
5-6.静态成员或者方法使用类名访问,不使用句柄访问。 
5-7.方法重载的时候,一定要注意方法名相同,避免类中使用两个非常相似的方法名。
5-8.不要在ComponentListener.componentResized() 方法中调用 serResize() 方法。 32 
5-9.不要覆盖父类的静态方法和私有方法。 
5-10.不要覆盖父类的属性。 
5-11.不要使用两级以上的内部类。 
5-12.把内部类定义成私有类。 
5-13.去掉接口中多余的定义(不使用 public, abstract, static, final 等,这是接口中默认的)。 
5-14.不要定义不会被用到的局部变量、类私有属性、类私有方法和方法参数。 
5-15.显式初始化所有的静态属性。 
5-16.不要使用 System.getenv() 方法。 
5-17.不要硬编码 ‘\n’和‘\r’作为换行符号。 
5-18.不要直接使用 java.awt.peer.* 里面的接口。 
5-19.使用 System.arraycopy() ,不使用循环来复制数组。 
5-20.避免不必要的 instanceof 比较运算和类造型运算。 
5-21.不要在 finalize() 方法中删除监听器(Listeners)。 
5-22.在 finalize() 方法中一定要调用 super.finalize() 方法。 
5-23.在 finalize() 方法中的 finally 中调用 super.finalize() 方法。 
5-24.进行字符转换的时候应该尽可能的较少临时变量。 
5-25.使用ObjectStream 的方法后,调用reset() ,释放对象。 
5-26.线程同步中,在循环里面使用条件测试(使用 while(isWait) wait() 代替 if(isWait) wait())。
5-27.不掉用 Thread 类的 resume(), suspend(), stop() 方法。 
5-28.减小单个方法的复杂度,使用的 if, while, for, switch 语句要在10个以内。
5-29.在Servlets中,重用JDBC连接的数据源。 
5-30.减少在Sevlets中使用的同步方法。 
5-31.不定义在包中没有被用到的友好属性、方法和类。 
5-32.没有子类的友好类应该定义成 final 。 
5-33.没有被覆盖的友好方法应该定义成 final
腾讯编码风格:
C/C++
1.程序的版式
1-1规则:程序块要采用缩进风格编写 :程序块要采用缩进风格编写,缩进的空格数为 ,缩进的空格数为4个。说明:由开发工具自动生成的代码可能不一致,但如果开发工具可以配置,则应该统一配 置缩进为 4个空格。
1-2规则:缩进或者对齐只能使用空格键 :缩进或者对齐只能使用空格键,不可使用 TAB 键。 说明 : 使用 TAB 键需要设置 TAB 键的空格数目是 4 格。
1-3 规则:相对独立的程序块之间 :相对独立的程序块之间、变量说明之后必须加空行 、变量说明之后必须加空行。 说明 :以下情况应该是用空行分开: 1)函数之间应该用空行分开; 2)变量声明应尽可能靠近第一次使用处,避免一次性声明一组没有马上使用的变量; 3)用空行将代码按照逻辑片断划分; 4)每个类声明之后应该加入空格同其他代码分开。
1-4 规则:较长的语句(>80 字符)要分成多行书写 )要分成多行书写。 说明: 以下情况应分多行书写: 1)长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行 要进行适当的缩进,使排版整齐,语句可读。 2)若函数或过程中的参数较长,则要进行适当的划分。 3)循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式 要在低优先级操作符处划分新行,操作符放在新行之首。
1-5 规则:不允许把多个短语句写在一行中 :不允许把多个短语句写在一行中,即一行只写一条语句 ,即一行只写一条语句。
1-6规则:if、for、do、while、case、switch、default default default 等语句自占一行 等语句自占一行,且 if、for、 do、while 等语句的执行语句部分无论多少都要加括号 等语句的执行语句部分无论多少都要加括号{}。
1-7 规则:代码行之内应该留有适当的空格 :代码行之内应该留有适当的空格 说明: 采用这种松散方式编写代码的目的是使代码更加清晰。代码行内应该适当的使用空 格, 具体如下: 1)关键字之后要留空格。像 const、virtual、inline、case 等关键字之后至少要留一 个空格, 否则无法辨析关键字。像if、for、while 等关键字之后应留一个空格再跟左 括号‘( ’,以突出关键字。 2)函数名之后不要留空格, 紧跟左括号’(’ , 以与关键字区别。 3)‘( ’ 向后紧跟,‘ )’、‘ ,’、‘ ;’ 向前紧跟, 紧跟处不留空格。 4)‘ ,’ 之后要留空格, 如 Function(x, y, z)。如果‘ ;’ 不是一行的结束符号。 5)值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符。二元操作符 的前后应当加空格。 6)一元操作符前后不加 空格。 7)像“[ ]”、“ .”、“ ->” 这类操作符前后不加空格。
1-8 建议:程序块的分界符 :程序块的分界符(如 C/C++语言的大括号‘{’和‘}’)应各独占一行并且 应各独占一行并且 位于同一列,同时与引用它们的语句左对齐 ,同时与引用它们的语句左对齐。在函数体的开始 。在函数体的开始、类的定义、结构的定义、 枚举的定义以及 if、for、do、while、switch、case 语句中的程序都要采用如上的缩 语句中的程序都要采用如上的缩进方式。
2.注释
2-1 规则:源文件头部应进行注释 :源文件头部应进行注释。
2-2 规则:函数头部应进行注释函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值等。
2-3 规则:注释应该和代码同时更新不再有用的注释要删除
2-4 规则:注释的内容要清楚 :注释的内容要清楚、明了,不能有二义性 ,不能有二义性。
2-5 建议:避免在注释中使用非常用的缩写或者术语。
2-6 建议:注释的主要目的应该是解释为什么这么做 :注释的主要目的应该是解释为什么这么做,而不是正在做什么
2-7 建议:避免非必要的注释 :避免非必要的注释
2-8 规则:注释的版式 说明:注释也需要与代码一样整齐排版 1)注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的 注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。 2)注释与所描述内容进行同样的缩排。 3)将注释与其上面的代码用空行隔开。 4)变量、常量、宏的注释应放在其上方相邻位置或右方。
2-9 规则:对于所有有物理含义的变量 :对于所有有物理含义的变量、常量,如果其命名不是充分自注释的 ,在声明时都必须加以注释,说明其物理含义 。
2-10 规则:数据结构声明 :数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释 如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置 。
2-11规则:注释不宜过多 :注释不宜过多,也不能太少,源程序中有效注释量控制在 ,源程序中有效注释量控制在 20%~30%之间。 说明: 注释是对代码的“提示”,而不是文档,不可喧宾夺主.
3标识符命名
3-1 命名尽量使用英文单词力求简单清楚,避免使用引起误解的词汇和模糊的缩写,使人产生误解。
3-2 命名规范必须与所使用的系统风格保持一致,并在同一项目中统一。 说明: 1)如在 UNIX 系统,可采用全小写加下划线的风格或大小写混排的方式,但不能使 用大小写与下划线混排的方式。 2)用作特殊标识如标识成员变量或全局变量的 m_和 g_,其后加上大小写混排的方 式是允许的。
3-3建议变量的命名可参考“匈牙利”标记法
3-4宏和模板名采用全大写的方式,每个单词间用下划线分隔。
3-5枚举类型 enum 常量应以大写字母开头或全部大写
3-6 命名中若使用了特殊约定或缩写则要有注释说明。 说明: 应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进 行必要的注释说明。
3-7 规则:自己特有的命名风格 ,要自始至终保持一致不可来回变化。说明: 个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用
3-8 规则:对于变量命名,禁止取单个字符 ,建议除了要有具体含义 外,还能表明其变量类型、数据类型等,但 i、j、k 作局部循环变量是允许的 说明: 变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如 i 写成 j),而编译 时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。
3-9 建议:除非必要,不要用数字或较奇怪的字符来定义标识符。
3-10:类、结构、联合、枚举的命名须分别以 C、S、U、E 开头,其他部分遵从一 般变量命名规范
4.可读性
4-1用括号明确表达式的操作顺序避免使用默认优先级。 说明: 防止阅读程序时产生误解,防止因默认的优先级与设计思想不符而导致程序出错
4-2 建议:不要编写太复杂多用途的复合表达式。
4-3 规则:涉及物理状态或者含有物理意义的常量避免直接使用数字必须用有意义的枚举或常量来代替
4-4 规则:禁止使用难以理解,容易产生歧义的语句。
5.变量、结构
5-1 尽量少使用全局变量 尽量去掉没必要的公共变量。说明: 变量是增大模块间耦合的原因之一,故应减少没必要的公共变量以降低模块间的耦合度。
5-2 变量,特别是指针变量被创建之后应当及时把它们初始化以防止把未被 初始化的变量当成右值使用。 说明:在 C/C++中引用未经赋值的指针,经常会引起系统崩溃。
5-3 仔细设计结构中元素的布局与排列顺序使结构容易理解、节省占用空间并减少引起误用现象。 说明: 合理排列结构中元素顺序,可节省空间并增加可理解性。
5-4留心具体语言及编译器处理不同数据类型的原则及有关细节。 说明: 如在 C 语言中,static 局部变量将在内存“数据区”中生成,而非 static 局部变量将 在“堆栈”中生成。这些细节对程序质量的保证非常重要。
5-5尽量减少没有必要的数据类型默认转换与强制转换说明:当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化, 如下结构中的位域排列,将占较大空间,可读性也稍差
5-6 规则当声明用于分布式环境或不同 CPU 间通信环境的数据结构时 CPU 间通信环境的数据结构时必须考虑机器的字节顺序、使用的位域及字节对齐等问题
6.函数、过程
6-1调用函数要检查所有可能的返回情况不应该的返回情况要用 ASSERT 来确认。
6-2编写可重入函数时,应注意局部变量的使用(如编写 C/C++语言的可重入函 C/C++语言的可重入函数时,应使用 auto 即缺省态局部变量或寄存器变量 auto 即缺省态局部变量或寄存器变量)。
6-3调用公共接口函数时,调用者有保障调用参数符合要求的义务。
6-4 建议:函数的规模尽量限制在 100 行以内。
6-5 一个函数仅完成一件功能。 说明多功能集于一身的函数,很可能使函数的理解、测试、维护等变得困难。
6-6不能用ASSERT 代替必要的安全处理代码,确保发布版的程序也能够合理地处 ,确保发布版的程序也能够合理地处理异常情况
6-7 尽量写类的构造、拷贝构造、析构和赋值函数 析构和赋值函数,而不使用系统缺省的 。 说明: 编译器以“位拷贝”的方式自动生成缺省的拷贝构造函数和赋值函数 ,倘若类中含 有指针变量,那么这两个缺省的函数就隐含了错误。
6-8对于不需要拷贝构造函数时,应显式地禁止它,避免编译器生成默认的拷贝构造函数。 6-9谨慎使用与程序运行的环境相关的系统函数
6-10 禁止编写依赖于其他函数内部实现的函数。 说明: 此条为函数独立性的基本要求。由于目前大部分高级语言都是结构化的
6-11检查函数所有参数与非参数的有效性。 说明: 1)函数的输入主要有两种:一种是参数输入;另一种是全局变量、数据文件的输入,即非参数输入。函数在使用输入之前,应进行必要的检查。 2)不应该的入口情况要用 ASSERT 来确认。 3)有时候不处理也是一种处理,但要明确哪些情况不处理。try…catch 是一种常 用的不处理的处理手段。
6-12 函数实现中不改变内容的参数要定义成 const。
7.C++专用规范
7-1在高警告级别下干净地编译使用编译器的最高警告级别。
7-2确保资源为对象所占有,使用显式的 RAII 和智能指针 RAII 和智能指针。 C++在语言层面强制的构造/析构恰好与资源获取/释放这对函数相对应,在处理需要 调用成对的获取/释放函数的资源时,应将该资源封装在对象中,并在对象的析构函数中 释放该资源,这样就保证了获取/释放的匹配指针
7-3主动使用 const,避免使用宏.应该尽可能的使用常量而不用变量,另外在定义数值的时候,应该把 const 做为默 认的选项。
7-4 合理使用组合(composition)和继承(inheritance)。继承是 C++中耦合度最强的关系之一。软件工程的一条重要原则是尽量减少耦合,在 组合和继承都能均可适用的情况下,应该优先考虑使用组合。组合的意思是将一种类型 以成员变量方式嵌入相关类型中。组合有如下优点: 1)在不影响调用代码的同时也更灵活。 2)编译期绝缘性好,编译时间也能缩短。 3)代码不可预测程度降低(有些类不适合作为基类)
7-5尽可能局部地声明每个变量,这通常是在程序具备了足够的数据来初始化变量之后, 并紧接着首次使用该变量之前
7-6 通过值指针,或引用适当地取得参数对仅用于输入的参数来说: 1)始终给仅用于输入的指针或引用参数加上 const 限定符。 2)最好是通过原始类型(例如:char,float)和可以通过值来复制并且复制成本 低的值对象(例如:Point,complex)来取得参数。 3)对其它自定义类型的输入,最好是通过 const 引用来取得。 4)如果函数需要参数的复本,那么可以考虑用传递值来代替传递引用
7-7 不要在头文件中定义具有链接属性的实体重复导致膨胀包括名字空间层级的变量或函数,需要占用内存。把此类实 体定义在头文件中会导致编译错误或内存浪费。应该把具有链接属性的实体放在实现文 件中。
7-8 与错误码相比,要尽量用异常来报告错误。对一些无法使用异常的错误,或者一些 不属于错误的情况,可以用状态码(status code,例如:返回码,errno)来报告。如 果不可能或不需要从错误中恢复,那么可以使用其它方法,比如正常或非正常地终止程 序。 在 C++中,和用错误码来报告错误相比,用异常来报告错误具有许多明显的优势,所 有这些都使得编出来的代码更健壮.
java
1 .缩进 
1-1程序块要采用缩进风格编写,缩进只使用TAB键,不能使用空格键(编辑器中请将,TAB设置为4格); 
1-2方法体的开始、类的定义、以及if、for、do、while、switch、case语句中的代码都
要采用缩进方式;
2.对齐 
2-1程序块的分界符左大括号”{” 和右大括号”}”都另起一行,应各独占一行并且位于同
一列,同时与引用它们的语句左对齐;
2-2对齐只使用TAB键,不使用空格键; 
2-3不允许把多个短语句写在一行中,即一行只写一条语句;
2-4 if、for、do、while、case、switch、default等语句自占一行。
3.换行 
一行的长度超过80个字符需要换行,换行规则如下:
3-1在一个逗号后面断开;
3-2在一个操作符前面断开; 
3-3长表达式要在低优先级操作符处划分新行;
3-4新行缩进2个TAB。
4.间隔 
4-1类、方法及相对独立的程序块之间、变量说明之后必须加空行; 
4-2关键字之后要留空格, 象if、for、while  等关键字之后应留一个空格再跟左括号”(”, 以突出关键字; 
4-3方法名与其左括号”(”之间不要留空格, 以与关键字区别; 
4-4二元操作符如 ” =”、” +=”  ” >=”、” <=”、” +”、*”、” %”、”&&”、” ||”、” << ,” ^” 等的前后应当加空格; 
4-5一元操作符如” !”” ~”、”++”、” –”等前后不加空格;
4-6象”[ ]”、” .” 这类操作符前后不加空格;
4-7 for语句中的表达式应该被空格分开,如:   
4-8强制转型后应该跟一个空格,如: 
5.注释
5-1 文件注释:所有的源文件都应该在开头有一个注释,其中列出文件的版权声明、文件名、功能描述以及创建、修改记录:     
5.2 类或接口注释 
采用JavaDoc文档注释,在类、接口定义之前应当对其进行注释,包括类、接口的描述、最新修改者、版本号、参考链接等:注:JavaDoc文档注释:描述Java的类、接口、构造方法、方法、以及字段。每个文档注释都被置于注释定界符/…*/之中,一个注释对应一个类、接口或成员。该注释应位于声明之前。文档注释的第一行(/)不需缩进,随后的文档注释每行都缩进1格(使星号纵向对齐)。
5-3 字段注释:采用JavaDoc文档注释,定义为public的字段必需给出注释,在类的(静态)
变量、实例变量定义之前当对其进行注释,给出该字段的描述等.  
5-4方法注释  采用JavaDoc文档注释,在方法定义之前当对其进行注释,包括方法的描述、输入、输出及返回值说明、抛出异常说明、参考链接等:   
5-5 其它注释(非文档注释):单行代码注释一律使用注释界定符
6.命名
6-1 基本规则:使用可以准确说明变量、字段、类、接口、包等完整的英文描述符;采用大小写混合,提高名字的可读性;采用该领域的术语;尽量少用缩写,但如果一定要使用,当使用公共缩写和习惯缩写等;避免使用相似或者仅在大小写上有区别的名字。
6-2 包命名:包名一律小写, 少用缩写和长名;采用以下规则:[基本包].[项目名].[模块名子模块名]..基本包:com.tencent或 com.qq;不得将类直接定义在基本包下,所有项目中的类、接口等都应当定义在各自的项目 和模块包中; 
6-3 类或接口命名:类或接口名是个一名词,采用大小写混合的方式,每个单词的首字母大写。尽量使你的类名简洁而富于描述。使用完整单词,避免用缩写词(除非该缩写词被更广泛使用.
6-4变量命名:采用大小写混合的方式,第一个单词的首字母小写,其后单词的首字母大写;变量名不应以下划线或美元符号开头;尽量避免单个字符的变量名,除非是一次性的临时变量。临时变量通常被取名为i,j,对不易清楚识别出该变量类型的变量应使用类型名或类型
名缩写作其后缀;组件或部件变量使用其类型名或类型名缩写作其后缀;集合类型变量,例如数组和矢量,应采用复数命名或使用表示该集合的名词做后缀: 
6-5 常量命名:全部采用大写,单词间用下划线隔开. 
6-6 方法命名  方法名是一个动词,采用大小写混合的方式,第一个单词的首字母小写,其后单词的首字母大写;取值类可使用get前缀,设值类可使用set前缀,判断类可使用is(has)前缀。
7.声明
7-1类或接口声明  类、接口定义语法规范: 
7-2方法声明:良好的程序设计应该尽可能减小类与类之间耦合,所遵循的经验法则是:尽量限制成员函数的可见性。如果成员函数没必要公有 (public),就定义为保护 (protected);没必要保护 (protected),就定义为私有 (private);方法定义语法规范:[可见性][‘abstract’] [‘static’] [‘final’][‘synchronized’][返回值类型]method_name(参数列表)[(‘throws’)][异常列表];声明顺序:构造方法静态公共方法静态私有方法 公共方法 友元方法 受保护方法 私有方法main方法;方法参数建议顺序:(被操作者,操作内容,操作标志,其他)
7-3变量声明:一行一个声明;声明局部变量的同时初始化(在变量的初始值依赖于某些先前发生的计算的特殊情况下可以不用同时初始化);只在代码块的开始处声明变量,(一个块是指任何被包含在大括号”{“和”}”中间的代码)不要在首次用到该变量时才声明;避免声明的局部变量覆盖上一级声明的变量,即不要在内部代码块中声明相同的变量名;公共和保护的可见性应当尽量避免,所有的字段都建议置为私有,由获取和设置成员函数(Getter、Setter)访问定义一个变量或者常量的时候,不要包含包名(类似java.security.MessageDigestdigest =null),而要定义成下面的格式,除非是两个包有相同的类名字段定义语法规范:  数组声明时应当将”[]”跟在类型后,而不是字段名后:声明顺序:常量 类变量 实例变量: 公有字段  受保护字段 友元字段 私有字段   
8.异常
8-1捕捉异常的目的是为了处理它。 
8-2多个异常应分别捕捉并处理,避免使用一个单一的catch来处理。
9.习惯 
9-1 if、for、do、while等语句的执行语句部分无论多少都要加括号”{}”; 
9-2每当一个case顺着往下执行时(因为没有break语句),通常应在break
语句的位置添加注释; 
9-3尽量避免在循环中构造和释放对象; 
9-4在使用局部变量的过程,按就近原则处理。不允许定义一个局部变量,然后在很远的地方才使用;
9-5相同的功能不允许复制成N份代码;
9-6在处理 String 的时候要尽量使用 StringBuffer 类。
百度编码风格:
Java
1.代码书写
1-1程序块要采用K&R代码风格编写,缩进的空格数为4个, 不能使用Tab说明:不同的缩进风格对代码的可读性影响很大,以tab为缩进单位在不同的tab step下可读性也相差很多,所以将缩进定为一个soft tab即4个空格,这样在所有环境下缩进都会保持一致。
1-2if、while、for、do语句的执行体总是用”{“和”}”括起来,即使单条语句也是并且在较长(超过一屏)的判断或者循环语句的结尾应该有注释语句做出标识。
1-3每行仅包含一条语句.说明: 这样做可读性更好。
2.命名要求
2-1Package 的名字应该都是由一个小写单词组成
2-2类(class)命名规则:类名是个一名词,大写开始,采用骆峰命名规则。使用完整单词,避免缩写词
2-3参数和变量的名字必须用一个小写字母开头,后面的单词用大写字母开头, 只允许使用字母和数字, 使用骆峰命名方式常量和枚举的属性必须全部使用大写,并且使用完整含义的单词,每个单词之间使用“_”分割
3.注释
3-1要求类、接口、公有方法都必须添加注释类、接口的注释, 说明该类或者接口的主要作用。
3-2方法注释采用标准的javadoc注释规范,注释中必须提供方法说明,参数说明和返回值和异常说明
4.常量与变量
4-1具有全局性逻辑功能的常量值需要定义为常量类型且相同含义的常量只能定义在一处。一行一个声明,避免在一个语句中给多个变量赋值。只在代码块的开始处声明变量,内外层的代码声明不要重名。
4-2对于固定且编译时可列的对象,如Status,Type等,应采用enum而非自定义常量实现。enum的好处是类型更清楚,不会在编译时混淆
5.空格
5-1一个紧跟着括号的关键字应该用空格分开
5-2空格应该位于参数列表中逗号的后面
5-3所有的二元运算符,除了”.”,都必须用空格与操作数分开
5-4for语句中的表达式应该被空格分开强制转型后应该跟一个空格
6.方法
6-1方法行数不能超过500行, 类的行数不能超过3000
6-2方法的参数个数不能超过7个参数过多但导致方法的使用和理解上增加难度,也会导致使用量容易弄混顺序。针对需要使用到过多参数时,可以抽取对象方式进行传递。
6-3方法内调用的嵌套不能超过5层过多的嵌套会加大代码阅读的难度,
6-4判断方法入口参数的合法性,特别是public,一定要检查入口参数是否合法。不要在方法中对方法的参数进行赋值。
6-5方法返回值,不能返回null;除非需要通过null表达特殊含义,同时必须在方法注释中加说明。返回布尔值的方法,需要以is打头。
6-6不用的方法直接删除,不建议使用的方法加Deprecated进行保留。
7.编码规则
7-1尽量使用接口而不是一个具体的类。
7-2异常捕获后必须处理,不能吃掉异常同一个异常,只在一处打印,log时需要打印异常的stack trace
7-3为了避免重复打印相同的异常日志,同一个异常,只在一处打印
7-4未使用的import和变量必须删除
7-5使用一个由其他方法返回的对象之前,先判断是否为null,以免产生NullPointerException 异常
7-6字符串比较时,将常量置于equals之前,避免null异常。
7-7如果涉及10个以上字符串的拼接,应该使用StringBuffer 或 StringBuilder,避免使用“+”号拼接产生大量中间对象线程上下文ThreadLocal变量的使用必须配必须手动清除,否则可能导致脏数据、内存溢出等问题。
7-8防止下标越界,在使用数组下标之前先判断下标的合法性,比如数组类型,集合类型。8.多线程并发
8-1对重要业务对象,需要防止对过时数据的修改
8-2对资源加锁时必须保证一致的加锁顺序,否则可能导致死锁。
8-3如果使用了静态工具类或单例,必须确保是线程安全的。Jdk自带的一些工具类也未必线程安全,比如DateFormat,每次请求使用时必须重新构造
8-4避免直接使用Thread,建议使用Concurrent包。
个人编码模板
1、代码的可读性至上
代码要能可阅读和可理解,就需要格式化成一致的方式。对函数和变量的命名应有意义,注释的表达应该简洁而准确。并且,准确地记录代码中所有棘手的部分是十分重要的。你必须清楚软件程序为什么能工作以及为什么能在所有可能的情况下顺利工作的原因。
2、 遵循正确的命名约定
当需要给类、函数和变量命名时,需要遵循以下指南:
1)、确保特定类名的第一个字母大写;
2)、使用大小写分离多个单词的命名;
3)、大写常数名,并使用下划线分离单词;
4)、确保特定功能和变量名的第一个字母小写;
5)、注意正确使用缩写。例如,用max而不用maximum。
3、必要时可使用空格
虽然空格对编译器是没有意义的,但是可用于提高代码的可读性。举个例子,你可以在函数间留三个空行。你还可以在函数内使用单独的空行用于分离关键的代码段。
4、确保代码有一定的可维护性
我们需要确保写出来的代码,换成另一个程序员来调整功能、修复bug,也是明确易懂的。要将函数中关键值用常量来标记,这样我们就可以随时根据需要来改变这些常量值。总而言之,代码必须坚固,能够处理任何类型的输入,然后在不崩溃的前提下,提供预期结果。
5、注释必须易于理解
注释应该是有意义的,能够清晰地解释所有关于软件程序的内容。注释的数量多少无所谓,质量才是关键。你需要使用/ 注释 /的风格来写注释,以确保位于每个源文件的顶部。此外,你也可以选择在注释中包括你的名字,编写代码的日期,以及简明扼要地说明程序的实际用途。不过,你可以选择省略一些功能明显的注释。你需要遵循的行内注释格式为//注释。
6、正确使用函数
每一个函数所包含的代码片段,必须既短又能够完成特定的任务。不妨将函数当作是“黑盒子”——独立,又可以有效处理任何类型的输入。不要忘记这样一条经验规则——即所谓的“Ten Line Rule”,也就是说,一个函数,通常说来,如果超过10行,那就需要以最精炼的方式去简化。并且,任何重复性的代码片段都应该被设置为一个单独的函数。上述做法不但可缩短程序的长度,还能大大提高其可读性。
7、整体的代码缩进
缩进在软件程序的流程控制上起着至关重要的作用。每一个新的while、for、if语句,以及switch结构,都需要缩进代码。这也可用于一行语句中括号已被省去的情况。例如,假设有if语句,那么相应else语句必须一齐缩进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值