您的位置:首页 > 其它

编码规范(华为)

2016-07-23 23:54 239 查看
高质量的代码需要注意以下几点:

1 排版

2 注释

3 标识符命名

4 可读性

5 变量、结构

6 函数、过程

7 可测性

8 程序效率

9 质量保证

10 代码编辑、编译、审查

11 代码测试、维护

12  宏

 

 

 

 

一.排版

1.   程序块要采用缩进风格编写,缩进的空格数为4个,函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格,case语句下的情况处理语句也要遵从语句缩进要求;对齐只使用空格键,不使用TAB键。

2.   相对独立的程序块之间、变量说明之后必须加空行。

3.   一行程序以小于80字符为宜,不要写得过长。较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。

4.   循环、判断等语句中若有较长的表达式或语句;函数或过程中的参数较长;则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。

5.   不允许把多个短语句写在一行中,即一行只写一条语句。

6.   if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}。

7.   程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。

8.   在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。

 

二.注释

1.   一般情况下,源程序有效注释量必须在20%以上。

2.   说明性文件(如头文件.h文件、.inc文件、.def文件、编译说明文件.cfg等)头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者、内容、功能、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。

3.   源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。

4.   函数头部应进行注释,列出:函数的目的/功能、输入参数、输出函数、返回值、调用关系(函数、表)等。

5.   边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。

6.   注释的内容要清楚、明了,含义准确,防止注释二义性。

7.   避免在注释中使用缩写。

8.   注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。

9.   对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或右方。

10.  数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。

11.  全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。

12.  注释与所描述内容进行同样的编排。

13.  将注释与其上面的代码用空行隔开。

14.  对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。

15.  对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,必须在该case语句处理完,下一个case语句前加上明确的注释。

16.  避免在一行代码或表达式的中间插入注释。

17.  通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的。

18.  在代码的功能、意图层次上进行注释,提供有用、额外的信息。

19.  在程序块的结束行右方加注释标记,以表明某程序块的结束。

20. 注释格式尽量统一,建议使用“/* …… */”。

21.  注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。

 

三. 标识符命名

1.   标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。

2.   命名中若使用特殊约定或缩写,则要有注释说明。

3.   自己特有的命名风格,要自始至终保持一致,不可来回变化。

4.   对于变量命名,禁止取单个字符(如i、j、k...),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k作局部循环变量是允许的。

5.   命名规范必须与所使用的系统风格保持一致,并在同一项目中统一,比如采用UNIX的全小写加下划线的风格或大小写混排的方式,不要使用大小写与下划线混排的方式,用作特殊标识如标识成员变量或全局变量的m_和g_,其后加上大小写混排的方式是允许的。

6.   除非必要,不要用数字或较奇怪的字符来定义标识符。

7.   正确的反义词组命名具有互斥意义的变量或相反动作的函数等。

8.   除了编译开关/头文件等特殊应用,应避免使用_EXAMPLE_TEST_之类以下划线开始和结尾的定义。

 

四. 可读性

1.   注意运算符的优先级,并用括号明确表达式的操作顺序,避免使用默认优先级。

2.   避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的枚举或宏来代替。

3.   源程序中关系较为紧密的代码应尽可能相邻。

4.   不要使用难懂的技巧性很高的语句,除非很有必要时。

 

五. 变量、结构

1.   去掉没必要的公共变量。

2.   仔细定义并明确公共变量的含义、作用、取值范围及公共变量间的关系。

3.   明确公共变量与操作此公共变量的函数或过程的关系,如访问、修改及创建等。

4.   当向公共变量传递数据时,要十分小心,防止赋与不合理的值或越界等现象发生。

5.   防止局部变量与公共变量同名。

6.   严禁使用未经初始化的变量作为右值。

7.   构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的公共变量,防止多个不同模块或函数都可以修改、创建同一公共变量的现象。

8.   使用严格形式定义的、可移植的数据类型,尽量不要使用与具体硬件或软件环境关系密切的变量。

9.   结构的功能要单一,是针对一种事务的抽象。

10.  不要设计面面俱到、非常灵活的数据结构。

11.  不同结构间的关系不要过于复杂。

12.  结构中元素的个数应适中。若结构中元素个数过多可考虑依据某种原则把元素组成不同的子结构,以减少原结构中元素的个数。

13.  仔细设计结构中元素的布局与排列顺序,使结构容易理解、节省占用空间,并减少引起误用现象。

14.  结构的设计要尽量考虑向前兼容和以后的版本升级,并为某些未来可能的应用保留余地(如预留一些空间等)。

15.  留心具体语言及编译器处理不同数据类型的原则及有关细节。

16.  编程时,要注意数据类型的强制转换;对编译系统默认的数据类型转换,也要有充分的认识;合理地设计数据并使用自定义数据类型,尽量减少没有必要的数据类型默认转换与强制转换。

17.  对自定义数据类型进行恰当命名,使它成为自描述性的,以提高代码可读性。注意其命名方式在同一产品中的统一。

18.  当声明用于分布式环境或不同CPU间通信环境的数据结构时,必须考虑机器的字节顺序、使用的位域及字节对齐等问题 。

 

六. 函数、过程

1.         对所调用函数的错误返回码要仔细、全面地处理。

2.         防止将函数的参数作为工作变量。

3.         函数的规模尽量限制在200行以内。

4.         一个函数仅完成一件功能。

5.         为简单功能编写函数。

6.         不要设计多用途面面俱到的函数。

7.         尽量不要编写依赖于其他函数内部实现的函数。

8.         避免设计多参数函数,不使用的参数从接口中去掉。

9.         检查函数所有参数输入的有效性。

10.     函数名应准确描述函数的功能。

11.     使用动宾词组为执行某操作的函数命名。如果是OOP方法,可以只有动词(名词是对象本身)。

12.     避免使用无意义或含义不清的动词为函数命名。

13.     函数的返回值要清楚、明了,让使用者不容易忽视错误情况。

14.     除非必要,最好不要把与函数返回值类型不同的变量,以编译系统默认的转换方式或强制的转换方式作为返回值返回。

15.     在调用函数填写参数时,应尽量减少没有必要的默认数据类型转换或强制数据类型转换。

16.     避免函数中不必要语句,防止程序中的垃圾代码。

17.     减少函数本身或函数间的递归调用。

18.     当一个过程(函数)中对较长变量(一般是结构的成员)有较多引用时,可以用一个意义相当的宏代替。

 

七. 可测性

1.   在同一项目组或产品组内,要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数,并且要有详细的说明。

2.   在同一项目组或产品组内,调测打印出的信息串的格式要有统一的形式。信息串中至少要有所在模块名(或源文件名)及行号。

3.   编程的同时要为单元测试选择恰当的测试点,并仔细构造测试代码、测试用例,同时给出明确的注释说明。测试代码部分应作为(模块中的)一个子模块,以方便测试代码在模块中的安装与拆卸(通过调测开关)。

4.   在进行集成测试/系统联调之前,要构造好测试环境、测试项目及测试用例,同时仔细分析并优化测试用例,以提高测试效率。

5.   使用断言来发现软件问题,提高代码可测性;用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况;用断言确认函数的参数;用断言保证没有定义的特性或功能不被使用;用断言对程序开发环境(OS/Compiler/Hardware)的假设进行检查。

6.   不能用断言来检查最终产品肯定会出现且必须处理的错误情况。

7.   对较复杂的断言加上明确的注释。

8.   正式软件产品中应把断言及其它调测代码去掉(即把有关的调测开关关掉)。

9.   在软件系统中设置与取消有关测试手段,不能对软件实现的功能等产生影响。

10. 用调测开关来切换软件的DEBUG版和正式版,而不要同时存在正式版本和DEBUG版本的不同源文件,以减少维护的难度。

11. 软件的DEBUG版本和发行版本应该统一维护,不允许分家,并且要时刻注意保证两个版本在实现功能上的一致性。

12. 在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码如打印函数等。

13. 调测开关应分为不同级别和类型。

14. 编写防错程序,然后在处理错误之后可用断言宣布发生错误。

 

八. 程序效率

1.   编程时要经常注意代码的效率。

2.   在保证软件系统的正确性、稳定性、可读性及可测性的前提下,提高代码效率。

3.   局部效率应为全局效率服务,不能因为提高局部效率而对全局效率造成影响。

4.   通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率;在保证程序质量的前提下,通过压缩代码量、去掉不必要代码以及减少不必要的局部和全局变量,来提高空间效率。

 

5.   循环体内工作量最小化。

6.   仔细分析有关算法,并进行优化。

7.   仔细考查、分析系统及模块处理输入(如事务、消息等)的方式,并加以改进。

8.   对模块中函数的划分及组织方式进行分析、优化,改进模块中函数的组织结构,提高程序效率。

9.   编程时,要随时留心代码效率;优化代码时,要考虑周全。

10. 不应花过多的时间拼命地提高调用不很频繁的函数代码效率。

11. 要仔细地构造或直接用汇编编写调用频繁或性能要求极高的函数。

12. 在多重循环中,应将最忙的循环放在最内层。

13. 尽量减少循环嵌套层次。

14. 避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。

15. 尽量用乘法或其它方法代替除法,特别是浮点运算中的除法。

16. 不要一味追求紧凑的代码。

 

九. 质量保证

1.   在软件设计过程中构筑软件质量。

2.   代码质量保证优先原则。

3.   只引用属于自己的存贮空间。

4.   防止引用已经释放的内存空间。

5.   过程/函数中分配的内存,在过程/函数退出之前要释放。

6.   过程/函数中申请的(为打开文件而使用的)文件句柄,在过程/函数退出之前要关闭。

7.   防止内存操作越界。

8.   认真处理程序所能遇到的各种出错情况。

9.   系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。

10. 系统运行之初,要对加载到系统中的数据进行一致性检查。

11. 严禁随意更改其它模块或系统的有关设置和配置。

12. 不能随意改变与其它模块的接口。

13. 充分了解系统的接口之后,再使用系统提供的功能。

14. 编程时,要防止差1错误。

15. 要时刻注意易混淆的操作符。当编完程序后,应从头至尾检查一遍这些操作符,以防止拼写错误。

16. 有可能的话,if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支。

17. Unix下,多线程的中的子线程退出必需采用主动退出方式,即子线程应return出口。

18. 不要滥用goto语句。

19. 不使用与硬件或操作系统关系很大的语句,而使用建议的标准语句,以提高软件的可移植性和可重用性。

20. 除非为了满足特殊需求,避免使用嵌入式汇编。

21. 精心地构造、划分子模块,并按“接口”部分及“内核”部分合理地组织子模块,以提高“内核”部分的可移植性和可重用性。

22. 精心构造算法,并对其性能、效率进行测试。

23. 对较关键的算法最好使用其它算法来确认。

24. 时刻注意表达式是否会上溢、下溢。

25. 使用变量时要注意其边界值的情况。

26. 留心程序机器码大小(如指令空间大小、数据空间大小、堆栈空间大小等)是否超出系统有关限制。

27. 为用户提供良好的接口界面,使用户能较充分地了解系统内部运行状态及有关系统出错情况。

28. 系统应具有一定的容错能力,对一些错误事件(如用户误操作等)能进行自动补救。

29. 对一些具有危险性的操作代码(如写硬盘、删数据等)要仔细考虑,防止对数据、硬件等的安全构成危害,以提高系统的安全性。

30. 资源文件(多语言版本支持),如果资源是对语言敏感的,应让该资源与源代码文件脱离,具体方法有下面几种:使用单独的资源文件、DLL文件或其它单独的描述文件(如数据库格式)

 

十. 代码编辑、编译、审查

1.   打开编译器的所有告警开关对程序进行编译。

2.   在产品软件(项目组)中,要统一编译开关选项。

3.   通过代码走读及审查方式对代码进行检查。

4.   测试部测试产品之前,应对代码进行抽查及评审。

5.   编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢失。

6.   同产品软件(项目组)内,最好使用相同的编辑器,并使用相同的设置选项。

7.   要小心地使用编辑器提供的块拷贝功能编程。

8.   合理地设计软件系统目录,方便开发人员使用。

9.   某些语句经编译后产生告警,但如果你认为它是正确的,那么应通过某种手段去掉告警信息。

10. 使用代码检查工具(如C语言用PC-Lint)对源程序检查。

11. 使用软件工具(如LogiSCOPE)进行代码审查。

十一.  代码测试、维护

1.   单元测试要求至少达到语句覆盖。

2.   单元测试开始要跟踪每一条语句,并观察数据流及变量的变化。

3.   清理、整理或优化后的代码要经过审查及测试。

4.   代码版本升级要经过严格测试。

5.   使用工具软件对代码版本进行维护。

6.   正式版本上软件的任何修改都应有详细的文档记录。

7.   发现错误立即修改,并且要记录下来。

8.   关键的代码在汇编级跟踪。

9.   仔细设计并分析测试用例,使测试用例覆盖尽可能多的情况,以提高测试用例的效率。

10. 尽可能模拟出程序的各种出错情况,对出错处理代码进行充分的测试。

11. 仔细测试代码处理数据、变量的边界情况。

12. 保留测试信息,以便分析、总结经验及进行更充分的测试。

13. 不应通过“试”来解决问题,应寻找问题的根本原因。

14. 对自动消失的错误进行分析,搞清楚错误是如何消失的。

15. 修改错误不仅要治表,更要治本。

16. 测试时应设法使很少发生的事件经常发生。

17. 明确模块或函数处理哪些事件,并使它们经常发生。

18. 坚持在编码阶段就对代码进行彻底的单元测试,不要等以后的测试工作来发现问题。

19. 去除代码运行的随机性(如去掉无用的数据、代码及尽可能防止并注意函数中的“内部寄存器”等),让函数运行的结果可预测,并使出现的错误可再现。

 

十二.  

1.   用宏定义表达式时,要使用完备的括号。

2.   将宏所定义的多条表达式放在大括号中。

3.   使用宏时,不允许参数发生变化。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: