|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
进而能拉拢大多数程序员用windows产品。并且从ASP.NETAJAX可以跨平台这一点上,间接证明了我们的推断,至少证明了微软做过这方面的研究。所以如果哪一天突然听说了.net可以跨平台了,那么请不要吃惊,如果这一天真的到来,java就到了真正和.net决战的时刻。因为不到万不得以的时候微软是不会推出跨平台的.net的,如果跨平台的.net还不足以对抗java的话,那么微软还剩的手段就是开源了,呵呵。程序|毛病接待到临诊断Java代码,一个隔周更新的新专栏,侧重会商和您一样平常编程事情有关的Java办理计划。本文为第一篇,先容了毛病形式的观点,一个十分有效的观点,它将进步您检测和修改代码中毛病的才能。您会懂得到一种最广泛的毛病形式,这将为您入手下手辨认和制止更初级的毛病形式奠基基本。
毛病形式和它们为何有效
正如好的编程妙技触及良多计划形式(您能够在分歧的程序高低文中组合和使用这些形式)的常识一样,好的调试妙技也触及对毛病形式的必定懂得。毛病形式就是已收回的毛病和程序中潜伏的毛病之间的反复呈现的互相干系。这类观点对编程来讲其实不奇怪。大夫们在诊断疾病时依托类似范例的互相干系。他们在练习时代经由过程和资历较老的大夫配合事情来进修这些。他们的教导就是会合在做这类诊断上的。相反,我们软件工程师的教导是会合在历程计划和算法剖析上的。这些妙技当然主要,可是人们对换试历程的教导却很少存眷。相反,我们得本人往“拾起”这类妙技。跟着极度编程的呈现和它对单位测试的注意,这类做法已入手下手改动了。可是频仍的单位测试只是办理了成绩的一部分。一旦发明毛病,就必需诊断和改正它们。侥幸的是,良多毛病都遵守我们能够辨认的几种毛病形式的个中一种。一旦您能够辨认出这些毛病形式,您就能够诊断堕落误的缘故原由而且更快地改正它了。
毛病形式与反形式有关,反形式是一次又一次被证实是失利的大众软件计划的形式。固然反形式是计划形式,毛病形式倒是与编程毛病相干的毛病的程序举动的形式。这与计划基本没有干系,而是与编程和调试历程有关。
经由过程示例进修
为了申明毛病形式前面的头脑,让我们来思索一种基础毛病形式,编程老手(常常另有更初级的程序员)经常会碰到这类毛病形式。在前面的文章中,我们漫谈到更初级的毛病形式。对每种形式,我会会商将有助于把该形式的毛病的产生把持到起码的编程准绳(并不是表示一切的毛病都是不遵守编程准绳的了局;不论我们遵守几准绳,我们城市出错误)。
为了分类起见,我会利用上面的情势(从医学上借用一些术语)来归纳综合毛病形式形貌:
形式称号
症状
原因
医治办法和防备措施
RogueTile形式
大概它是编程老手中最广泛的毛病形式,原因是复制和粘贴一段代码到程序的别的部分。偶然,复制的一小部分由于功效上需求的稍微分歧而作了修改。不成制止地,毛病在一个正本中被修改了,而在另外一个正本中没有被修改,如许在毛病症状复发时就会让您很头疼。只管年夜多半程序员很快就熟习了这类毛病形式,但他们中很少人接纳得当的措施来将这类毛病的呈现把持到起码。您很简单就会偷懒不往思索而复杂地复制您以为已能够运转的代码。可是事情效力因为修改代码而损失,这是由于不加选择的复制―粘贴操纵很快下降了复制代码带来的任何事情效力。
我称此为RogueTile形式是由于,一段代码的各个正本能够被当作是散布在程序中的“tile”。因为分歧正本中的代码呈现了差别,正本就酿成了“roguetile”。
症状
这类毛病的形式的最广泛症状是,在您以为已修改了成绩今后,程序还持续体现堕落误的举动。
原因
为了了解这类情形产生的缘故原由,我们来看看上面的二元树类条理布局:
publicabstractclassTree{
}
publicclassLeafextendsTree{
publicObjectvalue;
...
}
publicclassBranchextendsTree{
publicObjectvalue;
publicTreeleft;
publicTreeright;
...
}
关于这些类要注重的第一件事就是,两种详细类都包括Object范例的value字段。假如您决意稍后让树包括,好比说,Interger,您大概会健忘更新个中的一个字段声明。假如程序的别的部分必要这些字段是Interger的话,程序就极可能不会编译。您也许记得您改动了个中一个类的value字段的范例,却疏忽了一个现实,就是您没有在别的类中作响应的改动。
一些防备措施
固然,这个示例所示的毛病是编程老手能够很快学会经由过程分化出大众代码来制止的。在本例中,字段声明应当移到Tree类中。它的两个子类就会承继这个字段,并且对字段声明的任何改动都只必要在一个中央呈现。
持续看这个示例,我们大概还会编写在一个Tree中相加和相乘一切节点的办法。为了复杂起见,我将以递回的体例来编写这些办法。
//inclassTree:
publicabstractintadd();
publicabstractintmultiply();
//inclassBranch:
publicintadd(){
returnthis.value.intValue()+left.add()+right.add();
}
publicintmultiply(){
returnthis.value.intValue()*left.multiply()+right.multiply();
}
//inclassLeaf:
publicintadd(){returnthis.value.intValue();}
publicintmultiply(){returnthis.value.intValue();}
请注重我在multiply办法中为Branch类引进的毛病:我没有效第三项往乘,而是加了它。毛病产生了,由于我经由过程复制add办法中的代码并作稍微(但不完整)的修改创立了multiply办法。这类毛病十分潜伏,由于挪用multiply办法永久不会收回毛病旌旗灯号。现实上,在良多情形下,它会前往一个看上往完整公道的了局。
就象之前一样,我们能够经由过程分化出大众代码来将这类毛病把持到起码。在这类情形下,我们能够编写一个独自的办法,它在Tree上累计一个运算符(作为一个参数传送)。我们可使用一种被称为大众形式的计划形式(不是毛病形式!)在对象中封装这个运算符。
publicabstractclassOperator{
publicabstractintapply(intl,intr);
}
publicclassAdderextendsOperator{
publicintapply(intl,intr){
returnl+r;
}
}
publicclassMultiplierextendsOperator{
publicintapply(intl,intr){
returnl*r;
}
}
然后我们就能够以下面的代码所示在我们的Tree类条理布局中改动这个办法:
//inclassTree:
publicabstractintaccumulate(Operatoro);
publicintadd(){
returnthis.accumulate(newAdder());
}
publicintmultiply(){
returnthis.accumulate(newMultiplier());
}
//inclassLeaf:
publicintaccumulate(Operatoro){
returnvalue.intValue();
}
inclassBranch:
publicintaccumulate(Operatoro){
returno.apply(this.value.intValue(),
o.apply(left.accumulate(o),
right.accumulate(o)));
}
经由过程分化出大众代码,我们打消了在add和multiply办法注释中呈现复制―粘贴毛病的大概性。别的,请注重我们不再必要为Tree的每个子类编写独自的add和multiply办法了。
分化出大众代码是一个很好的习气,但它其实不合用于一切的情形。好比说,Java范例体系的复杂性常常迫使我们在准确范例查验和坚持对程序的每一个分歧的功效性元素的单点把持(请参阅参考材料,浏览我写的关于NextGen的文章)之间作出选择。正由于这个,RogueTile形式是一切开辟职员必需一向勉力以把持到起码的一种毛病范例。
下一篇内容是甚么?
简而言之,这是我们的第一个毛病形式。您大概想把它剪上去钉在您的通告牌上作为提示。
形式:RogueTile
症状:代码仿佛体现出后面改正过的毛病仍然存在。
原因:复制―粘贴代码片断的最少一个正本还包括在别的正本中已修改了的毛病。
医治和防备措施:假如大概,分化出大众代码;不然就对其举行更新。制止复制和粘贴代码。
在我的下一篇文章中,我会探求Java代码中呈现过的别的一些广泛的毛病形式。我们将出格看一下作为空指针非常而呈现的毛病形式,并会商怎样将它们的呈现次数把持到起码。
参考材料
会见形式主页,这是一个先容计划形式和怎样利用它们的优异主页。
反形式主页供应了关于该主题的书本的信息和链接。
假如您还没有这么做,请查阅极度编程,一个疾速开辟简便的、强健的软件的壮大的新办法。
然后下载JUnit并立即入手下手单位测试。
EricAllen 的关于NextGen(Java的一个运转时泛型范例的扩大)的文章申明了一个加倍壮大的范例体系是如何匡助加重存在于分化大众代码和利用范例体系在编译时代捕获毛病的两个方针之间的一些压力的。
关于作者
EricAllen在Cornell年夜学取得盘算机迷信和数学的学士学位。他今朝是Cycorp公司的Java软件开辟职员带头人,仍是Rice年夜学的编程言语小组的半工半读硕士生。他的研讨触及正轨语义模子和Java言语的扩大,都是在源代码和字节码的级别上的。今朝,他正在为NextGen编程言语完成一种从源代码到字节码的编译器,这也是Java言语的泛型运转时范例的一种扩大。
一旦你有了思想,那你编的程序就有了灵魂,不管是什么语言到了你的手里都会是你的工具而已,他们的价值是能尽快帮助你实现你想要的目标。但是如果你没有了思想,那就像是海里的帆船失去了船帆,是很难到打海的另一边的。 |
|