软件编码规范_第1页
软件编码规范_第2页
软件编码规范_第3页
软件编码规范_第4页
软件编码规范_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

软件编码规范 文件状态:[√]草稿[]正式发布[]正在修改文件编号:RDC-DED-SCS-SPC-00当前版本:作者:审核人:完成日期:中国人民银行清算总中心支付系统开发中心文档修订记录版本编号变化状态简要说明日期变更人批准日期批准人注:变化状态:A—增加,M—修改,D—删除

目录第一篇 C/C++编码规范 6第一章 代码组织 6第二章 命名 92.1 文件命名 92.2 变量命名 92.3 常量与宏命名 102.4 类命名 102.5 函数命名 102.6 参数命名 11第三章 注释 123.1 文档化注释 123.2 语句块注释 173.3 代码维护注释 20第四章 编码风格 224.1 排版风格 224.2 头文件 264.3 宏定义 274.4 变量与常量 304.5 条件判断 324.6 空间申请与释放 334.7 函数编写 334.8 类的编写 374.9 异常处理 404.10 特殊限制 40第五章 编译 41第六章 ESQL/C编码 46第二篇 Java编码规范 47第一章 代码组织 48第二章 命名 512.1 包命名 512.2 类命名 512.3 接口命名 512.4 方法命名 512.5 变量命名 512.6 类变量命名 522.7 常量命名 522.8 参数命名 52第三章 注释 533.1 文档化注释 533.2 语句块注释 573.3 代码维护注释 59第四章 编码风格 614.1 排版风格 614.2 包与类引用 664.3 变量与常量 664.4 类编写 674.5 方法编写 684.6 异常处理 714.7 特殊限制 71第五章 编译 73第六章 JSP编码 746.1 文件命名及存放位置 746.2 内容组织 746.3 编码风格 766.4 注释 786.5 缩进与对齐 786.6 表达式 796.7 JavaScript 79第三篇 PowerBuilder编码规范 80第一章 代码组织 81第二章 命名 822.1 文件命名 822.2 对象命名 822.3 变量命名 842.4 常量命名 852.5 函数与事件命名 852.6 参数命名 85第三章 注释 853.1 文档化注释 853.2 语句块注释 883.3 代码维护注释 88第四章 编码风格 894.1 界面风格 894.2 排版风格 934.3 变量与常量 954.4 条件判断 964.5 空间申请与释放 974.6 函数编写 974.7 特殊限制 97第五章 SQL编码 98前言程序编码是一种艺术,既灵活又严谨,充满了创造性与奇思妙想。然而应用软件设计是一项团结协作工程,而非程序员展示个人艺术的舞台,大型应用软件项目更是由很多程序员组成的大型开发团队协同完成的。每个程序员都有自己的编码经验与风格,如果缺乏统一的编程规范,则可能导致软件产品最终程序代码风格迥异,可读性与可维护性均较差,不仅给程序代码的理解带来障碍,也增加维护阶段的工作量。此外,经验证明不规范的编码行为往往还会导致程序出现更多的隐含错误。为规范编码行为,增强程序代码的可读性、可维护性,提高编码质量与效率,保障应用软件产品整体品质与可持续开发性,特制定本规范。本规范分C/C++编码规范、Java编码规范、PB编码规范三篇,分别从代码组织、命名、注释、编码风格、编译等方面加以阐述。规范文本分为规则与建议两种,其中规则是强制执行的条款,建议则由程序员根据实际情况灵活掌握。C/C++编码规范代码组织使用不同的文件分别放置模块的约束与实现。C++程序的约束文件使用.hpp做扩展名,实现文件使用.cpp做扩展名;C程序的约束文件使用.h做扩展名,实现文件使用.c做扩展名。一个模块可以包含一个类或功能上紧密联系的多个类。禁止将功能关联松散的多个类,放置到一个模块中。模块约束应仅包含模块对外提供的功能,禁止将模块内部使用的功能声明在模块约束中。下例中IsChineseChar()是内部使用的函数,不提供给外部应用使用,因此不能在commpub.hpp中增加声明。例:commpub.hppBOOLIsChineseString(constchar*sInStr);例:commpub.cppstaticBOOLIsChineseChar(constchar*s){……;}BOOLIsChineseString(constchar*sInStr){for(intii=0;ii<strlen(sInStr);ii++){if(!IsChineseChar(sInStr+ii)){returnFALSE;}}returnTRUE;}简单应用应创建下列目录结构,模块程序代码应分别放置到src/include目录与src/source目录,编译文件放置到src/source目录,编译后的可执行文件放置到rel/bin目录,静态库或动态库放置到rel/lib目录(应用使用的外部库及头文件放置在rel同级的lib与lib/include目录)。复杂应用应分子系统创建目录结构,模块程序代码应分别放置到src/module/include目录与src/module/source目录,应用编译文件放置到src目录,编译后的可执行文件放置到rel/bin目录,静态库或动态库放置到rel/lib目录。(应用使用的外部库及头文件放置在rel同级的lib与lib/include目录)各子系统可以创建独立的编译文件并放置到src/module/source目录,编译后的可执行文件放置到rel/bin/module目录或rel/bin,静态库或动态库放置到rel/lib/module或rel/lib目录。此时,应创建一个编译全部子系统的编译文件或脚本放置到src目录。命名命名应遵循下列原则:应简单清晰通俗;应使用英文命名,禁止使用中文命名;应尽量选择通用词汇;应使用完整单词或词组,避免使用简称;应准确表达其含义;避免同时使用易混淆的字母与数字,如1与l,0与o;禁止使用只靠大小写区分的多个名称;多单词组成的名称,单词的首字母应大写,如FileName。名称太长超过15字符时应使用简称。简称应遵循:应使用标准的或常用的简写,如Temp(tmp),Length(len);应用范围内简写应一致且规范,避免各处简写各不相同;简写可以使用单词的前一个或多个字母,如Channel(Chan)、Connect(Conn);也可以使用去掉所有的不在词头的元音字母,如screen(scrn),primtive(prmv);多个单词组成的名称,使用有意义的单词或去掉无用的后缀并简称,如CountofFailure(FailCnt),PagingRequest(PagReq)。文件命名文件命名应使用模块名的小写字母形式。禁止使用汉字或大、小写字母混用作为代码文件名。变量命名变量命名主要采用匈牙利命名法,格式为[作用域范围前缀_][前缀]基本类型+名称。其中,作用域范围前缀、前缀以小写字母表示且可选,基本类型以小写字母表示且必选。常用前缀符前缀符含义例子g_全局变量g_stSystem,g_cMacType,g_strSysNames_静态变量s_nCurCnt,s_strStaticName,s_pSysTimem_类数据成员m_nBankType,m_sWrkBuffer,m_strMyNameh句柄类变量hnFileHandle,hnSocket,hpProcHandlep指针类变量psReadBuff,pstrRetStr,ppTargeta数组类变量anPorts,asSendBuffers,apWrkBuffs常用基本类型符前缀符含义例子bboolbOK,bQuit,bFindc、chcharcFlag,cBankType,chSubSystemTypeschar[]sSysName,sStaticName,sTimeStrstrCString、StringstrSysName,strStaticName,strTimeStrbyunsignchar[]byMacStr,bySendBuffer,bySrcBuffern、iintnCnt,nPort,nRetCodellonglFileSize,lOffset,lCountddoubledAmount,dSumVal,dWrkValffloatfAmount,fSumVal,fWrkValui/ulunsignedint/longuiCnt,uiFileSize,ulRetCountwWORD与unsignedint等价的32位整数dwDOUBLEWORD与unsignedlong等价的64位整数em枚举型变量emDays,emColors,emSetst结构型编码stSystem,stCtrlData,stSet禁止使用单字母作为变量名。但下列常用单字母变量除外:常用单字母变量变量类型说明i,j,k,m,nint循环变量cchar单字符变量schar[]字符数组变量x,yint位置变量pchar*指针变量常量与宏命名常量与宏应使用全大写名称,多词组名称使用_分隔各单词,并使用断行注释说明其含义如:constintMAX_BUFF_SIZE=1024///<最大存储区字节数#defineMAX_FRAME_SIZE512///<单帧的最大长度作为错误码或返回码的宏,应使用E_类型_NAME形式,并使用断行注释说明其含义。#defineE_FILE_NOTFOUND61101001///<文件不存在!#defineE_DB_SELECT_FAIL62301050///<选取数据库失败!#defineE_SYS_INVALID_STATUS62301001///<系统状态非法!作为编译条件的宏,应使用_<NAME>_形式。如:#ifdef_NONE_THROW_#endif…#ifndef_FOR_CCPC_#endif为防止重复包含而定义的头文件预处理宏,应使用__NAME_HPP__(C++)或__NAME_H__(C)形式,其中NAME为模块名称。如:#ifndef__CSIGNAL_HPP__#define__CSIGNAL_HPP__…#endif#ifndef__CSIGNAL_H__#define__CSIGNAL_H__…#endif类命名类命名应使用字符C|T+名称形式。其中名称应使用名词或名词短语,且每个单词首字母大写。如:CSignal,CFile,CString,CTagMgr。函数命名函数命名应使用能够表达函数功能的英文动词或动宾结构短语,且每个单词的首字母大写。如:GetName(),StrTrimLeft(),KillProc()。禁止在函数名称中使用非字母或数字的其他字符,如下划线_。不应在函数名中使用数字,如:GetName1(),Kill2()。但数字是短语一部分的,可以使用,如KillSigusr2()。参数命名函数或方法的参数命名参考变量命名,但应使用In,Out、Ret等简写修饰参数,增加函数声明的可读性。如:BOOLIsSpaceStr(LPCSTRsInStr,ULONGnMaxLen=0,ULONG*plRetOffset=NULL);voidHexToBin(LPCSTRsInStr,BYTE*psOutStr,ULONG*plRetSize=NULL);注释程序代码中增加注释的目标是帮助对程序的阅读理解,不宜太多或太少,太多则会对阅读产生干扰,太少则不利于代码理解,因此只在必要的地方才加注释,且准确、易懂、简洁。文档化注释文件注释文件注释放置在文件头部,主要包括此文件的功能说明,编写人和修改人以及编写和修改的日期,版权声明,版本等信息,应尽量使用中文。注释格式如下:/***@filefilename.hpp*@brief文件简要说明**文件详细说明**@author*-时间作者1贡献1*-时间作者2贡献2*-时间作者3贡献3**@version*-时间版本1简要版本说明1*-时间版本2简要版本说明2**@par其他重要信息:*其他重要信息说明**@warning警告信息**@par版权信息:*版本声明信息*/例:/***@filecsignal.hpp*@briefUNIX信号函数封装类**本类封装部分UNIX信号处理函数,简化在UNIX下编写信号处理程序的编码难度。<br>*本类主要提供下列三类方法:*-信号集合管理,提供信号集合的添加、删除、判断功能;*-信号句柄管理,提供设置与获取信号处理函数功能;*-信号处理,设置与获取阻塞信号集、发送信号、等待信号功能。**@author*-2007-03-05lny创建初始版本*-2007-03-07lny添加文档注释信息*@version*-2007-03-05V1.0创建初始版本*-2007-03-07V2.0添加文档注释信息**@warning本类不能在WIN32操作系统使用。**@par版权信息:*Copyright(C)2007-2007CNCC/CDC*/注:粗体字为需定制化的内容;兰色字为可选的内容,如果没有这些内容,请删除。下同。类注释类注释放置在类声明前,主要介绍类的功能及相关说明。注释格式如下:/***@brief类简要说明**类详细说明**@par其他重要信息*其他重要信息说明**@par变更历史:*-时间作者修改说明*/例:/***@briefUNIX信号处理函数封装类**本类封装部分UNIX信号处理函数,简化在UNIX下编写信号处理程序的编码难度。<br>*本类主要提供下列三类方法:*-信号集合管理,提供信号集合的添加、删除、判断功能;*-信号句柄管理,提供设置与获取信号处理函数功能;*-信号处理,设置与获取阻塞信号集、发送信号、等待信号功能。**@warning本类不能在WIN32操作系统使用。*/classCSignal{…}函数或方法注释函数或方法注释放置在其声明前,主要介绍函数的功能、参数、返回值、异常、使用说明、范例、引用关系、变更信息等信息。注释格式如下:/***@brief函数功能简要说明*@param[in|out]参数名称1参数1简要说明;*@param[in|out]参数名称2参数2简要说明。*@return返回值说明*-返回值1返回值1说明;*-返回值2返回值2说明。*@exception异常说明*-异常1异常1说明;*-异常2异常2说明。**@note函数功能详细说明。*-详细说明1;*-详细说明2。*@warning警告信息*@deprecated函数即将失效警告*@see引用说明**@par使用范例:*@code*例子程序*@endcode**@par算法或流程说明:*详细算法或流程说明**@par变更历史:*-时间作者修改说明*/例:/***@brief添加一个或多个信号到信号集合。*@param[out]stSet要操作的信号集合;*@param[in]nSignal要添加到集合的信号;*@param[in]nOtherSignal要添加到集合的其他信号。*@return添加失败返回负整数,失败原因可以从errno获取。*@note如果要添加多个信号,则必须使用0作为最后一个信号。*@warning如果添加多个信号时没有使用0作结束,则程序可能异常中止!*@seeDelFromSet()、AddAllToSet()、ClearSet()**@par使用范例:*@code*intnRetCode=sig.AddToSet(&stSet,SIGUSR1,SIGUSR2,0);*if(nRetCode<0){...Fail...}*...*nRetCode=sig.AddToSet(&stSet,SIGHUP);*if(nRetCode<0){...Fail...}*@endcode*/intAddToSet(sigset_t*stSet,intnSignal,intnOtherSignal=0,...);重要的或复杂的函数,应提供算法说明或使用范例。如:例:/***@brief根据行号与密码生成报尾校验码作为身份认证串。*@param[in]sBankCode行号;*@param[in]sPassword密码。*@return身份认证串。*@par算法介绍:*-#计算sBankCode+sPassword的MD5数字摘要,输出32位字符;*-#取32位字符的0,5,10,15,16,21,26,31位作16位字符串的偶数位;*-#取"AUTHBEPS"各位作16位字符串的奇数位;*-#加密这16位的字符串,得到32位的字符串作为认证串。*/CStringBuildAuthStr(LPCSTRsBankCode,LPCSTRsPassword);数据成员注释类的每个数据成员均使用断行注释。注释格式如下:例:classCMTMsg{…private:BOOLm_bBodyInFile; ///<是文件型报文?CStringm_strFileName; ///<文件型报文的文件名CStringm_strBody; ///<直接设置的报体串CMTMsgHeaderm_Header; ///<报头对象CMTMsgTailm_Tail; ///<报尾对象CMTBatHeaderm_BatHeader; ///<批量业务头对象}结构注释结构可使用简单注释,也可使用与类相同的注释格式,其数据成员使用断行注释。注释格式如下:例:/**报头结构,总长度138字节。*/structCMTHeaderMap{charblockMark[3]; ///<报头块前缀={1:。charverID[1]; ///<版本号,保留=0。charmesgLen[6]; ///<报文总长度,保留,目前为空白。charappTradeCode[8]; ///<业务码0位(系统号)1-3位CMT号4位节点5-7位保留。charstartAddr[12]; ///<报文源地址,即报文发起人。chardestAddr[12]; ///<报文目标地址,即报文接收人。charmesgPurp[1]; ///<报文用途,保留。charoutForm[1]; ///<输出标识,保留。charmesgID[MSGID_LEN]; ///<报文标识号,报文发起人生成,通信层唯一确定一个报文。charmesgReqNo[REQUESTID_LEN];///<报文参考号,报文发起人生成,回应报文带回进行报文匹配。charworkDate[8]; ///<报文日期,格式为YYYYMMDD。charsentTime[14]; ///<报文时间,格式为YYYYMMDDHHMISS。charexpTime[4]; ///<报文有效期,保留,0-0xFFFF=65535。chardeliTime[6]; ///<报文提交时间,保留,格式为HHMISS。charmesgPRI[1]; ///<报文优先级,0x0-0xF=15。charreserve[20]; ///<保留域。charfinalMark[1]; ///<报头块后缀=}。};宏与变量注释宏与变量使用简单注释或断行注释。特别重要的宏可以使用与类相同的文档注释。注释格式如下:例:#defineMBT_PREFIX"{"///<报文块开始标志#defineMBT_SUFFIX"}"///<报文块结束标志#defineMBT_HEADER"{1:"///<报头块开始标志#defineMBT_BUSINESSHEADER"{2:"///<业务头块开始标志#defineMBT_BUSINESSDATA"{3:"///<正文块开始标志#defineMBT_TAIL"{C:"///<报尾块开始标志#defineMBT_FILE"{F:"///<文件说明块开始标志#defineMBT_BATHEADER"{B:"///<批量信息块开始标志#defineTAG_PREFIX":"///<TAG名开始标志#defineTAG_SUFFIX":"///<TAG名结束标志#defineMSGID_LEN20///<报文标识号长度(MSGID)#defineREQUESTID_LEN20///<报文参考号长度(REQID)例:/**业务头保留域长度*/#defineCMTBH_RESERVED_LEN16例:/***@brief短报文正文体最大长度。**此长度应根据MQCMT类定义最大消息长度进行调整,超过此长度的报文应分为多个报文片断传输。**@par计算公式:*@code*最大长度=MQCMT消息长度-sizeof(CMTMsgHeader)-sizeof(CMTMsgTail)-sizeof(MQMsg)+1*=MQCMT最大消息长度-175*@endcode*目前,MQCMT类定义的最大消息长度为1M=1048576字节。*/#defineSHORT_MSGBODY_MAX_LEN1000000文档注释技巧为使doxygen工具能生成更好的文档,编写文档注释时参考下列技巧:注释中使用的标识符前后均应留一个空格,以便doxygen识别此标识符,并自动生成一个引用连接。如:/***…*@parCMT报文格式说明:*-CMT报文由报头(CMTMsgHeader)、可选的批量业务头(CMTBatHeader)、正文体、报尾(CMTMsgTail)组成。其中除正文体外,其余各块都是定长的;*-正文体由一个或多个业务块组成。每个业务块由一个定长的业务头(CMTBusinessHeader)与一个变长正文块(CMTBusinessData)组成;*-正文块(CMTBusinessData)由一个或多个TAG码:TAG值对(报文域)组成,部分TAG值又可由多个定长子域组成;*-正文体可放置在报文中,也可存储在文件中,而在报文中仅放置文件名;*-当正文体在文件中,则说明批量业务头、业务头、正文块存储在文件中。*/注释中可使用HTML标记美化最终文档,但别滥用美化标记;较长的文档注释需要分段说明时,使用<br>分段。如果需要段首缩进两字符,使用全角的空格。文档注释中可以使用@par增加一个小节,灵活使用此标记可以任意地扩展文档的结构,满足特殊描述的需要。如:/***…**@par算法原理:*计算机内部运算使用的基数是2,即满2进位。如果计算机字长为32位,则最大可以表示的整数为4294967296.<br>*为了突破计算机最大整数的限制,可以采取两种做法,一是扩大基数,二是增加字长。*根据此原理,本类使用65536作为基数,每个整数的最大位数10(unsignedintarray[10]),*因此可以最大整数是65536的10次方,约1.4e48。通过变更基数或位数,本类理论上可以处理的任意整数。*/需要生成圆点列表时使用-,需要生成编号列表时使用-#。需要特别说明一段文字,可以使用@code/@endcode。如:*@par计算公式:*@code*最大长度=MQCMT消息长度-sizeof(CMTMsgHeader)-sizeof(CMTMsgTail)-sizeof(MQMsg)+1*=MQCMT最大消息长度-175*@endcode为使doxygen正确生成函数或方法的连接,注释中的函数名或方法名前后应留一个空格。如该函数或方法没有重载,则不必使用参数列表,如GetTag()。如该函数或方法重载,则应必须使用参数(类型)列表,如GetTag(LPCSTR,AMOUNT&,BOOL,int,int)。语句块注释程序代码主要流程、重要算法以及逻辑性较强的代码和有特殊设计意图的代码(如没有break的case块、空循环体、空语句块)等位置,应添加语句块注释。通过语句块注释,应能反映程序功能的概貌,注释量不应少于该模块概要设计的流程描述量。语句块注释应遵循下列原则:应使用断行注释,即//;一目了然的语句不应注释;每个分支、每个功能段均应注释;应放置在紧临该语句块上方或语句右侧,与其上方的语句块应留一空行,禁止放置在语句块的下方,但可以在语句块下方放置该语句块结束的注释。放置在语句右侧的注释垂直方向尽量对齐,缩进位置与语句块相同。例:主要流程注释 //参数检查if(nInpLen==0||byInpData==NULL) {//检查失败 strOutStr.Empty(); return; }//清除行计数staticintnLineChars=0;//输出的行长度计数if(bResetLineChars){//行计数复位nLineChars=0;}//计算输出长度intnOutLen=2*4*(nInpLen/3+1);//考虑到要添加回车换行,多分配点空间char*p=strOutStr.GetBufferSetLength(nOutLen);memset(p,0,nOutLen);例:逻辑性较强//1.BankCode+PasswordCStringstrWrkStr=sWrkBankCode+sWrkPassword;//2.计算MD5指纹CStringstrMD5=md5.HashBuffer((BYTE*)strWrkStr.GetBuffer(0),strWrkStr.GetLength());//3.选取八位数字指纹char*p=strMD5.GetBuffer(0);charsTmpStr[17];intii=0;memset(sTmpStr,0,sizeof(sTmpStr));for(ii=0;ii<8;++ii)sTmpStr[2*ii]=p[4*ii+ii%4];//4.组合固定串p="AUTHBEPS";for(ii=0;ii<8;++ii)sTmpStr[2*ii+1]=p[ii];例:特殊设计意图BigInt::~BigInt(){//NOTHING}switch(atoi(stCCSV0313_data.szOPERSTATUS)){case1://已付款execsqlupdateCISCODT0702setPAYCNT=:stCCSV0313_data.szCountwhereWORKDATE=:stCCSV0313_data.szWorkDateandCLSCODE=:stCCSV0313_data.szBankTypeandRSTYPE=:stCCSV0313_data.szRSTYPE andARSTSIGN=:stCCSV0313_data.szARSTSIGNandCGTYPE=:stCCSV0313_data.szCGTYPE;CheckDBError("CISCODT0702",E_DB_UPDATE);break;case2://已退票execsqlupdateCISCODT0702setRTNCNT=:stCCSV0313_data.szCountwhereWORKDATE=:stCCSV0313_data.szWorkDateandCLSCODE=:stCCSV0313_data.szBankTypeandRSTYPE=:stCCSV0313_data.szRSTYPE andARSTSIGN=:stCCSV0313_data.szARSTSIGNandCGTYPE=:stCCSV0313_data.szCGTYPE;CheckDBError("CISCODT0702",E_DB_UPDATE);break;default://DONOTHINGbreak;}需要注释一段代码时,避免使用/**/注释,而应使用#ifdef0…#endif形式,因此这种形式可以嵌套。如:例:#ifdef0//直接解析批量包报文(一次读取一个块)intCMTFileOperator::ParseMessage(CMTPkgMsg&msg,intnMaxCount,BOOLbNoDetail){BOOLbMustData=FALSE;CStringstrWrkStr;intnRetCount=0;while(1){ReadBlock(strWrkStr,bNoDetail);if(strWrkStr.IsEmpty())break;//正文块检查if(bMustData&&strncmp(strWrkStr,MBT_BUSINESSDATA,strlen(MBT_BUSINESSDATA))!=0){THROW_OUT(E_NEEDBUSIDATA,"");}elsebMustData=FALSE;//其他报文块//目前没有这样的块,做错块CStrings;s.Format("位置在文件第(%ld)字节",m_hFile.GetPos()-strWrkStr.GetLength());THROW_OUT(E_UNKNOWBLOCK,s);/*CStringsTmpFileName;*sTmpFileName.GetBufferSetLength(strWrkStr.GetLength()-strlen(MBT_FILE)-strlen(MBT_SUFFIX));*strncpy(sTmpFileName.GetBuffer(0),strWrkStr.GetBuffer(0)+strlen(MBT_FILE),strWrkStr.GetLength()-strlen(MBT_FILE)-strlen(MBT_SUFFIX));*//自动解析文件*ClearFailStatus();*msg.Patch(strWrkStr);*ExitOnFail();*/}return0;}#endif代码维护注释维护已经定版的代码时,禁止直接删除或编辑旧代码,而应使用注释保留旧代码,然后在旧代码下方增加新修改后的代码。代码维护注释应放置到被修改代码的上方,使用断行注释,并应注明修改日期、修改人、修改原因。对代码块进行修改的,还应标明修改结束的位置。代码维护注释应从行首开始,不必缩进。例:注销旧代码//2005-04-13lnydelete:将此函数迁移到commexception.cpp文件。#ifdef0//支持异常处理的系统,直接抛出错误voidThrowMsgException(intiCode,LPCSTRlpTagName,LPCSTRlpErrText){CStrings;if(lpErrText!=NULL)s=lpErrText;if(lpTagName!=NULL)s=s+"("+lpTagName+")";ThrowException(iCode,s);}#endif例:修改旧代码//清空数据Clean(FALSE);//解读报文块//2005-09-02lnymodify:增加自动读取报体文件功能。//returnPatch(pMsg);if(IsEmptyStr(pMsg))return0;例:增加新代码//2005-09-02lnyappend:增加自动读取报体文件功能。intnRetCode=Patch(pMsg);if(nRetCode!=0)returnnRetCode;if(m_bBodyInFile&&bAutoReadBodyFile){//Autoreadthebodyfile.CBuffedFilereader;if(!reader.Open(m_strFileName,FALSE,FALSE)){CStringstr;str.Format("打开报文体文件[%s]失败!",m_strFileName.GetBuffer(0));THROW_OUT(E_NEEDBUSIDATA,str);}…}return0;//2005-09-02lnyappendend.}编码风格排版风格缩进与对齐程序代码排版应采用缩进风格编写程序,每层缩进一个制表位(TAB)或四个空格。应用程序全部代码应保持一致,要么使用TAB,要么使用四个空格,不应混用。左花括号({)单独占一行且与右花括号(})对齐。例:if(!IsQuit()){exit(0);}应书写为:if(!IsQuit()){exit(0);}每行只定义一个变量或包含一个语句。例:intnRetCode,nMaxLen;应书写为:intnRetCode;intnMaxLen;超长的语句(>80字符)或表达式应分成多行书写。语句应在逗号分隔符处划分新行;表达式应在低优先级操作符处划分新行,操作符放在新行之首。划分出的新行要进行适当的缩进,使排版整齐,语句易读。例:if(!IsNumberString(stCIS410Detail.sBankCode)||strlen(stCIS410Detail.sBankCode)!=12||strcmp(stCIS410Detail.sBankCode,stCIS410Detail.sOrgBankCode)==0)应书写为:If(!IsNumberString(stCIS410Detail.sBankCode)||strlen(stCIS410Detail.sBankCode)!=12||strcmp(stCIS410Detail.sBankCode,stCIS410Detail.sOrgBankCode)==0)THROW_OUT(E_INVALIDLIST,StrPrint("票交机构行别非数字或长度非3位![%s]",stCIS410Detail.sClsCode).GetBuffer(0));应书写为:THROW_OUT(E_INVALIDLIST,StrPrint("票交机构行别非数字或长度非3位![%s]",stCIS410Detail.sClsCode).GetBuffer(0));对结构的多个数据成员赋值时,将等号对齐。例:rect.top=0;rect.left=0;rect.right=300;rect.bottom=200;应书写为:rect.top=0;rect.left=0;rect.right=300;rect.bottom=200;定义多个宏或初始化多个变量时,将值对齐。例:#defineMBT_PREFIX"{"///<报文块开始标志#defineMBT_SUFFIX"}"///<报文块结束标志#defineMBT_HEADER"{1:"///<报头块开始标志#defineMBT_BUSINESSHEADER"{2:"///<业务头块开始标志#defineMBT_BUSINESSDATA"{3:"///<正文块开始标志#defineMBT_TAIL"{C:"///<报尾块开始标志#defineMBT_FILE"{F:"///<文件说明块开始标志#defineMBT_BATHEADER"{B:"///<批量信息块开始标志#defineTAG_PREFIX":"///<TAG名开始标志#defineTAG_SUFFIX":"///<TAG名结束标志应书写为:#defineMBT_PREFIX"{"///<报文块开始标志#defineMBT_SUFFIX"}"///<报文块结束标志#defineMBT_HEADER"{1:"///<报头块开始标志#defineMBT_BUSINESSHEADER"{2:"///<业务头块开始标志#defineMBT_BUSINESSDATA"{3:"///<正文块开始标志#defineMBT_TAIL"{C:"///<报尾块开始标志#defineMBT_FILE"{F:"///<文件说明块开始标志#defineMBT_BATHEADER"{B:"///<批量信息块开始标志#defineTAG_PREFIX":"///<TAG名开始标志#defineTAG_SUFFIX":"///<TAG名结束标志m_bIsConnected=FALSE;m_bDoConnect=FALSE;MQODod={MQOD_DEFAULT};应书写为:m_bIsConnected=FALSE;m_bDoConnect=FALSE;MQODod={MQOD_DEFAULT};if、for、do、while、case、switch、default等语句独占一行,且if、for、do、while等语句的执行部分总要加括号{}。例:if(!IsQuit())exit(0);应书写为:if(!IsQuit()){exit(0);}定义指针或引用时,*与&应紧靠其类型而非变量。例:int*p=&nRetCode;CString&str=strOldName;应书写为:int*p=&nRetCode;CString&str=strOldName;空格与空行相邻两个功能相对独立的代码块间应使用空行隔开。例:MQMDmd={MQMD_DEFAULT};memcpy(&m_md,&md,sizeof(md));m_md.Version=MQOD_VERSION_2;MQPMOpmo={MQPMO_DEFAULT};memcpy(&m_pmo,&pmo,sizeof(pmo));m_pmo.Version=MQOD_VERSION_2;MQGMOgmo={MQGMO_DEFAULT};memcpy(&m_gmo,&gmo,sizeof(gmo));m_gmo.Version=MQOD_VERSION_2;应书写为:MQMDmd={MQMD_DEFAULT};memcpy(&m_md,&md,sizeof(md));m_md.Version=MQOD_VERSION_2;MQPMOpmo={MQPMO_DEFAULT};memcpy(&m_pmo,&pmo,sizeof(pmo));m_pmo.Version=MQOD_VERSION_2;MQGMOgmo={MQGMO_DEFAULT};memcpy(&m_gmo,&gmo,sizeof(gmo));m_gmo.Version=MQOD_VERSION_2;变量申明之后应使用空行与代码隔开。例:MQMsgInfomqMsg;mqMsg.m_strMsgId=strMsgId;mqMsg.m_nPriority=nPriority;mqMsg.m_iFeedback=iFeedbackCode;mqMsg.m_pBuffer=(LPTSTR)sMsgStr;mqMsg.m_nDataLen=nMsgLen;mqMsg.m_iSegmentFlag=iSegmentFlag;if(iFeedbackCode==MFBC_NONE)mqMsg.m_iMsgType=MT_NORMAL;elsemqMsg.m_iMsgType=MT_REPORT;应书写为:MQMsgInfomqMsg;mqMsg.m_strMsgId=strMsgId;mqMsg.m_nPriority=nPriority;mqMsg.m_iFeedback=iFeedbackCode;mqMsg.m_pBuffer=(LPTSTR)sMsgStr;mqMsg.m_nDataLen=nMsgLen;mqMsg.m_iSegmentFlag=iSegmentFlag;if(iFeedbackCode==MFBC_NONE)mqMsg.m_iMsgType=MT_NORMAL;elsemqMsg.m_iMsgType=MT_REPORT;函数返回语句要和其他语句用空行分开。例:ptr->m_chMsgType=MQ_MT_TAIL;iSegmentFlag=SF_LASTSEGMENT;strncpy(ptr->m_pBody,(char*)pTail,sizeof(CMTTailMap));returnPut((LPCSTR)ptr,strMsgId,sizeof(MQMsg)+sizeof(CMTTailMap)-1,iSegmentFlag,nPriority,iFeedbackCode);应书写为:ptr->m_chMsgType=MQ_MT_TAIL;iSegmentFlag=SF_LASTSEGMENT;strncpy(ptr->m_pBody,(char*)pTail,sizeof(CMTTailMap));returnPut((LPCSTR)ptr,strMsgId,sizeof(MQMsg)+sizeof(CMTTailMap)-1,iSegmentFlag,nPriority,iFeedbackCode);比较操作符,赋值操作符,算术操作符,逻辑操作符,位域操作符等双目运算符前后应加空格与操作数隔开。例:i=i+1;if(i>10)i=(i>>2);应书写为:i=i+1;if(i>10){i=(ii>>2);}逗号、分号后面应加空格,但前面不应加空格。例:for(intii=0;ii<10;ii++)应书写为:for(intii=0;ii<10;ii++)在关键字和其后的括号之间加一个空格。例:if(i>10)for(ii=0;ii<10;ii++)应书写为:if(i>10)for(ii=0;ii<10;ii++)单目运算符不应加空格与操作数隔开。例:while(!IsQuit()){ii++;a[ii]=a[ii]+1;}应书写为:while(!IsQuit()){ii++;a[ii]=a[ii]+1;}函数名与括号间、结构或类与成员间、左括号后、右括号前、不应加空格。例:CStringstr=stSet.GetName(strOrgName);if(str=="uname"){pOldSet->m_nName=str;}应书写为:CStringstr=stSet.GetName(strOrgName);if(str=="uname"){pOldSet->m_nName=str;}括号使用复杂的表达式应使用括号以避免二义性,不应依赖运算符优先级。如:if((i>0)||(i<=-12))、(p++)+1。位运算时应使用括号,如:i=(nSumVal<<4)。return与throw非函数,不应使用括号。如:returnnRetCode。头文件头文件应使用防止重复包含宏括整个头文件部分。宏名应为__模块名_HPP__或__模块名_H__。注意:#endif后必须保留一个空行,否则部分编译器会报警告信息。本模块需要的头文件以及外部函数,应全部列在本模块头文件的首部且紧临防重复包含宏,并按先系统级、公共级、应用级、本模块级的顺序摆放。尽量不在实现文件中包含除本模块头文件外的其他头文件以及外部函数。头文件引用禁止含路径信息,无论是全路径还是相对路径。禁止在头文件中定义变量或常量。例:头文件cis401.hpp#ifndef__MODULE_NAME_HPP__#define__MODULE_NAME_HPP__#include<stdio.h>#include"/PUBLIB/src/include/common.hpp"#include"../include/cispub.hpp"intg_nUserCode=0;…#endif例:实现文件cis401.cpp#include<string.hpp>#include"cstring.hpp"#include"../include/cis401.hpp"externlongGetFileSize(LPCSTRsFileName);…cis401.hpp应书写为:#ifndef__MODULE_NAME_HPP__#define__MODULE_NAME_HPP__#include<stdio.h>#include<string.hpp>#include"common.hpp"#include"cstring.hpp"#include"cispub.hpp"externlongGetFileSize(LPCSTRsFileName);externintg_nUserCode;…#endifcis401.cpp应书写为:#include"cis401.hpp"intg_nUserCode=0;…宏定义灵活使用编译宏解决平台或版本的兼容性问题。例:.cpp#ifdefWIN32//inWIN32voidprintTrace(LPCSTRlpName,LPCSTRlpText,...){charszTmp[4096];memset(szTmp,0,sizeof(szTmp));va_listargList;va_start(argList,lpText);_vsprintf(szTmp,lpText,argList);va_end(argList);fprintf(stderr,"[%s]%s:%s\n",StrCurrentTime("YYYY-MM-DDHH:MM:SS").GetBuffer(0),lpName,szTmp);}#else//inUNIXvoidprintTrace(LPCSTRlpName,LPCSTRlpText,...){charszTmp[4096];memset(szTmp,0,sizeof(szTmp));va_listargList;va_start(argList,lpText);vsprintf(szTmp,lpText,argList);va_end(argList);fprintf(stderr,"[%s]%s:%s\n",StrCurrentTime("YYYY-MM-DDHH:MM:SS").GetBuffer(0),lpName,szTmp);}#endif应修改为:.hpp#ifdefWIN32#definevsprintf_vsprintf#endif.cppvoidprintTrace(LPCSTRlpName,LPCSTRlpText,...){charszTmp[4096];memset(szTmp,0,sizeof(szTmp));va_listargList;va_start(argList,lpText);vsprintf(szTmp,lpText,argList);va_end(argList);fprintf(stderr,"[%s]%s:%s\n",StrCurrentTime("YYYY-MM-DDHH:MM:SS").GetBuffer(0),lpName,szTmp);}宏表达式的变量应使用括号括,使用宏时应避免传递表达式给宏变量。例:#defineMAX(a,b)(a>b)?a:b应书写为:#defineMAX(a,b)(((a)>(b))?(a):(b))调用:intnMax=MAX(i++,b++);应书写为:intnTmpi=i++;intnTmpb=b++;intnMax=MAX(nTmpi,nTmpb);单条语句构成的宏不应使用分号作为宏结束;多条语句构成宏时,应使用花括号括宏体。例:#defineThrowExceptionExt(sFileName,nErrCode,sExtMsg)\ThrowFileExceptionExt(__FILE__,__LINE__,sFileName,nErrCode,sExtMsg);returnnErrCode#defineRETCODE(n)returnn;应书写成:#defineThrowExceptionExt(sFileName,nErrCode,sExtMsg)\{\ThrowFileExceptionExt(__FILE__,__LINE__,sFileName,nErrCode,sExtMsg);\returnnErrCode;\}#defineRETCODE(n)returnn构成宏体的语句必须完成,禁止包含语句块的部分。例:#defineCLEAR_ALL(n)for(intii=0;ii<n;ii++)…CLEAR_ALL(strlen(str)){str[ii]=0;}#defineCLEAR_ALL(n)\{\for(intii=0;ii<(n);ii++)\{\str[ii]=0;\}\}以上两例应书写为:#defineCLEAR_ALL(str,n)\{\for(intii=0;ii<(n);ii++)\{\str[ii]=0;\}\}/*即使这样,代码依然是不安全的。应避免在宏中定义变量*/禁止使用宏替换关键字,如下列为不良写法。#defineMYENUMenumMYENUMerr{E_DATE=1,E_TIME=2}使用enum或constint或inline函数代替宏。例:#defineMAX_FRAME_SIZE1024#defineERR_DATE1#defineERR_TIME2#defineERR_TASK_NO3#defineExitOnFail(){if(g_nErrCode!=0)returng_nErrCode;}应书写为:constintMAX_FRAME_SIZE=1024;enumERR_TYPE{ERR_DATE=1,ERR_TIME=2,ERR_TASK_NO=3}inlineintExitOnFail(){if(g_nErrCode!=0){returng_nErrCode;}}变量与常量避免使用与全局变量、外部变量同名的局部变量;禁止使用关键字、保留字、函数名作为变量名。如下列为不良写法:例:intnMaxSize=100;intstrlen=1;for(intii=0;ii<10;ii++){ intnMaxSize=ii+strlen; strlen++; printf("===%d\n",strlen);}总在定义变量时指定其初始值,无论此变量是全局变量、静态变量还是局部变量。避免使用没有初始化的变量。尽量使用const修饰可能的变量,这可以避免很多书写错误。注意区分const的位置,constchar*p、char*constp、constchar*constp分别代表指针p指向常量串、常量指针p指向串、常量指针p指向常量串。而constint与intconst则是相同的含义。尽可能少使用全局变量。给全局变量指定值时注意值域范围,避免值越界。使用无符号数声明位域变量。例:typedefstruct{intbit0:1;intbit1:1;intbit2:1;intbit3:1;intbit4:1;intbit5:1;intbit6:1;intbit7:1;}BITS;BITSstBits;stBits.bit0=1;stBits.bit1=2;stBits.bit2=3;printf("%d%d%d\n",stBits.bit0,stBits.bit1,stBits.bit2);//期望输出:101,但实际输出是:-10-1。应书写为:typedefstruct{unsignedintbit0:1;unsignedintbit1:1;unsignedintbit2:1;unsignedintbit3:1;unsignedintbit4:1;unsignedintbit5:1;unsignedintbit6:1;unsignedintbit7:1;}BITS;…使用专门的初始化函数对所有的公共变量进行初始化。代码中的数值应尽量使用有意义的标识符代替。例:doubledArea=3.14*dRadii*dRadii;应书写为:constdoublePI=3.14;doubledArea=PI*dRadii*dRadii;充分使用C++的特性,在使用局部变量前,尽可能晚地定义它,并应增加注释说明。不要复用一个变量。每个变量用途应明确,频繁变更用途容易让人迷惑。例:intnReadSize=0;nReadSize=oReader.Read(psBuffer,10240);if(nReadSize==10240){nReadSize=CallProcess(psBuffer);if(nReadSize!=0)returnnReadSize;}应书写为:intnReadSize=0;nReadSize=oReader.Read(psBuffer,10240);if(nReadSize==10240){intnRetCode=CallProcess(psBuffer);if(nRetCode!=0)returnnRetCode;}使用静态变量或动态分配内存代替大局部变量(字节数超过4k),避免占用太多堆栈空间,但应注意静态局部变量是非重入安全的。注意变量的值域范围,避免值溢出或丢失精度。例:下溢导致死循环unsignedcharc=127;unsignedcharn=10;while(n>=0){n--;c++;}应书写为:unsignedintc=127;charn=10;while(n>=0){n--;c++;}不要将常量强制转换为变量,有时可能导致系统崩溃。条件判断if语句的判断条件必须是逻辑表达式,不应使用C++默认的0为false,非0为true的规则。如:例:char*p=strstr("abc","a");if(p){…;}应书写为:char*p=strstr("abc","a");if(p==NULL){…;}char*p=str;while(*p){p++;}应书写为:char*p=str;while(*p!=0){p++;}for(intii=10;ii;ii--)应书写为:for(intii=10;ii>0;ii--)禁止对逻辑表达式进行比较操作。如:例:if((ii>10)||(bQuit==TRUE)||IsContinue()==FALSE){…;}应书写成:if((ii>10)||bQuit||!IsContinue()){…;}避免对浮点类型作等于或不等于判断,应根据应用的实际情况使用范围判断。如:金额的小数位为两位,则判断金额是否为零,可以写成:if(dAmount<0.0001&&dAmount>-0.0001)。空间申请与释放使用C++的new操作符申请空间,使用delete操作符释放空间,new[]申请的数组空间,应使用delete[]释放。申请空间后、释放空间前,应判断指针是否为NULL;释放空间后应赋值该指针为NULL,避免重复释放空间。尽量在申请空间的函数内部释放空间,否则应妥善传递申请的空间指针,并在合适的时间释放,避免内存泄漏。函数编写仔细选择函数的参数并尽量减少参数个数。没有参数时明确地使用void说明;参数是数组类型的,使用数组类型而非指针类型;参数是类对象的,尽量使用对象的引用或对象指针;参数是大数据变量的,必须使用引用或指针;可默认值的参数尽量指定默认值。函数入口点应检查每个参数的合法性。仔细安排参数的位置,最常用的参数放置在最前面,输入参数尽量放置在左边,输出参数尽量放置在右边。显式声明函数的返回值,没有返回值的使用void说明。返回指针的函数,使用NULL作为错误返回。禁止返回局部变量的指针或引用。必须完整处理函数返回码,并预留通用返回码的处理,避免新增加的返回码被忽略。例:intnRetCode=CheckBusiness();if(nRetCode==-1){…return;}if(nRetCode==-2){…return;}应书写为:intnRetCode

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论