第七章 高质量子程序

一、何为子程序?

子程序是为实现某一特定目的而编写的方法或过程。

二、为何写子程序?

1、可以降低复杂度。如果面临一个复杂逻辑,通过子程序可以有效分解逻辑,比如将一些列操作封装起来,通过函数名来传递某种逻辑。

2、提高可移植性。如果想要某个程序有很高的可移植性,可以通过子程序将与硬件或非语言标准的东西隔离开,达到更高的可移植性。

3、避免重复代码。重复的代码在维护上带来麻烦,同时也占据了不必要的空间,如果两段程序中出现了类似的代码,则说明程序的分解上出现问题,并且改动起来会加大麻烦。

4、隐藏操作。对于使用指针、全局变量或者复杂布尔判断的地方,可以用子程序进行封装,这样可以更专注于本身要解决的问题。

三、如何设计子程序?

一般来说,一个子程序只实现某一特定目的,所以子程序的设计主要原则为增强子程序的内聚性。

1、如果一个子程序只实现单一功能,例如sin(),则可认为其具有很强的内聚性。

2、如果一个子程序中出现两种功能,并且两种功能只是用了相同的数据,并没有其他联系,则称之为通信内聚性。例如,将一份报表中的值打印后又将报表中的值进行重置。这个例子中,两个操作--打印和重置只是用了相同的数据,而没有进一步的联系,所以这种子程序的内聚性是不如功能内聚性强的。如果将打印和重置分别放到不同子程序,再由更高层次的子程序来调用两个子程序,则其内聚性提高。

3、如果一个子程序中存在只是需要同时执行才放到一起的操作,则称之为临时内聚性。比如说系统的启动需要读取不同配置文件,初始化临时文件,设置管理器等。对此可用临时内聚性的子程序分别调用各个每个操作所构成的子程序而不是由它直接执行所有的操作。

四、如何命名子程序?

1、描述子程序所做的所有事情。好的子程序命名通常起到子解释子程序功能的作用。

2、避免使用无意义的、模糊或表达不清的动词。有些词语表达非常灵活,可以延伸到涵盖几乎任何含义。例如HandleOutput()改成FormatAndPrintOutput(),就很清楚这个子程序的功能了。

3、不要仅适用于数字来形成不同的子程序名字。例如OutputUser.OutputUser1、OutputUser3这种子程序名字后面的数字无法显示出子程序所代表的抽象有何不同。

4、给过程起名时使用语气强烈的动词家宾语的形式。例如PrintDocument()、CalcMonthlyRevenues()、CheckOrderInfo()等都是不错的名字。在面向对象语言中,不用在过程名中接入对象的名字(宾语),因为对象本身已经包含在调用语句中了,可以用document.Print(),OrderInfo.Check()来表达。document.PrintDocument()这样的语句不仅显得太臃肿,并且在他们的派生类中被调用时也容易产生误解。如Check(支票)类是从Document(文档)类继承而来的,那么check.Print()就很显然表示打印一张支票,而check.PrintDocument()看上去就像是要打印支票簿或信用卡的对账单而不是想要打印支票本身。

5、准确使用对仗词。命名时遵守对仗词的命名规则有助于保持一致性。下面是一些常用队长词组:

add/remove     increment/decrement    open/close
begin/end      insert/delete          show/hide
create/destroy lock/unlock           source/target
first/last     min/max               start/stop
get/put        next/previous         up/down
get/set        old/new

6、为常用操作确立命名规则。在不同的系统里,区分不同类型的操作非常重要。例如获取对象的id操作:

假如某个项目中的每个对象都被分配了一个唯一标识,由于忽视为返回这种对象标识的子程序建立一个命名规则,以至于有了下面命名:

employee.id.Get()
dependent.GetId()
supervisor()
candidate.id()

其中:Employee类提供了其id对象,而该对象有进而提供了Get()方法;Dependent类提供了GetId()方法;SuperVisor类把id作为它的默认返回值;Candidate类则认为id对象的默认返回值是id,因此暴露了id对象。这样一来,一个id对象的获取就有这么多细节需要考虑,而这些问题完全可以通过建立获取id的命名规则而避免。

五、子程序应该多长?

一般来说,最大长度为100-150是一个不错的区间,当一个子程序超过200行时就应该特别注意了,通常这样的程序迟早会在可读性上遇到问题。

六、子程序的参数使用?

1、参数应该按照输入-修改-输出的顺序传递。这样传递正好与子程序输入、处理、输出的执行顺序一致。但是在c语言中,是按照修改的参数排在前面的顺序排列的。选用某种方式最好一致采用它,至少在整个项目中都是按照某种规则进行。

2、考虑定义自己的IN和OUT关键字。在这里,IN和OUT只是起到说明作用,如果想要改变参数的值,仍然需要传递指针或引用。在应用这项技术之前,有两个方面尤须注意。1)IN和OUT扩展了标准语言,可能会使得使用这个语言的人感到生疏。2)即使采用了IN,仍然可以在子程序中更改参数的值,而在别人看来,会认为子程序的功能是正确的,从而造成误解。注:在c++中,应该采用const关键字进行输入限定。

3、如果几个子程序都采用了类似的参数,则应该让它们的参数顺序保持一致。例如printf和fprintf只是前面多了一个f,所以其参数方面应该保持顺序一致,不要因为这样一个小小的顺序问题而导致记忆困难。

4、状态和出错变量应该参数表的最后。对于状态和出错变量,他们只是程序的附属功能,而且他们是仅用于输出的参数,因此这是一种很有道理的原则。

5、不要把子程序的参数用作工作变量。应在子程序中另外申请局部变量。如果将参数用作工作变量,由于已经在程序中改变参数的值,如果在子程序的某个地方要使用原有输入参数的值,就会出现错误。

6.在接口中对参数的假定加以说明。如果你假定了传给子程序的参数具有某种特征,就应该对这种假定加以说明。哪些参数假定需要加以说明呢?

1)参数是仅用于输入的、还是修改的、还是仅用于输出的。

2)表示数量的参数的单位(英寸、英尺、米等)。

3)如果没有枚举的话,应该说明状态代码和错误的含义。

4)所能接收的数值的类型。

5)不该出现的特定数值。

7、把子程序的参数个数限定在7个以内。如果你发现自己一直要传递很多参数,这就说明子程序之间的耦合太过紧密了,应该重新设计这个或这组子程序,降低期间的耦合度。如果你向很多不同的子程序传递相同的参数,就请把这些子程序组成一个类,并把那些经常用到的数据用作类的内部数据。

8、考虑对对参数采用某种表示输入、修改和输出的命名规则。如果你觉得把输入、修改、输出参数区分开很重要,那么就建立一种命名规则来对它们进行区分。

9、为子程序传递用以维持其接口抽象的对象或变量。比如说你有一个对象,它通过10个访问器子程序暴露其中的数据,被调用的子程序只需要其中的3项就能进行操作。如果要表达的抽象是子程序期望3项特定的值,但这3项特定的值只是碰巧由同一个对象所提供的,那就应该单独传递着3项数据。然而,如果子程序接口要表达的抽象是一直拥有某个特定对象,且该子程序要对这一对象执行这样、那样的操作,如果单独传递3项特定的数据,那就是破坏了几口的抽象。

如果你采用传递整个对象的做法,并发现自己是先创建对象,把被调用子程序所需的3项数据填入该对象,在调用过子程序后又从对象中取出3项数据的值,那就是一个证据,说明你应该只传递那3项数据而不是整个对象。(一般来说,如果在调用子程序之前出现装配的代码,或者在调用子程序之后出现拆卸的代码,都是子程序设计不佳的表现。)

如果你发现自己经常需要修改子程序的参数表,而每次修改的参数都是来自于同一个对象,那就说明你应该传递整个对象儿不是个别参数项了。

10、确保实际参数和形式参数相匹配。请养成好习惯,总是检查参数表中参数的类型,并对编译器给出的类型警告予以留意。

七、子程序的返回值?

1、检查所有可能的返回路径。应该确保所有的路径都有返回值。

2、不要返回局部变量的指针或引用。

八、宏子程序使用?

1、将宏表达式整个包含在括号中。将宏表达式包含在括号中是为了防止展开后出错和优先级问题。

2、将含有多条语句的宏用大括号括起来。这样做是为了在循环等操作中只执行一条语句,而其他语句没有执行。

时间: 2024-10-07 06:58:33

第七章 高质量子程序的相关文章

第七章,编写程序

在我们把做好了准备工作之后,就应该着眼于编写程序,这是一个程序员必须要熟练掌握的一门技术,但是,编写程序也有方法,如何更简单,快速,高效的编写程序,在本章中都有介绍. 标准和过程可以帮助你去组织你的想法和避免错误. 一旦你的代码完成了,其他人有可能在各种场合使用它.,所以组织.规范.文档化你的代码以使他人很容易的理解它是如何开发和工作的就变得非常重要.我们要在编写程序中规范自己的代码,为了自己以后方便,也为了他人能够理解. 而在编写程序中,算法,控制结构,数据结构也十分重要.算法是决定程序好坏的

《Linux高性能服务器编程》学习总结(七)——Linux服务器程序规范

第七章      Linux服务器程序规范 服务器程序除了需要网络通信外,还应该考虑很多其他的细节,而这些细节很多很杂,但又基本是模板式的.1)服务器程序基本都是以后台形式运行的,没有控制终端,不能接受用户输入,其父进程通常是init.2)服务器程序有一套日志系统.3)服务器程序以某个专门的非root身份运行.4)服务器通常是可配置的.5)服务器进程启动时通常会生成一个PID文件以记录后台进程的PID.6)服务器程序同城需要考虑系统资源和限制. 服务器一般使用syslog函数与rsyslogd守

第七章 数组实验

实验项目: 1.一维数组的运用 2.二维数组的应用 3.字符数组的应用 姓名:陈福洲  实验地点:教学楼514教室  实验时间:2019.5.29 一.实验目的与要求 1.掌握一维和多维数组的定义和数组元素的引用方法. 2.了解一维和多维数组初始化方法. 3.学习一维和多维数组的基本算法. 4.掌握数组的定义.初始化方法及其元素的引用方法. 5.掌握c语言提供的对字符串进行处理的基本函数库. 二.实验内容 一维数组的应用(7.3.1) 实验练习1:(1)问题的简单描述:编写程序,利用随机函数产生

linux程序设计——CD唱片应用程序(第七章)

7.4 CD唱片应用程序 这篇为第七章的CD唱片应用程序,代码在CD唱片应用程序代码下载.我们使用dbm数据库对数据存储,改进之前的CD唱片应用程序. 7.4.1 更新设计 虽然在文件中以逗号分隔变量来存储信息是一种在shell中很容易实现的方式,但是这样局限性很大,因为许多CD标题和曲目都包含逗号.可以通过使用dbm数据库来改进这种方法. 将CD资料分为标题和曲目两个部分,并用不同的文件来保存它们. 前面的实现存在一个问题,即将应用程序的数据访问部分和用户接口部分混在了一起,这与程序全实现在一

2014年软考程序员-常考知识点复习笔记【第七章】

51CTO学院,在软考备考季特别整理了"2014年软考程序员-常考知识点复习笔记[汇总篇]",帮助各位学院顺利过关!更多软件水平考试辅导及试题,请关注51CTO学院-软考分类吧! 查看汇总:2014年软考程序员-常考知识点复习笔记[汇总篇]  数组和链表的优缺点 数组,在内存上给出了连续的空间.链表,内存地址上可以是不连续的,每个链表的节点包括原来的内存和下一个节点的信息(单向的一个,双向链表的话,会有两个). 数组优于链表的: A. 内存空间占用的少,因为链表节点会附加上一块或两块下

读《程序是怎么跑起来的》第七章有感

第七章程序是在何种环境中运行的,应用的运行环境是指操作系统和计算机(硬件)的种类应用的运行环境主要是用类似于Windows(OS)和AT兼容机(硬件),这样的OS和硬件的种类来表示.不同的硬件种类需要不同的操作体统,应用是为了在特定操作系统上运行而作成的.FreeBSD是一种Unix操作系统,通过各个环境中编译Ports中公开的代码,就可以执行有此可以生成的本地代码了,而模拟器是指在Macintosh上提供虚拟的Windows环境,只要分别为各个环境安装专用Java虚拟机,同样的字节代码就能在各

程序设计基础 第七章 数组与字符串

第七章 数组与字符串 A总结: 1.数组是同类型的集合,同一个数组的数组元素具有相同的数据类型,引用数组就是引用数组的各元素,通过下标的变化可以引用任意一个数组元素,注意不要进行下标越界的引用,那样会带来副作用. 2.数组类型在数据处理和数值计算中有十分重要的作用,数组与循环的结合可以解决很多的问题. 3.数组可以根据下标的多少分类:一维数组(一个下标)……… 4.C语言使用字符数组来存放字符串,该字符数组中包含一个’\0’字符,代表字符串的结尾. B解析: 7.1:数组的基本概念 :按一定的顺

构建之法学习(第七章 MSF)

第七章 MSF MSF(Microsoft Solution Framework)微软解决方案框架: MSF是一套大型系统开发指南,是微软推荐的软件开发方法,它描述了如何用组队模型.过程模型和应用模型来开发Client/Server结构的应用程序,是在微软的工具和技术的基础上建立并开发分布式企业系统应用的参考. 一.MSF 9条基本原则 1.推动信息共享与沟通 --把所有信息都保留并公开,讨论要包括所有涉及的角色,决定要公开并告知所有人. 当然,对牵涉到技术机密.安全性等信息要采取必要的保护措施

Android开发艺术探索——第七章:Android动画深入分析

Android开发艺术探索--第七章:Android动画深入分析 Android的动画可以分成三种,view动画,帧动画,还有属性动画,其实帧动画也是属于view动画的一种,,只不过他和传统的平移之类的动画不太一样的是表现形式上有点不一样,view动画是通过对场景的不断图像交换而产生的动画效果,而帧动画就是播放一大段图片,很显然,图片多了会OOM,属性动画通过动态的改变对象的属性达到动画效果,也是api11的新特性,在低版本无法使用属性动画,但是我们依旧有一些兼容库,OK,我们还是继续来看下详细