《代码大全》读书笔记:第7章——高质量的子程序

来源:百度文库 编辑:神马文学网 时间:2024/04/27 20:58:25
《代码大全》读书笔记:第7章——高质量的子程序
开始拜读《代码大全》,顺便写些读书笔记,不打算每一章都写,没这个必要。先从第七章开始。
7.1 创建子程序的正当理由
简单地列举,就是:降低复杂度、引入中间的易懂的抽象、避免代码重复、支持子类化、隐藏顺序、隐藏指针操作、提高可移植性、简化复杂的逻辑判断、改善性能;等等。
其实这些理由之间都是有联系的。其中关于可移植性的部分,如果子程序设计得好,可以把底层的、会随着环境而变化的部分抽象出来,写成一个函数,高层部分调用该函数的代码不需要改动,方便了移植。
7.2 在子程序层上设计
Unix的哲学之一就是:保持高内聚、低耦合。这里谈到内聚,可简单理解为:子程序中的各种操作之间联系的精密程度。而Unix另外一个哲学是:每次只做一件事并且做好。所以子程序的目标就是只把一件事做好,不管是多小的事。
可取的内聚性包括:
A. 功能的内聚性:最强最好的一种内聚,让一个子程序仅仅执行一项操作。可惜现实中中仅编写这种子程序往往是不现实的,所以还有一下3种差强人意的内聚;
B. 顺序上的内聚性:子程序中包含特定顺序执行的操作。
C. 通信上的内聚性:子程序中的不同操作使用了同样的数据。这种平时我倾向于不用。
D. 临时的内聚性:含有一些因为需要同时执行才放到一起操作的子程序。比如说,系统开始运行时读取一些杂七杂八的东西。
如果只编写A类的子程序,个人认为基本不现实,而且会造成子程序太繁多,而对于剩下3类,关键在于如何设计让程序的逻辑性更强,更容易让人理解。其他内聚都是不可取的,如书中谈到的:过程上的内聚性,逻辑上的内聚性和巧合的内聚性。其中,逻辑上的内聚性是指若干操作放到同一个子程序中,通过传入参数来选择执行哪一项。通常会让子程序产生一个长长的if-else,或者switch/case。比较好的做法就是:写几个子程序来分别执行各自的操作。
7.3 好的子程序名字
1)描述子程序所做的所有事情。如果你的子程序设计得好,那么给子程序起个好的名字应该不难;反之,如果写的是一个有副作用的子程序,那就会起长又笨的名字。
2)避免使用无意义的、模糊或表达不清的动词。比如:HandleOutput,这样的名字太泛,无法准确描述。
3)不要通过数字来形成不同的子程序名字。不用多说,傻X才这么做。
4)根据需要确定子程序名字长度。变量名最佳长度为:9到15. 子程序可稍微长点,自己把握。
5)给函数命名时要对返回值有所描述。比如:printer.IsReady(),简洁明了。
6)使用动词加宾语形式。比如:ftp_do_download()。
7)准确适用对仗。如:add/remove, begin/end, insert/delete;等等。
7.4 子程序可以写多长
关于这个话题,众说纷纭。我们比较偏向于编写短小的子程序。我对于子程序的最小长度没有限制,几行的子程序也有;书中说到最大长度为143行(包括注释)以内最佳,通常我们也是这么做。我对200行以上的子程序总是心存畏惧。
7.5 如何使用子程序参数
1)按照输入-修改-输出的顺序排列参数。好建议,符合人的正常思维逻辑。通常我们也是会不自觉地如此安排顺序。
2)考虑创建自己的IN和OUT参数。我没有定义过,觉得没必要,不过以后确实有必要也可以尝试。
#define IN
#define OUT
void PrintPageNum(IN int pageNum, OUT boolean status);
3)三句简单道理:如果几个子程序使用类似参数,应该让这些参数的顺序保持一致;使用所有参数;把状态或出错变量放在最后。
4)不要把子程序参数用作工作变量。比较好的做法是重新定义一个工作变量。
5)在接口中对参数假定加以说明。即要判断参数的有效性。
6)把子程序的参数个数限制在7个以内。一般情况我觉得5个参数已经算多了。呃,想起了windows的API,不说了。
7.6 使用函数时要特别考虑的问题
先说函数和过程的区别:函数是指有返回值的子程序;过程是指没有返回值的子程序。书中的观点貌似倾向于给每个函数设置一个返回值,但对于这点我觉得要根据实际情况而定。
7.7 宏子程序和内联子程序
对于宏的使用,我主要用来定义常量。如果你的宏包含多条语句,那就用一个大括号括起来,以防出现副作用。另外,内联子程序,即inline函数的使用也要小心。C++要求把inline写进头文件,这违反了封装性;另外inline由于是生成子程序的全部代码,无疑造成整个代码长度的增长。这两种东西,慎用。
END