Skip to main content

编写高质量程序的检查清单

Original Essay: http://cs.engr.uky.edu/~raphael/checklist.html, by Raphael Finkel, University of Kentucky

 

本检查清单应帮助您编写高质量的程序.
Raphael Finkel, 8/17/2005

  • 标识符:确保所有标识符都有意义.
    1. 一个字母的标识符几乎从不具有意义.
    2. 类似flagtemp的名称很少有意义。与其使用flag,不如考虑命名布尔条件,如valueFound.
    3. 考虑使用多词标识符,如nameIndex. 较长的标识符(在合理范围内)往往非常易读.
  • 裸文字:除了在定义常量时使用0和1以及除了""之外的字符串,避免在程序中使用数字和字符串.
    1. 不要将字面整数用作数组边界.
    2. 不要将字面整数用作运行参数,例如超时或端口号.
    3. 不要使用字面整数选择菜单条目.
    4. 不要使用字面整数测量字符串或某些数据的大小:在C和C++中使用sizeof()strlen(),在Java中使用.length().size.
    5. 不要将字面字符串用作文件名.尽管可以输出字面字符串.
    6. 不要将字面整数用于索引包含异构数据的数组.
    7. 不要使用表示字面量的名称声明标识符,如 "thirty".
  • 模块化:程序由相互作用的组件构建而成.
    1. 不要将所有代码放入main()函数中.
    2. 实际上,不要让任何函数承担太多工作.如果超过约50行,可能太长了.
    3. 如果你多次复制代码,请考虑是否使用循环更合适,或者可能是子程序.
    4. 如果发现自己缩进得很深,很可能是没有在需要的时候使用子程序.
    5. 不要重新发明库函数(除非任务需要).查阅手册了解如sprintf()atoi()等函数.
    6. 在C和C++中使用头文件(头文件名以.h结尾)定义所有需要在多个文件中使用的常量,并声明所有在文件之间导出的子程序。但不要将子程序的主体放在头文件中(内联子程序除外).
  • 格式化:程序应易于阅读.
    1. 参阅http://geosoft.no/development/javastyle.html以获取关于格式化和其他展示问题的明确建议。此参考资料专门针对Java,但对其他语言也有价值.
    2. 尽量将所有行限制在80个字符内;出于历史原因,许多人在80列窗口中查看代码.
    3. 不要同时使用制表符和空格进行缩进,因为并非所有文本编辑器都将制表符视为8个空格.
    4. 确实要遵循一种反映程序控制结构的一致的缩进模式.
    5. 不要在程序中放置许多空行。子程序之间一个空行就足够了.
    6. 不同的操作系统以不同的方式终止行。如果您在Win32(使用\r\n)、Unix(使用\n)和MacOS(使用\r)之间切换,请将文件重新格式化以使用一致的终止方法.
    7. 不要在源文件上设置可执行位(Unix).
  • 编码:您希望编码清晰、可维护且高效,按此顺序。这里的一些规则非常具体;其他规则更通用.
    1. 如果只有一个可以匹配的if语句,不要使用一系列没有else的if语句;使用else if.
    2. 当您需要对文本输入进行分类时,不要列举所有可能的第一个字符.
    3. 使用位移运算符而非乘法构建位模式.
    4. 在switch语句中,始终检查默认情况。同样,在一系列if-then-else语句中,使用最后一个else.
    5. 所有系统调用都可能失败。始终检查返回代码,并使用perror()报告失败.
    6. 布尔值应始终在Java中使用布尔类型,在C++中使用bool,在C中使用0/1整数。不要使用字符t和f,也不要使用-1和1.
    7. 如果可能的话,使用循环初始化数据结构.
    8. 每个变量和结构的每个字段只用于一个目的。除非有充分理由,否则不要重载它们.
    9. 不要为类型、变量和文件名使用相同的标识符,即使更改了大小写。这太令人困惑了.
    10. 如果您在网络传输之前使用htonl()或类似的程序修改数据,请勿直接修改数据。创建一个新的数据结构.
    11. 尽量不要使用全局或非局部变量。尽可能在最小范围内声明每个变量。非局部变量有合理的用途,但请确保您真正需要它们.
    12. Shell, Perl, 和Python程序的#! 行应作为文件的第一行;否则,该行仅作为注释.
    13. 尽量避免编写特殊情况。您通常可以使用伪数据或其他数据结构方法将特殊情况融入常规情况中.
  • 编译器:让它们帮助您发现错误。始终使用所有警告选项调用编译器.
    1. 对于C和C++,使用-Wall标志.
    2. 对于Java,使用-Xlint:all  -deprecation,并使用pmd程序获得更好的风格建议.
    3. 对于Python,使用-t  -W  all.
    4. 对于Perl,使用-w标志并指定use strict。Cgi-bin脚本还应具有-T标志.
  • make实用程序:使用它,并善于使用它.
    1. Makefile应始终具有一个"clean"配方,该配方应删除Makefile中其他配方可以重建的所有文件,包括对象和可执行文件.
    2. 如果项目具有多个源文件,Makefile应根据需要生成对象(.o)文件并将它们链接在一起.
    3. Makefile应编写得当,以便如果连续运行两次make,第二次运行不会重新编译.
    4. 每个配方都应创建其目标中指定的文件.
    5. 每个配方都应使用其先决条件列表中指定的所有文件.
    6. 学会使用类似.c.o的目标规则,以避免重复的makefiles.
    7. 如果只有一个C或C++源文件,可执行文件应具有相同的名称(不带.c.cpp扩展名).
    8. 确保在需要的地方将所有.h文件列为先决条件。可以考虑使用makedepend为您生成先决条件列表.
  • 文档:不仅仅是为了评分。在编写程序时,它还可以帮助您!
    1. 在编写程序时添加文档。随着设计的变化,您可以随时修改它.
    2. 编写外部文档:如何编译和运行程序以及程序的预期功能?外部文档通常在单独的README文件中;对于小项目,可以将其作为单个源文件中的注释.
    3. 包含内部文档:您使用了哪些算法和数据结构?概述可以在单独的README文件中,但通常将内部文档放在描述特定例程、声明和步骤的位置.
    4. 检查整个程序和文档中的拼写错误。提交拼写错误的工作是不礼貌的,表明对细节的疏忽.
    5. 检查所有文档(和输出消息)中的语法错误.
    6. 如果在关闭括号上放一个简短的注释,程序会更易读。例如,可以在结束条件的括号上加上一个注释,如"if value looks good"。在结束循环的括号上可以加上一个注释,如"for each input line"。结束一个过程的括号上可以加上一个注释,只是给出过程的名称。结束一个类的括号上可以有一个注释,说"类"然后是类的名称.