除了计算机本身之外,子程序可以说是计算机科学最重大的发明。子程序使得程序非常好 读而且也非常容易理解,编程语言中的任何特性都不能和这一点相比。
一. 生成子程序的原因
降低复杂性:使用子程序的最首要原因是为了降低程序的复杂性,可以使用子程序来隐含 信息,从而使你不必再考虑这些信息。
限制了改动带来的影响:
要把最可能改动的区域设计成最容易改动的区域。最可能被改动的区域包 括:硬件依赖部分、输入输出部分、复杂的数据结构和商务规则。
改进性能:通过使用子程序,可以只在一个地方,而不是同时几个地方优化代码段。把相 同代码段放在子程序中,可以通过优化这一个子程序而使得其余调用这个子程序的子程序全部 受益。把代码段放入子程序也使得用更快的算法或执行更快的语言(如汇编)来改进这段代码 的工作变得容易些。
进行集中控制 。在一个地方对所有任务进行控制是一个很好的想法
· 改善某一代码段可读性
· 简化复杂的布尔测试
二 子程序名称恰当
对于过程的名字,可以用一个较强的动词带目标的形式。
对于函数名字,可以使用返回值的描述。
避 免 无 意 义 或 者 模 棱 两 可 的 动 词 。
描述子程序所做的一切
三 强内聚性
强调强相关性的目的是, 每一个子程序只需作好一项工作,而不必过分考虑其它任务。
弱内聚性子程序的出错机会要比强内聚性出错机会 高 6 倍,而修正成本则要高 19 倍( Selby 和 Basili 1991 )
1 可取的内聚性
功能内聚性。功能内聚性是最强也是最好的一种内聚,当程序执行一项并且仅仅是一项工 作时,就是这种内聚性,这种内聚性的例子有: sin(), GetCustomerName(), EraseFile(),
顺序内聚性
顺序内聚性是指在子程序内包含需要按特定顺序进行的、逐步分享数据而又 不形成一个完整功能的操作,
通讯内聚性。通讯内聚性是在一个子程序中,两个操作只是使用相同数据,而不存在其它 任何联系时产生的
,在 GetNameAndChangePhoneNumber()这个子程序中,如果 Name 和 PhoneNumber 是放在同一个用户记录中的,那么这个子程序就是通讯内聚性。这个子程序从事 的是两项而不是一项工作,因此,它不具备功能内聚性。 Name 和 PhoneNamber 都存储在用户 记录中,不必按照某一特定顺序来读取它们,所以,它也不具备顺序内聚性。
临时内聚性。因为同时执行的原因才被放入同一个子程序里,这时产生临时内聚性
2 不可取的内聚性
过程内聚性。当子程序中的操作是按某一特定顺序进行的,就是过程内聚性
逻辑内聚性。当一个子程序中同时含有几个操作,而其中一个操作又被传进来的控制标志 所选择时,就产生了逻辑内聚性。
偶然内聚性。当同一个子程序中的操作之间无任何联系时,为偶然内聚性。也叫作“无内 聚性”。
四 松散耦合性
1 耦合标准 子程序之间具有良好耦合的特点是它们之间的耦合是非常松散的,任一个子程序都能很容 易地被其它子程序调用。
火车车箱之间的联接是非常容易的,只要把两节车箱推撞到一起,挂 钩就会自动挂上,想象一下,用螺栓把它们固定到一起,或者只有特定的车厢之间才能联接到 一起,那么事情将会有多么麻烦。火车车厢之间的联接之所以非常容易,是因为它们的联接装 置非常简单。同样,在软件中,也应该使子程序之间的耦合尽量简单。
如果一个子程序越容易被其它子程序调用,那么它的耦合程度也就越低。这样 的好处是可以增强灵活性和维护性。在建立系统结构时,应该沿着相互耦合程度的最低线将其 分开。
最好的耦合方式:简单数据耦合。如果两个子程序之间传递的数据是非结构化的,并且全部都是通过参数表 进行的,这通常称作“正常耦合”,这也是一种最好的耦合。
五 子程序的长度
最近研究发现,当子程序长度是 100 到 150 行时,错误率最低
六 放错性编程
即使一个子程序被传入了坏数据,它也不会被伤害,哪怕这个数据是由其它子程序错误而产生 的。
使用断言
断言是一个在假设不正确时会大声抗议的函数或宏指令。
在断言中应避免使用可执行代码,把可执行代码放入断言,在关闭断言时,编译程序有可 能把断言捎去