代码编程规范-扩展(函数)
扫描二维码
随时随地手机看文章
前言
这篇重点介绍一下代码编程规范的扩展要求-函数规范要求
函数设计的精髓:编写整洁函数,同时把代码有效组织起来。
整洁函数要求:代码简单直接、不隐藏设计者的意图、用干净利落的抽象和直截了当的控制语句将函数有机组织起来。
代码的有效组织包括:逻辑层组织和物理层组织两个方面。逻辑层,主要是把不同功能的函数通过某种联系组织起来,主要关注模块间的接口,也就是模块的架构。物理层,无论使用什么样的目录或者名字空间等,需要把函数用一种标准的方法组织起来。例如:设计良好的目录结构、函数名字、文件组织等,这样可以方便查找。
规范要求
【规范1】一个函数仅完成一件功能
一个函数实现多个功能给开发、使用、维护都带来很大的困难。
将没有关联或者关联很弱的语句放到同一函数中,会导致函数职责不明确,难以理解,难以测试和改动。
【规范2】重复代码应该尽可能提炼成函数
原因:重复代码提炼成函数可以带来维护成本的降低。
当一段代码重复两次时,即应考虑消除重复,当代码重复超过三次时,应当立刻着手消除重复
当一段代码逻辑相同,但是内部的部分变量和输出不同,可以进行提炼成函数,内部的不同变量作为入参等方式(有些逻辑相同的可以使用表驱动方式)
【规范3】避免函数过长,新增函数不超过 50 行 (非空非注释行)
原因:
过长的函数往往意味着函数功能不单一,过于复杂
延伸阅读材料:业界普遍认为一个函数的代码行不要超过一个屏幕,避免来回翻页影响阅读(根据实际情况可以超过 50 行,自行把握)
【规范4】避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层
函数的代码块嵌套深度指的是函数中的代码控制块(例如:if、for、while、switch等)之间互相包含的深度
原因:每级嵌套都会增加阅读代码时的脑力消耗,需要记住前一级的状态,不利于代码阅读
做法:可以使用平级的代码控制块,如// 错误示例 void serial(void) { if (...) { if (...) { if (...) { ...; } } } } // 正确示例 void serial(void) { if (!...) { return; } if (!...) { return; } ...; }
【规范5】对参数的合法性检查,如果公司有相关规定,则按照规定走,如果没有,则由接口函数负责。
对于模块间接口函数的参数的合法性检查这一问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这一必要的处理过程,造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。
【规范6】检查函数所有非参数输入的有效性,如数据文件、公共变量等
函数的输入主要有两种:一种是参数输入;另一种是全局变量、数据文件的输入,即非参数输入。函数在使用输入参数之前,应进行有效性检查,防止调用者使用函数时传入不合理的入参,导致系统崩溃
【规范7】函数的参数个数不超过5个
函数的参数过多,会使得该函数易于受外部(其他部分的代码)变化的影响,从而影响维护工作。函数的参数过多同时也会增大测试的工作量。
函数的参数个数不要超过5个,如果超过了建议拆分为不同函数,或者使用结构体作为入参(结构体作为入参时,尽量使用使用指针传递,提高效率)
【规范8】函数中的不变参数或者函数入参在函数内不会改变使const
不变的值更易于理解/跟踪和分析,把const作为默认选项,在编译时会对其进行检查,使代码更牢固/更安全
对应调用者而言,函数的入参如果是const, 则一眼就能明白哪些是入参
【规范9】函数入参的定义顺序应是输出参数比输入参数先定义
主要是统一规范,如函数memcpy、sprintf、memset等等,输出参数都是在函数的入参中先定义
【要求 10】函数应避免使用全局变量、静态局部变量和 I/O 操作,不可避免的地方应集中使用
实际开发过程中,难免会存在函数使用全局变量、静态局部变量和 I/O 操作,但是为了提高代码阅读性,建议集中使用
【规范11】在源文件范围内声明和定义的所有函数,除非外部可见,否则应该增加static关键字
如果一个函数只是在同一文件中的其他地方调用,那么就用static声明。使用static确保只是在声明它的文件中是可见的,并且避免了和其他文件或库中的相同标识符发生混淆的可能性;且在阅读上能迅速了解哪些是非公开函数。





