Chapter 7 High-Quality Routines (Page 198-223)
高质量的子程序
7.1 Valid Reasons to create a Routine
创建子程序的正当理由
1. 降低复杂度
2. 引入中间,易懂的抽象
3. 避免代码的重复
代码分解(decomposition)
4. 支持子类化覆盖(subclassing override)
5. 隐藏顺序
6. 隐藏指针操作
指针操作的可读性通常很差,且易出错。通过把这些操作隔离在子程序内部,你就可以把精力集中于操作的意图本身,而不
是指针操作机制的细节。
7. 提高可移植性
8. 简化复杂的布尔判断
9. 改善性能
把代码集中在一处可以更方便地查出哪些代码的运行效率低下。、
10. 确保所有的子程序都很小
避免下面的观点:
Operations That Seem Too Simple to Put Into Routines
似乎过于简单而没有必要写成子程序的操作
7.2 Design at the Routine Level
在子程序层上设计
内聚性(cohesion),是指子程序中各种操作之间联系的紧密程度。
关于内聚性cohesion的讨论一般会涉及到内聚性的几个层次。以下概念可以帮助你思考如何让子程序尽可能地内聚。
功能的内聚性(functional cohesion)
它是最强也是最好的一种内聚性,也就是说让一个子程序仅执行一项操作。
除此之外,还有其他的内聚性人们却通常认为不够理想的。
顺序上的内聚性(sequential cohesion)
通信上的内聚性(communicational cohesion)
临时的内聚性(temporal cohesion)
过程上的内聚性(procedural cohesion)
逻辑上的内聚性(logical cohesion)
巧合的内聚性(coincidental cohesion)
7.3 Good Routine Names
好的子程序的名字
1. 描述子程序所做的所有事情
2. 避免使用无意义的,模糊或表述不清的动词。
3. 不要紧通过数字来形成不同的子程序名字
4. 根据需要确定子程序名字的长度
研究表明,变量名的最佳长度是9-15个字符。
5. 给函数命名时要对返回值有所描述
6. 给过程命名时使用语气强烈的动词加宾语的形式
7. 准确使用对仗词。
8. 为常用操作确立命名规则
7.4 How Long can a routine Be
子程序可以写多长
理论上认为的子程序最佳最大长度通常是一屏代码或打印出来1到2页的代码,也就是约50-150行代码。
人们在子程序长度问题上积累了大量的研究成果,其中适用于现代编程:
1. 子程序长度和错误量成反比。
2. 另一项研究发现,子程序的长度与错误量没有关联,而结构复杂度以及数据量却与错误量有关。
3. IBM研究发现,最容易出错的是那些超过500行代码的子程序。超过500行之后,子程序的出错率就会与其长度成正比。
总结,如果编写超过200行代码的子程序,那你要小心了。对于超过200行代码的子程序来说,没有哪项研究发现它能降低成本和/或
降低出错率,而且在超过200行后,你迟早会在可读性方面遇到问题。
7.5 How to Use Routine Parameters
如何使用子程序参数
1. 按照输入-修改-输出的顺序排列参数
2. 考虑自己创建in和out关键字
例如,C++中,可以预定义IN和OUT这两个宏关键字只是起到说明性的作用。
3. 如果几个子程序都用了类似的一些参数,应该让这些参数的排列顺序保持一致。
子程序的参数顺序可以产生记忆效应----不一致的顺序会让参数难以记忆。
4. 使用所有的参数
如果传递了一个参数,就一定要用到这个参数。如果不用它,则要把它从子程序的接口中删去。未用到的参数和出错率的增
加不无关系。成正比的。
5. 把状态或出错变量放在最后
6. 不要把子程序的参数用做变量
7. 在接口中对参数的假定加以说明
8. 把子程序的参数个数限定在大约7个以内。
心理学研究发现,通常人类很难同时记住超过7个单位的信息。
9. 考虑对参数采用某种表示输入,修改,输出的命名规则
10. 为子程序传递用以维持其接口抽象的变量或对象
传递3项值好?还是传递对象(包括10项值)好呢?这要看:子程序的接口要表达何种抽象?
11. 使用具名参数
12. 确保实际参数与形式参数相匹配
形式参数也称为“哑参数(dummy parameters)”,是指在子程序定义中声明的变量。
实际参数是指在实际的子程序调用中用到的变量,常量或者表达式。
7.6 Special Considerations in the Use of Functions
使用函数时要特别考虑的问题
1. When to use a Function and When to use a Procedure?
2. Setting the Function's Return Value
设置函数的返回值
a. 检查所有可能的返回路径
b. 不要返回指向局部数据的引用或指针
3. Macro Routines and Inline Routines
宏子程序和内联子程序
Key Points 要点
1. 创建子程序最主要的目的是提高程序的可管理性,当然也有其他一些好的理由。其中,节省代码空间只是一个次要的原因;提高
可读性,可靠性和可修改性等原因都更要重要一些。
2. 有时候,把一些简单的操作写成独立的子程序也非常有价值。
3. 子程序可以按照其内聚性分为很多类,而你应该让大多数子程序具有功能上的内聚性,这是最佳的一种内聚性。
4. 子程序的名字是它的质量的指示器。如果名字糟糕但恰如其分,那就说明这个子程序设计的很差劲。如果名字糟糕而且有不准确
,那么他就反映不出程序是干什么的。不管怎样,糟糕的名字都意味着程序需要修改。
5. 只有在某一个子程序的主要目的是返回由其名字所描述的特定结果时,才应该使用函数。
6. 细心的程序员会非常谨慎的使用宏,而且只在万不得已时才用。