《mfc开发编程规范》由会员分享,可在线阅读,更多相关《mfc开发编程规范(28页珍藏版)》请在金锄头文库上搜索。
1、MFC开发编程规范 *软件公司软件开发规范 (试行版) 在公司团队协作开发的情况下,编程时应该强调的一个重要方面是程序 的易读性,在保证软件的速度等性能指标能满足用户需求的情况下,能 让其他程序员容易读懂你的程序。一套鲜明的编程风格,可以让协作 者、后继者和自己一目了然,在很短的时间内看清程序的结构,理解设 计的思路。大大的提高代码的可读性、可重用性、程序健壮性、可移植 性和可维护性。 制定本编程规范的目的是为了提高公司的软件开发效率及所开发的软件 的可维护性,提高软件的质量。本规范由程序风格、命名规则、注释规 范、程序健壮性、可移植性、错误处理以及软件的模块化规范等部分组 成。 一、程序风格
2、: 1、严格采用阶梯层次组织程序代码: 各层次缩进的分格采用VC的缺省风格,即每层次缩进为4格,括号位于 下一行。要求相匹配的大括号在同一列,对继行则要求再缩进4格。例 如: void main() long lI; /循环变量 long lSum;/用来记录和 float fAvg;/用来求平均值 /对数进行累加。 for( lI=0;lI class CcmTVector3d public: TYPE x,y,z; ; 、对常量(包括错误的编码)命名,要求常量名用大写,常量名用英 文表达其意思。 如:#define CM_FILE_NOT_FOUND CMMAKEHR(0X20B) 其中C
3、M表 示类别。 、对const 的变量要求在变量的命名规则前加入c_,即:c_+变量命名 规则;例如: const char* c_szFileName; 2、 函数的命名规范: 函数的命名应该尽量用英文表达出函数完成的功能。遵循动宾结构的命 名法则,函数名中动词在前,并在命名前加入函数的前缀,函数名的长 度不得少于8个字母。 例如: long cmGetDeviceCount(); 3、函数参数规范: 、 参数名称的命名参照变量命名规范。 、 为了提高程序的运行效率,减少参数占用的堆栈,传递大结构的 参数,一律采用指针或引用方式传递。 、 为了便于其他程序员识别某个指针参数是入口参数还是出口
4、参 数,同时便于编译器检查错误,应该在入口参数前加入const标志。 如: cmCopyString(const char * c_szSource, char * szDest) 4、引出函数规范: 对于从动态库引出作为二次开发函数公开的函数,为了能 与其他函数 以及Windows的函数区分,采用类别前缀+基本命名规则的方法命名。 例如:在对动态库中引出的一个图象编辑的函数定义为 imgFunctionname(其中img为image缩写)。 现给出三种库的命名前缀: 、 对通用函数库,采用cm为前缀。 、 对三维函数库,采用vr为前缀。 、 对图象函数库,采用img为前缀。 对宏定义,结果
5、代码用同样的前缀。 5、文件名(包括动态库、组件、控件、工程文件等)的命名规范: 文件名的命名要求表达出文件的内容,要求文件名的长度不得少于5个 字母,严禁使用象file1,myfile之类的文件名。 三、注释规范: 1、函数头的注释 对于函数,应该从“功能”,“参数”,“返回值”、“主要思路”、“调用方 法”、“日期”六个方面用如下格式注释: /程序说明开始 /=/ / 功能: 从一个String 中删除另一个String。 / 参数: strByDelete,strToDelete / (入口) strByDelete: 被删除的字符串(原来的字符串) / (出口) strToDelete
6、: 要从上个字符串中删除的字符串。 / 返回: 找到并删除返回1,否则返回0。(对返回值有错误编码的要/ 求列出错误编码)。 / 主要思路:本算法主要采用循环比较的方法来从strByDelete中找到 / 与strToDelete相匹配的字符串,对多匹配strByDelete / 中有多个strToDelete子串)的情况没有处理。请参阅: / 书名 / 调用方法: / 日期:起始日期,如:2000/8/21.9:40-2000/8/23.21:45 /=/ 函数名() /程序说明结束 、 对于某些函数,其部分参数为传入值,而部分参数为传出值,所 以对参数要详细说明该参数是入口参数,还是出口参
7、数,对于某些意义 不明确的参数还要做详细说明(例如:以角度作为参数时,要说明该角 度参数是以弧度(PI),还是以度为单位),对既是入口又是出口的变量 应该在入口和出口处同时标明。等等。 、 函数的注释应该放置在函数的头文件中,在实现文件中的该函数 的实现部分应该同时放置该注释。 、 在注释中应该详细说明函数的主要实现思路、特别要注明自己的 一些想法,如果有必要则应该写明对想法产生的来由。对一些模仿的函 数应该注释上函数的出处。 、 在注释中详细注明函数的适当调用方法,对于返回值的处理方法 等。在注释中要强调调用时的危险方面,可能出错的地方。 、 对日期的注释要求记录从开始写函数到结束函数的测试
8、之间的日 期。 、 对函数注释开始到函数命名之间应该有一组用来标识的特殊字符 串。 如果算法比较复杂,或算法中的变量定义与位置有关,则要求对变量的 定义进行图解。对难以理解的算法能图解尽量图解。 2、变量的注释: 对于变量的注释紧跟在变量的后面说明变量的作用。原则上对于每个变 量应该注释,但对于意义非常明显的变量,如:i,j等循环变量可以不注 释。 例如: long lLineCount /线的根数。 3、文件的注释: 文件应该在文件开头加入以下注释: / / 工程: 文件所在的项目名。 / 作者:*,修改者:* / 描述:说明文件的功能。 / 主要函数: / 版本: 说明文件的版本,完成日期
9、。 / 修改: 说明对文件的修改内容、修改原因以及修改日期。 / 参考文献: / 为了头文件被重复包含要求对头文件进行定义如下: #ifndef _FILENAME_H_ #define _FILENAME_H_ 其中FILENAME为头文件的名字。 4、其他注释: 在函数内我们不需要注释每一行语句。但必须在各功能模块的每一主要 部分之前添加块注释,注释每一组语句,在循环、流程的各分支等,尽 可能多加以注释。 其中的循环、条件、选择等位置必须注释。 对于前后顺序不能颠倒的情况,建议在注释中增加序号。 例如: /1、注释 for () if() /注释 else /注释 /注释 switch()
10、 case: / 注释 case: / 注释 default: /注释 在其他顺序执行的程序中,每隔3-5行语句,必须加一个注释,注明这 一段语句所组成的小模块的作用。对于自己的一些比较独特的思想要求 在注释中标明。 四、程序健壮性: 1、函数的返回值规范: 对于函数的返回位置,尽量保持单一性,即一个函数尽量做到只有一个 返回位置。(单入口单出口)。 要求大家统一函数的返回值,所有的函数的返回值都将以编码的方式返 回。 例如编码定义如下: #define CM_POINT_IS_NULL CMMAKEHR(0X200) : : 建议函数实现如下: long 函数名(参数,) long lRes
11、ult; /保持错误号 lResult=CM_OK; /如果参数有错误则返回错误号 if(参数=NULL) lResult=CM_POINT_IS_NULL; goto END; END: return lResult; 2、关于goto的应用: 对goto语句的应用,我们要求尽量少用goto语句。对一定要用的地方要 求只能向后转移。 3、资源变量的处理(资源变量是指消耗系统资源的变量): 对资源变量一定赋初值。分配的资源在用完后必须马上释放,并重新赋 值。 例: long * plAllocMem;/定义一个分配内存的变量。 plAllocMem=(long*)calloc(40, size
12、of( long );/分配一段内存。 /处理分配内存错误 if(plAllocMem=NULL) lResult=CM_MEM_ALLOC_FAILED; goto END; 使用内存 /释放资源变量,并重新赋值。 if(pAllocMem!=NULL) free(plAllocMem); pAllocMem=NULL; 4、对复杂的条件判断,为了程序的可读性,应该尽量使用括号。 例:if(szFileName!=NULL) goto: END; while(wSize- 0) *pvToMem+=pvFromMem+; END: return lResult; 采用判断可以检查传入的指针错
13、误,但是这样的判断是程序最终的编译 代码变大,同时降低了最终发布的程序的执行效率。由于传入空指针明 显是调用这函数的程序的错误,而不是这个函数的错误,我们可以考虑 采用断言来代替指针检查,即用 ASSERT( pvToMem!=NULL goto: END; 这样只会在debug版中才会产生检查代码,而在正式发布版中不会带有 这些代码。并且可以方便我们在程序调试中和测试时发现错误,同时又 不影响程序的效率。 在下面的一些情况中必须加断言: a、 数的参数,特别是指针参数必须利用断言来进行确认。 b、 利用断言检查程序中的各种假设的正确性。 c、 在程序设计中不要轻易认为某种情况不可能发生,对你
14、认为不可能 发生的情况必须用断言来证实。 为了使程序中的断言发挥作用,所有用于在开发内部进行测试或调试的 动态库、执行程序、组件必须采用debug版。 说明: 在程序效率要求较高、或者调用比较频繁的函数,对入口参数的错误检 查,使用断言方式,其优点如上所叙,但其健壮性不强,所以在其他情 况下,仍要求使用传统的检查方式,以增强程序的健壮性,当然,为了 调试方便,可同时使用断言方式。 、 严格的测试: 对每一段代码都要求进行严格的测试,特别对一些功能函数要对其各种 临界点(比如零值、无穷大的值等)进行测试。尽量做到每一段代码零错 误。 六、模块化规范: 为了提高软件的重用性,减少重复开发的工作量。
15、同时也为了提高程序 的可读性,方便程序的维护,必须加强软件的模块化工作。模块化应该 遵循以下几个基本规范: 1、 个函数应该作到精而小,函数的代码应该控制在一个适度的规模, 每个函数的代码一般不能超过150行,如果超过这个规模,应该进行模 块化的工作。对于一些特殊的函数确实要超过150行,应该提交出来讨 论,通过后,要求编写者更加详细的对函数注释,并写明函数超行的原 因,以及设计思想等。 2、 某一功能,如果重复实现三遍以上,既应该考虑模块化,将其写成 通用函数。并向开发人员发布。并要求将接口文档和实现的功能备 案。 3、 每一个开发人员要尽可能的利用其他人的现成的模块,减少重复开 发。 4、 对函数进行模块化时,要考虑函数的层次关系,特别是在增加新的 功能模块时,对原来的函数代码要进行认真的调整,做到相同功能的不 同函数没有重复代码,此要求的目的在于便于代码维护。举例如下: 现有