创建子程序的正当理由
-
降低复杂度;
-
引入中间,易懂的抽象(一堆的if,switch等,肯定不如一个GeName()来的易懂);
-
避免代码重复;
-
支持子类化(类派生)
-
隐藏顺序(处理顺序执行事情的代码,可以封装到子程序中)
-
隐藏指针操作(指针的可读性差,且容易出错)
-
提高可移植性
-
简化复杂的布尔判断(复杂的bool判断放入函数中,利用具有概括性的名字代替可提高可读性)
-
改善性能(代码集中在一处,方便优化,方便使用)
-
创建类的很多理由也是创建子程序的理由(见二章节的内容)
1、在实现函数时,可能需要考虑的一些问题
- 函数的名字,能否做到“望文知义”?
- 子程序是否需要注释?
- 子程序的布局是否一致?
- 子程序的参数个数,const,&的使用是否合理正确?
- 子程序的功能是否单一(内聚性强)?
- 子程序是否有防范错误输入?
- 其他-这些问题问完,函数也该完美了吧
2、内聚性的层次
- 功能的内聚性:最好也是最强的内聚性,即让子程序仅执行一项操作
- 顺序上的内聚性:指在子程序中包含需要按特定顺序执行的操作
- 通信上的内聚性:即子程序的不同操作使用了相同的数据,但不存在其他任何联系(如某个函数先利用传入的数据汇总显示,再将数据初始化。可以分成两个子程序)
- 临时的内聚性:指一些需要同时执行的操作放到一个子程序中。如StartUp()中放了一大堆不相关的代码等
3、不可取的内聚性
- 过程上的内聚性:指一个子程序的操作是按照特定的顺序进行的
- 逻辑上的内聚性:若干操作被放入一个子程序,通过传入的标志选择其中一项操作(Envent Handler是特例)
- 巧合的内聚性:子程序中各操作没有任何关联,也称为无内聚性或混乱的内聚性
4、断言
- 建立自己的断言机制
- 用错误处理代码处理预期发生的状况,用断言处理绝不会发生的状况
- 避免把要执行的代码放入断言中
- 用断言注解并验证前条件和后条件
- 高健壮性的代码,应该先使用断言再处理错误
5、错误处理技术
- 返回中立值:返回一个没有危害的值如0,空串等
- 返回下一个正确的数据:如读数据库时发现一条记录损坏,可以继续读下去
- 返回与前次相同的值
- 换用最接近的合法值
- 把警告信息记录到日志文件
- 返回错误码
- 调用错误处理子程序或对象
- 当错误发生时,显示出错消息
- 用最妥当的方式在局部处理错误
- 关闭程序
具体用何种方式,视具体情况而定。
6、异常
审慎明智地适用,可以降低复杂度,草率粗心,只会让代码无法理解
一些建议:
- 用异常通知程序的其他部分,发生了不可忽略的错误:异常的优越之处在于它能提供无法被忽略的错误通知机制。
- 只在真正例外的情况抛出异常:即其他编码实践无法解决的情况下才使用异常。
- 不能用异常推卸责任:若错误能在局部处理,则处理之。
- 避免在构造函数和析构函数中抛出异常,除非在同一地方把它们捕获
- 在恰当的抽象层次抛出异常:如不要把更底层的异常抛给调用方。
- 在异常消息中加入异常发生的全部信息
- 避免使用空的catch语句:有时你可能试图敷衍一个不知如何处理的异常,请不要这样做,若确实有需要,请说明原因
- 了解所用函数库可能抛出的异常
- 考虑创建一个集中的异常报告机制
- 把项目中对异常的使用标准化
- 考虑异常的替换方案