标题:
创建高质量的子程序
[打印本页]
作者:
chinanic
时间:
2008-8-22 17:27
标题:
创建高质量的子程序
在讨论高质量的子程序的细节之前,明确下面这两个基本术语会很有帮助。首先,什么是“子程序(routine)”?子程序是为实现一个特定的目的而编写的一个可被调用的方法(method)或过程(procedure)。例如C++中的函数(function),Java中的方法(method),或Microsoft Visual Basic中的函数过程(function procedure)或子过程(sub procedure)。对于某些使用方式,C和C++中的宏(macro)也可认为是子程序。你可以把创建高质量子程序的很多技术应用到所有的这些情况中。
那什么又是高质量的子程序呢?这个问题更难回答。也许回答这个问题的最简单的办法,是来看看什么东西不是高质量的子程序。这里举一个低质量的子程序的例子:
C++示例:低质量的子程序
void HandleStuff( CORP_DATA & inputRec, int crntQtr, EMP_DATA empRec,
double & estimRevenue, double ytdRevenue, int screenX, int screenY,
COLOR_TYPE & newColor, COLOR_TYPE & prevColor, StatusType & status,
int expenseType )
{
int i;
for ( i = 0; i < 100; i++ ) {
inputRec.revenue
= 0;
inputRec.expense
= corpExpense[ crntQtr ][ i ];
}
UpdateCorpDatabase( empRec );
estimRevenue = ytdRevenue * 4.0 / (double) crntQtr;
newColor = prevColor;
status = SUCCESS;
if ( expenseType == 1 ) {
for ( i = 0; i < 12; i++ )
profit
= revenue
- expense.type1
;
}
else if ( expenseType == 2 ) {
profit
= revenue
- expense.type2
;
}
else if ( expenseType == 3 )
profit
= revenue
- expense.type3
;
}
这个子程序里有哪些不妥呢?给你一个提示:你应该能够从中发现至少10个不同的问题。请你先列出自己发现的问题,然后再来看下面这份清单:
■ 这个子程序有个很差劲的名字。HandleStuff()一点也没有告诉你这个子程序究竟是做什么的。
■ 这个子程序没有文档(有关文档的话题已经超出了子程序的范畴,因此将在第32章“自我注解的代码”讨论)。
■ 这个子程序的布局不好。代码的物理组织形式几乎没有给出任何关于其逻辑组织的提示。布局的使用过于随意,程序内的不同部分使用了不同的布局风格。请比较一下expenseType==2和expenseType==3这两处的代码风格(在第31章“布局与风格”中会讨论布局问题。)
■ 这个子程序的输入变量inputRec的值被改变了。如果它是一个输入变量,它的值就不应该被修改(而且在C++中它应该定义为const)。如果变量的值就是要被修改的,那就不要把它命名为inputRec。
■ 这个子程序读写了全局变量——它从 corpExpense 中读取数值并将其写入profit。它应该更直接地与其他子程序通讯,而不是去读写全局变量。
■ 这个子程序没有一个单一的目的。它初始化了一些变量,向数据库写入数据,又做了一些计算——从这些事情之间看不出任何联系。子程序应该有单一而明确的目的。
■ 这个子程序没有注意防范错误数据(bad data)。如果crntQtr等于0,那么表达式ytdRevenue*4.0/(double)crntQtrh将会导致除零错误。
■ 这个子程序用了若干神密数值(magic number):100、4.0、12、2、3等。神秘数值的问题会在第12.1节“数字概述”中探讨。
■ 这个子程序未使用其中一些参数:screenX和screenY在程序中都没有被引用过。
■ 这个子程序的一个参数传递方式有误:prevColor被标为引用参数(&),但在这个子程序内却未对其赋值。
■ 这个子程序的参数太多了。合理的参数个数,其上限大概是7个左右,而这个子程序有11个。这些参数的排布方式也难以理解,估计没人想仔细研究它们、甚至没人想数数有几个参数。
■ 这个子程序的参数顺序混乱且未经注释。(参数的顺序会在本章探讨。而代码注释问题会在第32章中阐述)
抛开计算机本身,子程序也算得上是计算机科学中一项最为重大的发明了。子程序的使用使得程序变得更加易读,更易于理解,比任何编程语言的任何功能特性都更容易。像上例那样滥用这一计算机科学中最为重要的特性,简直就是一种犯罪。
子程序也是迄今为止发明出来的用以节约空间和提高性能的最重要手段。设想,如果对每个子程序调用都重复写出代码,而不是转到相应的子程序,那么代码会变得多么臃肿。再设想一下,如果要对一段代码的性能进行改善,但这些代码反复出现在不同地方,而不是被纳入了一个子程序,那该有多困难。正是子程序使得现代化的编程成为可能。
“好吧,”你可能会说,“我早就知道子程序很重要,而且我在编程时也一直在用它们。这里的讨论好像是要纠正什么,那么你想让我做些什么呢?”
我希望你能够理解,创建一个子程序可以有很多合理的原因,但完成它的方式却有对错之分。当我还是一名在读的计算机系大学生时,我曾认为创建子程序的主要原因不过是为了避免重复代码。我所用过的那本入门教程也告诉我说,使用子程序的好处就是因为它避免了重复的代码,从而使程序更易于开发、调试、编档和维护等等。除了还讲了一些如何使用参数和局部变量等语法细节之外,这就是那本教程所涵盖的全部内容了。它对子程序理论和实践的解释既不够好,也不够完整。下面的几节将给你一些更好的解释。
How Long Can a Routine Be?
子程序可以写多长
理论上认为的子程序最佳最大长度通常是一屏或一到两页列印代码,也就是约50~150行代码。按这种精神,IBM曾经把子程序的长度限制在50行之内,而TRW则把这一长度限制在两页纸之内
作者:
◆◆◆◆◆◆
时间:
2008-8-25 12:10
CC研究C++了!!呵呵!
欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/)
Powered by Discuz! 7.2