瑞星卡卡安全论坛技术交流区系统软件 【转载】软件开发人员必备工具书 【代码大全】

«345678910»   7  /  16  页   跳转

【转载】软件开发人员必备工具书 【代码大全】

而且会使它们之间的两个特定域真正联系的可见性更好。
有问题的数据结构耦合的例子。一个程序向另一个子程序传递变量OfficeRec。OfficeRec
有27 个域,而被调用的子程序使用其中16 个,这也是数据结构耦合,但是,它是一个好的数
据结构耦合吗?决不是。传递OfficeRec 使得联系是大规模的,这个事实非常明显,而传递16
个单独参数,则又再次非常拙劣地表明了这一点,如果被调用子程序仅使用其中的6到7 个域,
那么单个地传递它们是个好主意。
在现在这种情形下,可以进一步对OfficeRec进行结构化,以使得在被调用程序中用得到的
16 个域包含在一个或两个亚结构中,这将是最简洁的解决办法。
简单数据耦合或可能数据结构耦合的例子。一个程序调用EraseFile()子程序,通过一个
含有待删文件名的字符串确定将要删去的文件,这很可能是一个简单数据耦合。但也可以说这
是一个数据结构耦合,因为字符串是一个数据结构。
我觉得,我们的结论是半斤与八两的关系,这两种叫法都是同样正确的,对其作严格区分是没
必要的。
控制耦合的例子。比如,一个程序向另一个子程序传递控制标志,通知它到底是打印月报
表、季度报表还是年度报表。
不可取的全局数据耦合的例子。一个程序改动一个表的人口作为全局变量,这个表是以雇
员的识别卡作为索引的。然后,这个程序又调用另一个子程序并把雇员识别卡作为一个参数传
递给它,而这个被调用的子程序则用雇员识别卡去读全局数据表,这是一个典型的全局数据耦
合(虽然仅仅传递雇员识别卡形成的是简单数据耦合,但是第一个程序对表入口的改动,已经
决定了这是一种最坏的耦合——全局数据耦合)。
可取的全局数据耦合的例子。一个程序把雇员识别卡传递给另一个子程序,两个程序都利
用这个识别卡从一个全局表中读取雇员的名字,两个子程序都没有改变全局数据。
gototop
 

这通常也称为“全局数据耦合”,但事实上它更像“简单数据耦合”,我们也可称它为“可取的
全局数据耦合”。与前述一个子程序改变另一个程序使用数据的例子不同,这两个程序并不是由
全局数据联系在一起的。比较两个例子,这种对相同全局数据的只读使用是良性的。这两个从
同一个全局表读取数值的程序,与上述那两个通过使用全局数据来掩盖它们之间联系的程序是
完全不同的。
内容耦合的例子。在汇编语言中,一个子程序可以知道另一个子程序中说明为局部变量的
表的地址。它可以命名用这个地址直接去改动这个表,而地址在两个子程序间并没有当作参数
传递。
内容耦合另一个例子。一个Basic程序利用GOSUB语句来执行另一个子程序中的一段代码。
好的耦合关键是它可以提供一个附加的抽象层次——一旦写好它,就可以认为它是独立的。
它降低了整个程序的复杂性,并且使你每次只致力于一件事情。如果在使用子程序时要求同时
考虑几件事情——知道它的内部内容、对全局数据的改动、不确定的功能等,就会使其丧失抽
象能力,那么使用子程序还有什么用呢?子程序本来是用于降低复杂性的工具,如果使用它没
有使工作更简单,那说明没有用好它。
5.5 子程序长度
理论上,常把一个子程序的最佳长度定为一两页,即66 到132行。按照这种原则,在七十
年代,IBM 公司曾把子程序的长度限制在50 行以下,而TRW 公司则把这个标准定为132 行
(McCabe 1976)。几乎没有什么证据证明这一限制是正确的。相反,倒是证明较长子程序更有
利的证据更有说服力,请参照以下几点:
· Basili和Perricone 1984 年的研究表明,子程序的长度与错误数量是成反比的。随着子
程序长度的增加(长至200 行的代码),每一行的错误数量开始下降。
· 另一个由shen et al 1985年进行的研究表明,程序长度与错误数是无关的,但错误数
量会随着结构复杂性和数据数量的增加而增加。
· 一项由Card、Church 和Agresti在1986 年,以及Card和Glass在1990 年进行的调查
表明,小型子程序(32 行代码或更少)并不意味着低成本和低错误率,证据表明大型
子程序(65 行或更多)的每行成本要低于小型子程序。
· 对450 个子程序的一项调查发现小型子程序(包括注释行,少于143 行源语句)的每
行错误率要比大型子程序高23%(Selby和Basili 1991)。
· 对计算机专业高年级学生进行的测验表明,学生们对一个被过度模块化的、由许多有
10 行左右代码子程序组成的软件,与同样内容但不含任何子程序的软件的理解程度
是相同的。但若把整个程序分解成中等规模的子程序(每个有25 个代码),学生们的
理解程度会上升为65%。
· 最近研究发现,当子程序长度是100 到150 行时,错误率最低(Lind 和Variavan
1989)。
研究子程序长度有什么好处呢?如果你是一个经理,不要限制程序员们编写长于一页的子
程序,刚才引用的资料和程序员们自己的经验都可以证明你这样作是正确的。如果想编写一个
gototop
 

长度是100行,150行或200 行的子程序,那就按照你想的去作吧。目前的证据表明,这种长度
的子程序并不更易引发错误,而其开发更为容易。
如果要开发长于200 行的子程序,就要小心了(这里的长度不包括注释行和空行)。目前还
没有任何证据表明长于200 行的子程序会带来更低的成本或更少的错误。而这样做却会使你达
到可理解性的上限。在对IBM为OS/360操作系统及其它系统而开发代码研究中发现,最易出
错的子程序是那些大于500 行的子程序。在超过500 行之后,错误数量会与子程序的长度成正
比。而且,对一个有148,000 行代码软件的研究发现,修改少于143行子程序错误所耗费的成
本,要比修复长于143 行的子程序中错误成本低2.4 倍(Sely和Basin 1991)。
5.6 防错性编程
防错性编程并不意味着要对自己的程序提高警惕,这一想法是在防错性驾驶的基础上产
生的,在这种驾驶方法中,必须在心中时刻认为其它驾驶员的行为都是不可预测的。这样,
就可以在他们做出某些危险举动时,确保自己不会因此受伤。在防错性编程中,其中心思想是,
即使一个子程序被传入了坏数据,它也不会被伤害,哪怕这个数据是由其它干程序错误而产生
的。更一般地说,其思想核心是承认程序中都会产生问题,都要被改动,一个聪明的程序员就
以这点为依据开发软件。
作为本书介绍的提高软件质量技术之一,防错性编程是非常有用的。最有效的防错性编码
途径是一开始就不要引人错误。可以采用逐步设计方法、在编码前先写好PDL、进行低层次设
计、审查等都可以防止错误引入。因此,应优先考虑它们,而不是防错性编程。不过,你可以
把防错性编程与这些技术组合起来使用。
5.6.l  使用断言
断言是一个在假设不正确时会大声抗议的函数或宏指令。可以使用断言来验证在程序中作
出的假设并排除意外情况。一个断言函数往往大致带有两个内容:假设为真时的布尔表达式和
一个为假时要打印出来的信息。以下是一个假定变量Denominator不为零时一个Pascal断言:
Assert ( Denominator<>0,'Denominator is unexpectedlg equal to 0.' ) ;
这个断言假定Denominator 不等于”0”,第一部分Denominator<>0 是一个布尔表达式,其
结果为True或False。第二部分是当第一部分的结果为False肘,将要打印出来的信息。
即使不愿让用户在最终软件中看到断言信息,在开发和维护阶段,使用断言还是非常方便
的。在开发阶段,断言可以消除相互矛盾的假设,消除传入于程序的不良数值等等。在维护,
可以表明改动是否影响到了程序其它部分。
断言过程是非常容易写的,下面就是一个用Pascal写成的例子:
Procedure Assert
(
Aseertionn: boolean;
Message : string
);
gototop
 

begin
if( not Assertion)
begin
writeln(Messase);
writeln('stopping the program.');
halt(FATAL ERROR)
end
end;
一旦写好了这样一个过程,就可以用像第一个例子那样的语句来调用它。
下面是使用断言的一些指导方针:
如果有预处理程序的话,使用预处理程序宏指令。如果在开发阶段使用预处理程序处理断
言,那么在最终代码中把断言去掉是非常容易的。
在断言中应避免使用可执行代码,把可执行代码放入断言,在关闭断言时,编译程序有可
能把断言捎去。请看以下断言;
ASsert(FileOpen(InputFile<>NULL,’Coulldnt Oped input file’);
这行代码产生的问题是,如果不对断言进行编译,也编译不了打开文件的代码,应把可执
行语句放在自己的位置上,把结果赋给一个状态变量,然后再测试状态。以下是一个安全使用
断言的例子:
FileStatus : FileOpen (InputFile);
Assert(FileStatus<> NULL,'couldn't Opeh input file');
5.6.2  输入垃圾不一定输出垃圾
一个好的程序从来不会输出乱七八糟像垃圾似的东西,不管它被输入的是什么。一个好程
序的特点是“输入垃圾,什么也不产生”,或“输入垃圾,输出错误信息”,也可以是“不允许
垃圾进入”。从现在的观点来看“输入垃圾,输出垃圾”,往往是劣质程序。
检查所有外部程序输入的数值。当从用户文件中读取数据时,要确保读人的数据值在允许
范围之内。要保证数值是可以取的,并且字符串要足够短,以便处理。要在代码中注释出输入
数据的允许范围。
检查全部子程序输入参数值。检查子程序输入参数值,事实上与检查外部程序数据是一样
的,只不过此时由子程序代替了文件或用户。
以下是一个检查其输入参数的子程序的例子,用c语言编写:
float tan
(
float OppositeLength;
float AdjacentLength;
)
{
/*计算角度正切*/
Aseert( AdjancentLength != 0,”AdjanceLength deteced to be 0." );
gototop
 

return (OppsiteLenght/AdjancetLength);
}
决定如何处理非法参数。一旦发现了一个非法参数,该如何处理呢?根据不同情况,可
以希望返回一个错误代码、返回一个中间值、用下一个合法数据来代替它并按计划继续执行、
与上次一样返回一个正确答案、使用最接近的合法值、调用一个处理错误的子程序、从一个子
程序中调用错误信息并打印出来或者干脆关闭程序。由于有这样多的方案可供选择,所以当在
程序的任一个部分处理非法参数时,一定要仔细,确定处理非法参数的通用办法,是由结构设
计决定的,应该在结构设计层次上予以说明。
5.6.3  异常情况处理
应核预先设计好异常处理措施来注意意想不到的情况。异常处理措施应该能使意外情况
的出现在开发阶段变得非常明显,而在运行阶段又是可以修复的,例如,在某种情况下使用了
一个case 语句,其中只预计到了五种情况,在开发阶段,应该能利用异常情况处理产生一个警
告,提示出现了另外一种情况。而在产品阶段,应该利用异常情况处理做一些更完美的工作,
比如向一个错误记录文件中写入信息等。总之,应该设计出不必费多大周折,就可以从开发阶
段进入产品阶段的程序。
5.6.4  预计改动
改动几乎是每个程序都不可避免的现象。比如,开发一个旧的软件新版本,就需要对原有
代码作出许多改动,不过,即使是在开发一个软件的第一版时,也不得不由于加入某些没有预
计到的功能而对其进行改动。在开发软件时,应该努力作到使它很容易地进行改动。而且,越
是可能的改动,越是要容易进行,把你在其中预想到的改动域隐含起来,是减少由于改动而对
程序带来影响的最有力武器之一。
5.6.5 计划去掉调试帮助
调试帮助措施包括:断言、内存检查报告、打印语句等及其它一些为方便调试而编写的代
码。如果所开发的软件是供自己使用的,那么把它们保留在程序中并无大碍。但是,如果是一
个商用软件,那么这些措施留在程序中,则会影响其速度和占用空间等性能指标。在这种情况
下,应事先作好计划,避免调试信息混在程序中,下面是几种方法。
使用版本控制。版本控制工具可以从同一源文件中开发出不同版本的软件。在开发阶段,
可以设置包含全部调试辅助手段的版本控制工具,这样,到了产品阶段,就可以很容易地去掉
在商用版本中所不希望出现的这些辅助手段。
使用内部预处理程序。如果在编程环境中带有预处理程序,如C 语言,那么仅用一下编译
程序开关,就可以加入或去掉这些辅助手段。可以直接使用预处理程序,也可以通过编写宏指
令来进行预处理程序定义。下面是一个用c语言写成的,直接使用预处理程序的例子:
#define DEBUG
gototop
 

#ifdefined(DEBUG)
/*调试代码*/

#endif
这种思想可能有几种表现形式。不仅仅是定义DEBUG,还可以赋给它一个值,然后再测试
它的值,而不是测试它是否被定义了。用这种方法可以区分调试代码的不同层次。也可能希望
某些调试用代码长期驻存在程序中,这时可以使用诸如#if DEBUG>0 之类的语句,把这段代
码围起来,其它一些调试代码可能是有某些专门用途的,这时可以用#if DEBUG—一
PRINTER ERROR 这样的语句把这段代码围起来,在其它地方,还可能想设置调试层次,可用
如下语句:
#if DEBUEG>LEVEL_A
要是不喜欢程序内部充斥着#if defined()这样的语句的话,可以用一个预处理程序宏指
令来完成同一任务。以下是一个例子:
#define DEBUG
#if defined( DEBUG)
#define DebugCode( code fragment){code_fragment}
#else
#define DebugCode(code fragment)
#endif
DebugCode
(
statement 1;
statement 2;

statment n;
)
与使用预处理程序的第一个例子一样,这种技术也有多种形式,可以使它更复杂一些,从
而不是简单地全部包括或全部排除调试代码。
编写自己的预处理程序。如果编程语言中没有预处理程序,可以自己编写一个加入或去掉
调试代码的预处理程序,这项工作是非常容易的。还要建立一个标识调试代码的约定,并编写
自己的预编译程序来遵循这一约定。比如,在Pascal 中,可以编写一个对如下关键字作出反应
的预编译程序:/#BEGIN DEBUG/和/#END DEBUG/人并写一个批处理文件来调用这个
预处理程序,然后再编译这段已经预处理过的代码。从长远观点来看,这样做可以节约许多时
间,因为你不会误编译没有预处理过的代码。
保留使用调试程序。在许多情况下,可以调用一个调试子程序来进行调试工作。开发阶段
根据DEBUG是否定义,包含或不包含这段代码
gototop
 

在控制返回调用程序之前,这个子程序可能进行几项操作。在最终软件中,可以用一个子程序
来代替那个复杂的调试子程序,这个子程序将立即返回控制,或者在进行两个快速操作之后,
返回控制。使用这种方法,对性能带来的影响很小,与编写自己的预处理程序来相比,其速度
也要快得多。所以,有必要保留这个子程序在开发阶段和最终产品阶段的两个版本,以供在将
来的开发和产品调试中使用。
比如,可以用一个检查传入其中指针的子程序作为开始:
Procedure DoSomething
(
Pointer:PONITER_TYPE;
...
);
begin
{ check parameters passed in }
CheckPointer(Pointer); 这行调用检查指针的子程序
...
end.
在开发阶段,CheckPointer()子程序将对指针作全面检查,这项工作可能很费时,但却非
常有效,它很可能是以下这个样子的:
Procdure CheCPOnter( POinter: POINTER_TYPE);——这个程序检查传入的每个指
针,它可以在开发期间使用.完成格外检查
begin
{perform check 1--maybe chech that it's not nil}
{perfom check 3 --maybe check that what is point to isn't corrupted}
{perform check n--...}
end;
当程序进入最终产品阶段时,可能并不希望所有的内务操作都与指针检查联系到一起,这
寸,可以用下面这个子程序来代替刚才那个子程序:
Proccure CheckPointer (Pointer: POlNTER_TYPE ); 本程序仅是即返回其调用程序
begin
{no code;just return to caller}
end;
以上这些并不是去掉调试辅助工具的所有方案,但从提供一些在你的环境下能有效工作
守案这个思路的角度来说,这些已经是足够的了。
5.6.6  尽早引入调试辅助工具
越早引入调试辅助工具,它们所起的作用也就会越大。一般说来,只有在被某一问题困扰
gototop
 

几次之后,你才会舍得花功夫去编写调试辅助工具,但如果你在第一次遇到问题时就这样做,
或者引用一个以前遗留下的调试辅助工具,那么它将在整个项目中都会对你有很大帮助。
5.6.7  使用“防火墙”包容错误带来的危害
“防火墙”技术是一种包容危害策略,在建筑物中,防火墙的作用是防止火灾蔓延,把火
隔离在一个地方。在轮船中使用分隔式水密能也是同样道理,如果船撞上了冰山,那么只有被
撞的水密舱才会破损,而其它舱由于是与它分隔开来的,所以不会受到它的影响,这样就避免
了由一个洞而带来的全船进水的灾难性后果。
信息隐蔽可以帮助在程序中建立防火墙。对另一个子程序的内容知道得越少,对它如何操
作的假设也就越少,而假设越少,其中一个假设出错的可能性就会越小。
松散的耦合也是在程序内部修建防火墙的手段之一。两个子程序之间的耦合越松散,那么
其中一个子程序中的错误影响到另外一个子程序的机会也越少。相反,如果两个子程序联系得
非常紧密,那么一个子程序错误很可能会影响另外一个子程序。
在程序中建防火墙的最好办法是把某些接口标识成“安全”区边界。对穿越安全区边界的
数据进行合法性检查,如果是非法的数据,就要作出合理的反应。基于这种想法的另一种技术
是手术室技术,在数据被允许进入手术室之前,要对其进行消毒处理,手术室中的一切都认为
是无毒安全的。当然,这个手术室是指一段代码,这样,在设计中,要作出的一个关键决定,
就是在这个“手术室”中进入些什么?哪些要被放在它外面?应该把门放在哪儿?应该把哪些
子程序放在安全区内,哪些放在外面?用什么对数据进行消毒?最简单的办法是在外部数据进
入时对其进行消毒,但是,数据往往需要在几个层次上进行消毒,因此,有时需要进行多重消
毒。
5.6.8  检查函数返回值
如果调用了一个函数,并且可以忽略函数退回值(例如,在C 语言中,甚至不需要知道函
数是否返回一个值),千万不要忽略这个返回值。要对这个值进行检查。如果不想让它出错的话,
一定要对其进行检查。防错性设计的核心就是防止常错误。
对于系统函数来说,这个原则也是适用的,除非在结构设计中制定了不检查系统调用的返
回码,而是在每次调用后检查错误代码。如果发现错误,C 语言中的Perror(),或其它语言中
等效的部分,能同时也查出错误个数和这个错误的说明。
5.6.9 在最终软件中保留多少防错性编程
防错性编程带来的矛盾是,在开发过程中,你希望出现错误时越引人注意越好,惹人讨厌
总比冒险忽视它好得多。但在最终产品中,你却希望它越不显眼越好,程序运行不管成功与否,
都要看起来十分优雅。以下是帮助你决定在最终软件中应该保留哪些防错性编程的一些原则:
保留查找在要错误的代码。首先要确定哪些域可以承受本测试到的错误,而哪些域不能。
例如,你正在编写一个表格程序,程序中的屏幕更新区就可以承受末测试到的错误,因为发生
这种情况的后果,不过是一个混乱的屏幕而已,而在计算部分,就不能发生这种情况。因为这
会在表格中产生难以察觉的错误。绝大多数用户都宁愿忍受一个混乱的屏幕而不是错误的表格。
去掉那些无关紧要错误的代码。如果一个错误的后果是无关紧要的,那就去掉检查它的代
码。在上例中,你很可能会去掉检查屏幕更新区错误的子程序。“去掉”并不是指从物理上把这
gototop
 

段代码删掉,它指的是版本控制预编译开关,或其它不编译那段特定代码的技术。如果不存在
空间限制问题,你也可以保留这段查错代码,并让它向一个错误记录文件隐蔽地传送信息。
去掉那些引起程序终止的代码。在开发阶段,程序发现了一个错误时,你会希望这个错误
越引人注意越好,以便你能修复它,通常,达到这一目的最好办法是让一个程序在发现错误时
打印出错误信息然后终止。即使对于微小错误来说,这样做也是很有用的。
而在最终软件中,在程序终止前,用户总是希望有机会将其工作存盘。他们往往愿为达到
这一目的而忍受一些反常现象,用户们不会感激那些使其工作付诸东流的东西,不管这些东西
在调试阶段多么有用,哪怕最终极大提高了软件质量。如果程序中含有会使干百万数据丢失的
调试代码,那么在最终产品中应将其去除掉。
保留那些可以使程序延缓终止的代码。同时,那些相反的代码也应该保留。如果程序中含
有测试潜在致命错误的信息,那么用户会为能在它们最终发展起来之前将自己的工作有盘而感
到高兴。我所使用的文字处理机在溢出内存之前会亮起“SAVE”提示灯进行警告,当发现这一
情况后就立即存盘并退出。当重新启动程序时,一切又变得正常了。从理论上说,程序不应该
溢出内存,而且,在用同一台机器重新启动程序运行同一文件时,它也不应该用更多内存。产
生了内存溢出问题说明程序有缺欠,但是,程序员想得很周到,在程序中保留了内存检查代码,
我也宁愿得到一个警告信息,而不愿失去我前面所做的工作。
保证留在程序中的错误提示信息是友好的。如果在程序中保留了内部错误提示信息,要确
保它是用友好的语言表达。在我早期编程工作中,我曾经收到一个用户的电话,说她在屏幕上
看到了这样的信息“你的指针地址有错,笨蛋!”幸亏她还有一些幽默感,这对我来说是很幸运
的。通常的办法是通知用户存在“内部错误”,并告诉用户一个她可以投诉的电话号码。
要对防错性编程提高警惕。过多的防错性编程会带来它自身的问题,如果你对每一种可以
察觉的参数传递,在每一个可以察觉的地方都进行检查,那么程序将变得臃肿而笨拙。更糟的
是,附加的用于防错性编程的代码本身并非是完善无缺的,同其它代码一样,你也会在其中发
现错误,而且,如果你是随意写它的,那么错误也会更多。考虑好需要在哪里预防错误,然后
再使用防错性编程。
                      5.7  子程序参数
子程序间的接口往往是一个程序中最容易出错的部分,由Basili 和Perricone 进行的一项研
究表明,程序中39%的错误都是内部接口错误,即予程序间的通信错误。以下是尽量减少这类
错误的一些准则:
确保实际参数与形式参数匹配。形式参数,即哑参数,是在子程序定义中说明的变量,实
际参数是在调用程序中使用的变量和参数。
常见的错误是在子程序调用时变量类型有误,比如,在需要使用实型数时使用了整型数
(这种情况只在像C 这种弱类型的语言中,才会遇到。例如,在汇编语言或在C语言中未使用
全部编译程序的全部警告时就可能产生这种问题。而在Pascal 中,当变元是单纯输入的时候,
几乎不会产生这个问题)。通常编译程序在把实参传入子程序之前,会把它转为形参的类型。如
果产生这个问题,编译程序通常会产生警告。但是在某些情况下,特别是当变元既用于输入也
用于输出时,你可能由于传递了错误的变元类型而受到惩罚。
gototop
 

要养成检查参数表中参数变元类型和注意编译程序关于变量类型不匹配警告的习惯。在
C 语言中,使用ANSI函数的原型,以便编译程序会自动检查变元类型,并在发现类型错误时发
出警告。
按照输入一修改一输出的顺序排列参数。不要随机地或者按照字母表的顺序排列参数,应
该将输入参数放在第一位,既输出又输入的参数第二位,仅供输出的参数第三位这样来排参数。
这种排列方法示示子程序中操作进行的顺序——输入数据、修改数据、输出一个结果、下面是
一个Ada语言中的参数排列顺序。
procedure InvertMatrix
(
OringinalMatrix : in MATRIX;
ResultMatrix : out MATRIX;
);
procedure ChangeStringCase
(
DesiredCase : in STRING_CASE;
MixedCaseString: in out USER_STRING
);

procedur PringPageNumber
(
PageNumber : in INTEGER;
Status: out STATUS_TYPE
);
这种排列约定与C 语言中把被修改的参数放在首位的规定是冲突的。不过我仍然认为上述
排列顺序至少对我来说是十分明智的。但如果你一直接某种特定方式对参数排序,这也是可以
帮助提高程序可读性的。
如果几个子程序今使用了相似的参数,应按照不变的顺序排到这些参数。子程序中参数的
排列顺序可以成为一种助记符,而不停变动的排列,会使得这些参数非常难记。比如,在C 语
言中,fptintf()函数与printf()函数相比,除了多了一个文件作为第一变元之外,两者其余都是一
样的。而函数fputs()与函数puts()相比,也只是前者多了一个文件作为最后变元。这实在是一个
糟糕的区别,因为它使得这些函数的参数的难记程度比实际要高多了。
我们来看一个例子,同样是C语言中的函数,函数Strncpy()是按照目标字符率、源字符
率和字节的最大数目来排列变元的,而函数memcpy()是按同样的顺序来排列变元的,这种相
似性使得两个函数中的参数都非常好记了。
使用所有的多数。如果向某个子程序中传入了一个参数,那就要在其中使用;如果不用它
的话,就把它从子程序接口中去掉。因为出错率是随着未用参数个数的增加而升高的,一项调
查表明,在没有未用参数的子程序中,有46%是完全无错的。而在含有未用参数的子程序中,
gototop
 
«345678910»   7  /  16  页   跳转
页面顶部
Powered by Discuz!NT