BUG,规范,断言和调试

发表于:2007-9-28 13:37

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:网络转载

对于BUG的自信
        Donald E. Knuth(高德纳)在TeX: The Program的前言中说:"我相信,在1985年11月27日,TeX代码里面的最后一个BUG已经被发现和解决了。但是,如果代码中仍旧有BUG,我很高兴付给任何第一个发现BUG的人20.48美元(这是前一个金额的两倍,而且我计划在一年内把它翻倍。你看,我很自信!)"

想知道后来发生了什么吗?

        在http://truetex.com/knuthchk.htm可以看到他写出去的支票的金额是从2.56美元开始翻倍的。微基百科中关于这种支票的文章(http://en.wikipedia.org/wiki/Knuth_reward_check)说,截至2001年10月为止,他写出去了超过两千张这样的支票,但是他的BUG支票是如此有名,以至于很多人把他的支票收藏起来而不是拿出去兑现(http://www.tug.org/whatis.html)。

有多少程序员在发布产品的时候可以这样自信地声明产品没有问题?

        遗憾的是,现在的程序员经常把发现BUG的责任推给测试人员——“不用担心,测试人员会发现所有BUG的,这是他们的工作”。实际上,测试人员并没有开发人员的条件,他们不可能进行源代码级别的调试,很大程度上只能靠运气——没错,是靠运气,如果一个BUG很容易被发现,程序员不太可能自己没有发现它——来发现BUG。

        还有一些人干脆就认为BUG是不可避免的,或者认为不值得这么精益求精,但是实际上防止BUG出现的最好的时机,就是在编写代码的时候。在编写代码一段时间之后,即使是编写者本人也可能需要一段时间来理解代码(如果不习惯写注释的话,这段时间会更长),更别说定位问题所在了。在编写代码时,如果具有良好的习惯,可以免去很多在之后消灭BUG的困难。

规范不是语法
        太多人把不要使用goto奉为圣旨,从来不想去打破。他们会争论,goto会造成难以维护的难读的代码,以及使编译器无法进行优化。这两点在很大程度上是真的,但是也有使用goto可以增加程序可读性和效率时候。在这种情况下,遵循“不使用goto语句”规范会产生更糟糕的代码。

        一些人喜欢在成员函数后面加const,但是另外一些人没有养成这个习惯。一个直接的结果就是,一些看起来对对象完全没有影响的函数不能在const函数里面使用。这时候应该怎么办?如果函数实际上会对对象成员造成影响(例如CToolBar::GetItemRect),这也会带来潜在危险。

        为了和ANSI标准之前编写的代码兼容,ANSI C中的memchr函数的声明为

void *memchr(
     const void *buf,
    int c,
    size_t count
 );


        这里c是一个字符。很明显,标准为了兼容性放弃了明确性和更强的类型检查。如果放弃兼容性,这个函数应该声明为如下形式              
        void *memchr(   const void *buf,   unsigned char c,   size_t count);
        微软的很多代码使用一种叫做匈牙利表示法的命名规范。这使得标识符的含义和类型更加明确——但是这是从广义的角度来说的。考虑如下函数声明
        char *strcpy(   char *strDestination,   const char *strSource );
        如果严格遵循原始的匈牙利表示法,那么两个参数的声明应该是pch开头。但是以str开头给这两个参数更多含义:它们指向以\0为结束符的字符串
        规范是用来在大部分时间里遵循,以及在可以得到更好的结果时打破的。

编译警告的意义
        智能化的编译器开始将语法正确的语句列为警告:

while(size-->0);//注意这里有个分号    *pTo++=*pFrom++;

        编译器会报告空循环问题。

        但是对于以0结尾的字符串复制
  while(*pTo++=*pFrom++);
 
,这样的警告是多余的。
        更加常见的警告是在条件判断语句中
if(ch='\0')    EndOfString();

        为了绕过这个警告,需要添加额外的运算或者语句,或者更正错误的赋值。
while((*pTo++=*pFrom++)!='\0')...{}if(ch=='\0')
        一些程序员甚至将比较语句修改成
if('\0'==ch)
        这样作的原因显而易见:为了减少潜在的BUG。如果你的编译器没有这样的警告,那么你可以使用一些工具来检查那些语法正确但是有潜在BUG的代码。。但是,良好的编程习惯还是减少BUG出现的最好的方法。

        在觉得警告消息太烦人的时候,不妨想想编译器的开发人员为什么要编写这么多警告消息,而不是仅仅寻求关闭警告的方法。  

        P.S. Visual C++的默认警告等级是3级。发布软件之前应该改成4级,之后检查所有的编译警告。

31/3123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号