第七章:高质量的子程序

在子程序层上设计
功能的内聚性:是最强也是最好的一种内聚性,让一个子程序仅执行一项操作。
顺序上的内聚性:子程序内包含有需要按特定顺序执行的操作,这些操作需要共享数据。在全部执行完后,才算完成了一项完整的功能。
通信上的内聚性:一个子程序中的不同操作使用了同样的数据,但不存在其他任何联系。
临时的内聚性:是指含有一些因为需要同时执行才放到一起的操作。
一般来说,其他类型的内聚性都是不可取的。举例如下:
过程上的内聚性:把一组操作赋予特定的顺序,而在该子程序内,这些操作并没有原因彼此关联
逻辑上的内聚性:若干缺乏逻辑关联操作被放入同一子程序中,通过传入的控制标志选择执行其中的一项。
巧合的内聚性:子程序中的各个操作没有什么关联。
好的子程序名字
  • 描述子程序所做的所有事情
  • 避免使用无意义的模糊或者描述不清的动词
  • 根据需要确定名字长度
  • 函数的名字最好能表达出返回值的描述
  • 确立命名规则
理论上子程序的长度应该不要超过200行。
如何使用子程序参数
按照参数用途:输入-修改-输出的顺序排列参数
如果几个子程序都用了类似的参数,应该让参数顺序保持一致
使用所有的参数
把状态或出错变量放到最后
不要把子程序的参数用作工作变量
在接口中对参数的假定加以说明,一种比注释更好的方法是使用断言assertions
需要说明的如下:
参数用途是输入、还是修改、还是输出
表示数量的参数的单位
所能接受的数值范围
不该出现的特定数值
把子程序的参数数目限制在7个以内
考虑对参数采用某种表示输入、修改、输出的命名规则。如加上i_ m_ o_的前缀
为子程序传递用以维持其接口抽象的变量或对象。子程序需要的参数取决于需要表达的抽象。
确保实际参数与形式参数相匹配。
使用函数时要考虑的问题
函数永远应该以它的返回值来命名,如果一个子程序的用途就是返回一个由它名字指示的值,那么就用函数,否则使用过程。
检查所有可能的返回路径
不要返回指向局部数据的引用或指针
宏子程序和内联子程序
把宏表达式整个包含在括号里
把含有多条语句的宏用大括号括起来
用给子程序命名的方法来给展开后的宏命名,以便在需要时可以把宏替换为子程序
高质量的子程序
子程序中是否有适合单独提出的部分?
过程的名字是否用了“动词 宾语”词组?函数名字是否描述了其返回值?
是否给常用操作建立了命名规则?
是否具有功能上的内聚性?即子程序只做一件事?
子程序之间是否有松散的耦合?子程序之间的连接是否是小的、明确的、可见的、灵活的?
子程序的参数表是否表现出一种具有整体性且一致性的抽象?
子程序参数的排列顺序是否合理?
子程序的参数是否没超过7个?
是否避免了把参数用作工作变量?
如果子程序是一个函数,那么它在考虑所有情况下,返回值是否合法?