软件编程建议.doc_第1页
软件编程建议.doc_第2页
软件编程建议.doc_第3页
软件编程建议.doc_第4页
软件编程建议.doc_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

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

文档简介

Comment liao1 Page 1 密级可以选择以下几种 无 一般 内部 组内 秘密 绝密等 文文 档档 编编 号号产品版本产品版本受控状态受控状态 V 1 0内部 产品名称 产品名称 软件编程建议软件编程建议共共 页页 软件编程建议软件编程建议 仅供内部使用仅供内部使用 北京世纪百合科技有限公司北京世纪百合科技有限公司 Beijing Centurial Lily Technology Co Ltd 版权所有版权所有 不得复制不得复制 北京世纪百合技术有限公司 软件编程建议 第 2 页 共 16 页 文档修改记录文档修改记录 版本号日期所改页注 记提交人批准人 北京世纪百合技术有限公司 软件编程建议 第 3 页 共 16 页 目录 1 引言引言 4 1 1目的 4 1 2范围 4 2 建议建议 4 2 1代码 4 2 2代码的效率 11 2 3可测试性 13 2 4操作系统下的编程 14 2 5代码的编辑 编译和审查 16 北京世纪百合技术有限公司 软件编程建议 第 4 页 共 16 页 1 引言引言 1 1目的目的 本建议的目的在于在公司开发的所有软件产品中推荐使用开发方法以及开发 经验 使用该建议将有助于提高软件生产效率 减少开发过程的错误以及提高软 件产品的最终品质 1 2范围范围 本规范内容涉及范围包括 代码的可靠性 代码的效率 代码的可测试性以 及代码的编译 编译和审查 以及多任务操作系统 vxWorks 下的编程 2 建议建议 2 1 代码代码 2 1 1在两个以上的关键字 变量 常量进行对等操作时 它们之间的操作符之在两个以上的关键字 变量 常量进行对等操作时 它们之间的操作符之 前 之后或者前后要加空格 进行非对等操作时 如果是关系密切的立即前 之后或者前后要加空格 进行非对等操作时 如果是关系密切的立即 操作符 如 操作符 如 后不应加空格 后不应加空格 说明 采用这种松散方式编写代码的目的是使代码更加清晰 示例 1 比较操作符 赋值操作符 算术操作符 逻辑操作符 赋值操作符 算术操作符 wLength 2 算术操作符 wLength wWidth 2 赋值操作符 算术操作符 2 内容操作 与内容之间 bFlag bEmpty 非操作 与内容之间 pbyAddr 地址操作 与内容之间 3 前后不加空格 pCaller byId byId 指针前后不加空格 4 if for while switch 等与后面的括号间应加空格 使 if 等关键字更 为突出 明显 示例 if wLength wWidth printf the length is d n wLength 应该改为 wLength 或 wLength ifdef ISDN DEBUG printf the length is d n wLength endif 2 1 3对分支语句 条件分支 循环语句等 应该编写注释 对分支语句 条件分支 循环语句等 应该编写注释 说明 这些语句往往是程序实现某一特定功能的关键 对于维护人员来说 良好的 注释帮助更好的理解程序 有时甚至优于看设计文档 示例 如下注释意义不大 if bReceiveFlag is TRUE if bReceiveFlag 而如下的注释则给出了额外有用的信息 if mtp receive a message from links if bReceiveFlag 当代码比较长 特别是有多重嵌套时 应当在一些段落的结束处加注释 便于阅读 示例 if bFlag while wTemp end of while wTemp 北京世纪百合技术有限公司 软件编程建议 第 6 页 共 16 页 end of if bFlag 2 1 4有实际意义的变量命名禁止取单个字符 如有实际意义的变量命名禁止取单个字符 如 i j k 除了要有具体含 除了要有具体含 义的字母外还要有能表明其变量类型以及数据类型的字母 义的字母外还要有能表明其变量类型以及数据类型的字母 i j k 等单个等单个 字符作为局部循环变量是允许的 字符作为局部循环变量是允许的 2 1 5用正确的反义词组命名具有互斥意义的变量或相反动作的函数等 用正确的反义词组命名具有互斥意义的变量或相反动作的函数等 当函数当函数 名由名词和动词组成时 名词放在动词的前面 名由名词和动词组成时 名词放在动词的前面 说明 下面是一些在软件中常用的反义词组 add delete begin end min max insert delete first last get release increment decrement put get up down create destroy lock unlock open close source destination old new start stop next previous show hide cut paste send receive 示例 int iMinSum int iMaxSum int UserAdd BYTE pbyUserName int UserDelete BYTE pbyUserName 2 1 6结构中元素的个数应适中 若结构中元素个数过多可考虑依据类型相近原结构中元素的个数应适中 若结构中元素个数过多可考虑依据类型相近原 则把元素组成不同的子结构 以减少原结构中元素的个数 则把元素组成不同的子结构 以减少原结构中元素的个数 接口之间的数接口之间的数 据结构和消息结构应该定义为紧凑方式 据结构和消息结构应该定义为紧凑方式 说明 目的是为了增加结构的可理解性 可维护性 接口之间的数据结构和消息结 构定义为紧凑方式可以保证接口传递数据时元素位置不会出现偏移 示例 typedef struct WORD wDestTaskID WORD wSourTaskID WORD wMsgType WORD wMsgLength WORD wTaskID BOOLEAN bDataFlag BYTE pbyData DWORD dwDataSize PACK STRUCTCFM SENT BGP DATA 如果认为上述结构元素过多 可以划分为如下形式 typedef struct WORDwDestTaskID WORDwSourTaskID WORDwMsgType WORDwMsgLength PACK STRUCTCOMMON HEAD typedef struct 北京世纪百合技术有限公司 软件编程建议 第 7 页 共 16 页 COMMON HEADstCommHead WORD wTaskID BOOLEANbDataFlag BYTE pbyData DWORD dwDataSize PACK STRUCTCFM SENT BGP DATA 2 1 7定义用于分布式环境或不同类别定义用于分布式环境或不同类别 CPU 间通信环境的数据结构时 要机器间通信环境的数据结构时 要机器 的字节顺序 位域顺序等问题的字节顺序 位域顺序等问题 说明 比如 Intel X86 CPU 与 MOTOROLA PPC CPU 在处理位域及整数时 其在内 存存放的 顺序 正好相反 示例 假如有如下短整数及结构 short int iExample typedef struct BYTE byProtocol 5 BYTE byLayerId 2 BYTE byExt 1 ISDN BEARER 如下是 Intel CPU 生成短整数及位域的顺序 内存 0 1 2 从低到高 以字节为单位 iExample 低字节 高字节 内存 0 4bit 5 6bit 7bit 字节的各 位 ISDN BEARER byProtocol byLayerId byExt 如下是 PPC CPU 生成短整数及位域的方式 内存 0 1 2 从低到高 以字节为单位 iExample 低字节 高字节 内存 7 3bit 2 1bit 0bit 字节的各 位 ISDN BEARER byProtocol byLayerId byExt 2 1 8函数的规模一般限制在函数的规模一般限制在 200 行以内 函数功能要求单一 行以内 函数功能要求单一 说明 不包括注释和空行 2 1 9避免函数有太多的参数 参数个数尽量控制在避免函数有太多的参数 参数个数尽量控制在 5 个以内 个以内 2 1 10 功能特别简单的函数可以通过宏 冒号表达式或内联函数等方式实现 以功能特别简单的函数可以通过宏 冒号表达式或内联函数等方式实现 以 提高效率 提高效率 说明 通过宏或内联函数代替函数 省去了参数压栈 生成汇编语言的 CALL 调用 返回参数 执行 return 等过程 从而提高了速度 示例 如下语句的功能太单一 北京世纪百合技术有限公司 软件编程建议 第 8 页 共 16 页 int isdn MaxParam int iTx int iRx return iTx iRx iTx iRx 可以通过表达式 iResult iTx iRx iTx iRx 或宏 define MAX a b a b a b iResult MAX iTx iRx 也可以通过内联函数 inline int isdn MaxParam int iTx int iRx return iTx iRx iTx iRx 来实现 2 1 11 函数的扇入 扇出系数要合理 设计高扇入 合理扇出 小于函数的扇入 扇出系数要合理 设计高扇入 合理扇出 小于 7 的函数 的函数 说明 扇出是指一个函数直接调用 控制 其它函数的数目 而扇入是指有多少 上级函数调用它 扇出过大 表明函数过分复杂 需要控制和协调过多的下级函 数 而扇出过小 如总是 1 表明函数的调用层次可能过多 这样不利程序阅读 和函数结构的分析 并且程序运行时会对系统资源如堆栈空间等造成压力 函数 较合理的扇出 调度函数除外 通常是 3 5 扇出太大 一般是由于缺乏中间层 次 可适当增加中间层次的函数 扇出太小 可把下级函数进一步分解多个函数 或合并到上级函数中 当然分解或合并函数时 不能改变要实现的功能 也不能 违背函数间的独立性 扇入越大 表明使用此函数的上级函数越多 这样的函数 使用效率高 但不能违背函数间的独立性而单纯地追求高扇入 公共函数及底层 函数应该有较高的扇入 较良好的软件结构通常是顶层函数的扇出较高 中层函 数的扇出较少 而底层函数则扇入到公共模块中 2 1 12 减少函数本身或函数间的递归调用 减少函数本身或函数间的递归调用 说明 递归调用特别是函数间的递归调用 如 A B C A 影响程序的可理解性 递归调用一般都占用较多的系统资源 如栈空间 且对程序的测试有一定影响 故 除非为某些算法或功能的实现方便 应减少没必要的递归调用 2 1 13 要时刻注意易混淆的操作符 防止拼写错误 要时刻注意易混淆的操作符 防止拼写错误 说明 形式相近的操作符最容易引起误用 如 C C 中的 与 与 if byRegister byFlag return wTempValue 上述函数的输出在 1 127 范围内 依次输出 每次结果不同 如果需要输出结果相同 可作如下改动 WORD isdn AssignCRValue void WORD wTempValue WORD wCurrentCR 1 改为 auto 类型 wTempValue wCurrentCR wCurrentCR if wCurrentCR 127 wCurrentCR 1 return wTempValue 2 1 16 当某函数的返回值为指针类型时 则指针指向的必须是当某函数的返回值为指针类型时 则指针指向的必须是 STATIC 的局部变的局部变 量或申请的动态内存 如果指针指向的是量或申请的动态内存 如果指针指向的是 AUTO 的局部变量 则返回的为的局部变量 则返回的为 错指针 错指针 说明 AUTO 的局部变量使用的是堆栈 当函数的退出后释放 所以返回的指针将 指向无效的内存 示例 如下函数 其返回值错误的 WORD isdn GetValue void WORD wCurrentCR 0 wCurrentCR if wCurrentCR 127 北京世纪百合技术有限公司 软件编程建议 第 10 页 共 16 页 wCurrentCR 1 return 应该改作 WORD isdn GetValue void static WORD wCurrentCR 0 wCurrentCR if wCurrentCR 127 wCurrentCR 1 return 2 1 17 谨慎使用谨慎使用 strcpy 函数 函数 说明 当源字符串的长度不确定时 例如由用户输入的命令参数串 应该使用 strncpy 函数 避免由于目的缓冲区长度不够造成越界 注意 使用 strncpy 函数时应该紧接着设置结束标志 0 以免出现不可预测的结果 示例 如下函数可能出现越界 void isdn SetCallNumber BYTE pbyCallerNumber BYTE abyNumber 26 strcpy abyNumber pbyCallerNumber programm code 在上述函数中 pCallerNumber 为用户输入的用户号码指针 aNumber 为用户号 码缓冲区 当用户输入的号码长度大于 25 个时 出现越界 因为用户号码长度最大为 25 因此可作如下更改 void isdn SetCallNumber BYTE pbyCallerNumber BYTE abyNumber 26 strncpy abyNumber pbyCallerNumber 25 abyNumber 25 0 programm code 2 1 18 在函数内不要定义占用内存很大的局部变量 局部变量占用的内存应该控在函数内不要定义占用内存很大的局部变量 局部变量占用的内存应该控 制在制在 1K 以内 以内 说明 由于局部变量要使用系统的堆栈空间 堆栈是有限的 如果函数定义的局部 变量使用内存过大 当函数多层调用时 可能造成堆栈溢出 引发系统故障 北京世纪百合技术有限公司 软件编程建议 第 11 页 共 16 页 示例 如下函数不规范 void isdn ShowRunning void BYTE pbyShowBuf 2048 program code 应作如下书写 void isdn ShowRunning void BYTE pbyShowBuf pbyShowBuf BYTE malloc size BYTE 2048 if pbyShowBuf NULL return program code free pbyShowBuf 2 2代码的效率代码的效率 2 2 1在保证软件系统的正确性 稳定性 可读性及可测性的前提下 提高代码在保证软件系统的正确性 稳定性 可读性及可测性的前提下 提高代码 效率 局部效率应为全局效率服务 不能因为提高局部效率而对全局效率效率 局部效率应为全局效率服务 不能因为提高局部效率而对全局效率 造成影响 造成影响 说明 不能一味地追求代码效率 而对软件的正确性 稳定性 可读性及可测性造 成影响 2 2 2 可以通过对系统数据结构的划分与组织的改进 以及对程序算法的优化来可以通过对系统数据结构的划分与组织的改进 以及对程序算法的优化来 提高空间效率 提高空间效率 说明 这种方式是解决软件空间效率的根本办法 2 2 3尽量使循环体内的计算复杂度最小 尽量使循环体内的计算复杂度最小 说明 应仔细考虑循环体内的语句是否可以放在循环体之外 使循环体内工作量最 小 从而提高程序的时间效率 示例 如下代码效率不高 for i 0 i ISDN MAX NUMBER i iSum i iBackSum iSum 语句 iBackSum iSum 完全可以放在 for 语句之后 如下 for i 0 i ISDN MAX NUMBER i 北京世纪百合技术有限公司 软件编程建议 第 12 页 共 16 页 iSum i iBackSum iSum 2 2 4在多重循环中 应将最忙的循环放在最内层 应该尽量减少循环嵌套层次 在多重循环中 应将最忙的循环放在最内层 应该尽量减少循环嵌套层次 说明 减少 CPU 切入循环层的次数 示例 如下代码效率不高 for wRow 0 wRow 100 wRow for wCol 0 wCol 5 wCol wSum aNumber wRow wCol 可以改为如下方式 以提高效率 for wCol 0 wCol 5 wCol for wRow 0 wRow 100 wRow wSum aNumber wRow wCol 2 2 5 避免循环体内含判断语句 应将循环语句置于判断语句的代码块之中 避免循环体内含判断语句 应将循环语句置于判断语句的代码块之中 说明 目的是减少判断次数 循环体中的判断语句是否可以移到循环体外 要视程 序的具体情况而言 一般情况 与循环变量无关的判断语句可以移到循环体外 而 有关的则不可以 示例 如下代码效率稍低 for i 0 i ISDN MAX RECT NUMBER i if iDataType ISDN RECT AREA iAreaSum aRectArea i else iRectLenSum aRect i wLength iRectWidthSum aRect i wWidth 因为判断语句与循环变量无关 故可如下改进 以减少判断次数 if iDataType ISDN RECT AREA for i 0 i ISDN MAX RECT NUMBER i iAreaSum aRectArea i else for i 0 i ISDN MAX RECT NUMBER i 北京世纪百合技术有限公司 软件编程建议 第 13 页 共 16 页 iRectLenSum aRect i wLength iRectWidthSum aRect i wWidth 2 3可测试性可测试性 2 3 1使用断言来发现软件问题 提高代码可测性 使用断言来发现软件问题 提高代码可测性 说明 断言是对某种假设条件进行检查 可理解为若条件成立则无动作 否则应报 告 它可以快速发现并定位软件问题 同时对系统错误进行自动报警 示例 下面是一个断言 用宏来设计的 其中 NULL 为 0L ifdef DEBUG ON VOS 断言定义 define ASSERT f while f Assert FILE LINE else define ASSERT f NULL endif DEBUG ON 2 3 2用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况 用断言来检查程序正常运行时不应发生但在调测时有可能发生的非法情况 如用断言可以确认函数的参数 如用断言可以确认函数的参数 示例 假设某函数参数中有一个指针 那么使用指针前可对它检查 如下 RESULT isdn Receive NI CELL pstCell SK BUF pstSkBuf ASSERT pstCell NULL 用断言检查指针 ASSERT pstSkBuf NULL program code return OK 2 3 3正式软件产品中应把断言及其它调测代码去掉 即把有关的调测开关关掉 正式软件产品中应把断言及其它调测代码去掉 即把有关的调测开关关掉 说明 加快软件运行速度 2 3 4 在软件系统中设置与取消有关测试手段 不能对软件实现的功能等产生影在软件系统中设置与取消有关测试手段 不能对软件实现的功能等产生影 响 响 说明 即有测试代码的软件和关掉测试代码的软件 在功能行为上应一致 北京世纪百合技术有限公司 软件编程建议 第 14 页 共 16 页 2 4操作系统下的编程操作系统下的编程 2 4 1如果函数同时被多个任务调用会产生错误 要在函数中加入互斥开关 如如果函数同时被多个任务调用会产生错误 要在函数中加入互斥开关 如 果只是其中的一段代码同时被调用会产生错误 则在该段代码的开头应该果只是其中的一段代码同时被调用会产生错误 则在该段代码的开头应该 加入互斥开关 加入互斥开关 说明 有一些函数 如访问某些全局变量 数据区或文件的函数 在被多个任务同 时被调用时会产生数据不一致或数据丢失错误 在这种情况下可以通过信号量保护 这些数据 示例 1 以下函数是由多个任务调用的读写某一数据区的函数 BOOL isdn AccessData void 获取信号量 Lock 读写数据代码 program code 释放信号量 unLock return OK 任务在调用该函数时获取信号量 直到完成所有操作后才释放信号量 如果另一任 务同时调用该函数 会因为没有信号量进入 PEND 状态 直至信号量被释放 示例 2 以下函数中的一段代码读写某一数据区 该函数被多个任务调用 BOOL isdn Command int iCommand switch command case program code break case ISDN DATA ACCESS 获取信号量 Lock 读写数据代码 program code 释放信号量 unLock break default break return OK 北京世纪百合技术有限公司 软件编程建议 第 15 页 共 16 页 任务在调用该函数时 只有在执行该段代码时才获取信号量 直到完成该段代码后 才释放信号量 如果另一任务同时执行该段代码 会因为没有信号量进入 PEND 状 态 直至信号量被释放 2 4 22 4 2 公共模块函数可能同时被多个任务同时调用 这些函数应该考虑重入问题 公共模块函数可能同时被多个任务同时调用 这些函数应该考虑重入问题 说明 2 4 2 2 4 3 节讲述的是这些函数的特殊情况下的特殊处理方式 一般函数的 重入问题只要不使用全局变量即可解决 2 4 32 4 3 由其它任务调用的接口函数 如果某种操作可能与本任务正在进行的操作出由其它任务调用的接口函数 如果某种操作可能与本任务正在进行的操作出 现冲突时 应

温馨提示

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

评论

0/150

提交评论