您现在的位置: 中国IT实验室 >> IT项目工程与管理 >> 软件工程 >> 文章正文
如何让软件的改进过程实现自动化

ChinaITLab 收集整理  2004-12-23  保存本文  推荐给好友  QQ上看本站  收藏本站



  概要
  几年前每个人都被Quality 软件的问题所困扰。Quality 中的Q 之所以大写就是为了强调单词的重要性。引入了消耗几个小时的程序和检查过程、以及大量的文书工作,就是为了设法减少软件的故障率。就是前不久,这种趋势已经演变为更为轻便的处理过程,该过程使用了轻便的软件和极端编程。这仍然是一个积极的转变因为保证软件品质仍然是重要的。有些分析家估计:有60%的软件故障可自动检测出来。那么我们能做的就是在昨天的质量装置恐龙和今天的困惑之间建一座桥梁,以便让问题解决的又快又代价低?作者Joe Walker 测试了不同类型的故障和七种工具以帮助你揭示他们的真面目。
  
  有许多免费工具可以轻而易举的报告你的代码有什么故障,然后帮助你改进代码的质量。而且因为故障常常是主观方面的,大部分工具可以配置以适合你的本地代码类型。
  
  但是一开始你就有减少故障的义务。这听起来好像是一个简单的问题——肯定对于每个人来说软件质量必须摆在第一位。但是,花费最少时间来修改代码往往看起来更加合理一些。任何保存寿命短的软件应该编辑的尽可能少,而且编写没有人阅读的单行文档也是毫无意义的。我在想有多少块文档花费在编写和检查方面的时间比某人阅读他们节省的时间多呢?因此,我们的目的就是把值得我们提高作品质量的工作和浪费资源的工作区别开来。
  
  你想在提高代码质量方面走多远?
  
  存在以下几种故障种类。我给出的工具在它们攻击的故障类型方面有区别。我根据他们的严重性确定了四种不同的故障类,从困扰用户的普通故障到阻止代码重新使用的有组织的故障都有:
  
  Current bugs: 当前故障阻止软件的正确运行。它们困扰用户并且可(或者应该)通过你的软件测试显示出来。当前故障与潜在故障截然不同。
  
  Latent bugs: 这些故障当前不产生问题。但是它们潜伏着,在以后才出现。阿里安5号火箭的失败就是由于一个浮点到整数转换错误引起的,当前面的火箭速度较慢时处于睡眠期;但是速度较快的阿里安 5却触发了这个问题。千年病毒也是一个潜伏故障的例子,只有当环境改变时它才浮出水面。使用传统的测试方法测试潜伏病毒要困难得多,并且找到他们就需要具有远见的人询问:“什么改变才能让故障从黑暗中走出来?
  
  Accident-waiting-to-happen bugs: 代码可以既简单又安全,或者他也可以是一团糟,等着绊倒那些对他们的编辑结果想得不多的可怜的程序员。一般而言,代码越老,就越有可能出现明显生锈的刀口;并且某些工业证据也表明:长时间没有重构的代码一般七年之后也就不再需要重新编写了。
  
  Poorly organized bugs: 组织不好的代码不容易重新使用并且常常包含对代码的过多依赖,其实有些是不必要的。因此它更有可能受其他代码位中的故障影响。编码标准致力于解决这种类型的问题,但是编码标准不能完全解决问题。他们不能停止问题如循环的依赖性,它使得你毫无机会来维持可重新使用的代码。
  
  这些问题根据他们的严重性组织的比较粗糙。当前故障一般比潜伏故障更难以解决,而潜伏故障依次的比等待发生的故障或者组织故障更加令人担心。
  
  下列代码包含了上述四种故障案例。认出它们后奖励一下你自己:
  
  1: public static void main(String[] args)
  2: {
  3:   System.out.println(toUpperCase('q'));
  4: }
  5:
  6: private static char toUpperCase(char main)
  7: {
  8:   return (char) (main - 31);
  9: }
  
  这里有一个当前故障因为行8应该读取:
  
  8: return (char) (main - 32);
  
  这种简单问题不解决,程序也不会运转。与其辛苦计算出q的大写字母为Q,还不如设法劝说我们相信答案就是R。
  
  这里有一个潜伏故障因为迟早有人会设法得到? 或者某数的大写版本,而不是任何明智的东西。
  
  一个小小的等待发生事故的故障是由于行6中的某些傻变量名引起的。main 并没有真正的描述什么正在进行,而且还用方法名来迷惑我们。更好的代码如下:
  
  6: private static char toUpperCase(char lower)
  
  如果该代码描述了为什么她要从小写字母盘上的字符减去32,那么它会安全的多。
  
  最后如果你将toUpperCase()方法变为公用的,并为方便其他类的使用将它变为实际类——甚至你可以使用下面的标准Sun微系统提供的方法,那么代码就组织得更好一些:
  
  3: System.out.println(Character.toUpperCase('q'));
  
  你想在哪里止住?
  你什么时候停止调整和提高你的代码呢?这个问题没有一个真正的答案;这取决于你和你的项目。商业项目常常只关注于ROI (投资回报),因此它主要解决当前故障,并且通过实现编码标准解决这个问题很容易。
  
  我们常常看到商业项目无意中采取了某些步骤来阻止潜伏故障的解决,它们实现了一个严格的变化控制程序,该程序将代码修改与产生的故障联系在一起来帮助测试。要开发队伍足够忠诚于软件品质,以致于关心某人的软件而且不设置障碍,这实在是太难了。
  
  在更具有启迪性的开发环境里,大家都承认重构是创造高品质软件的至关重要的组成部分。重构就是逐步稳固你代码的组织以避免等待发生事故的过程。
  
  但是即使是最关注品质的开发者也有他们的限制。你真的关心你注释中的标点符号吗?或者你真的关心方法是否是以最合理的顺序声明的吗?
  
  Reasoning Inc.最近研究了不同商业和开源项目的品质,并据此发表大字标题。该公司针对不同的商业选择分析了Linux TCP/IP堆栈的源代码、Apache Web服务器、和Tomcat 。有趣的是, Reasoning公司还运行了下面描述的免费工具版本,然后手工分析结果以删除错误证据。他的结果出现了一些异常,但是它表明:开源关注于品质由此产生的回报比品质软件本身产生的回报明显要大得多。
  
  我鉴别的七种工具可帮助显示故障,他们与Reasoning 公司的方法类似,并且在某些情况下也能帮助解决这些故障。我还将这些工具用于我最近的项目之一:DocTree。 DocTree 产生一个动态的装载Webpage,它包含到一万个类的Java文档的深度链接,这些类来自于许多重要的Java软件项目。DocTree不是一个很大的项目,但是它足够成为这七种工具的有用的测试案例。该资源可从java.net (见 Resources)处下载,所以你可以利用Ant看到这些工具是如何在同一个基础上运行。 有几个工具有绘图用户界面(GUIs)。但是,把它们当作你的构造过程(如,从一个Ant构造脚本)的一部分来运行可能更有意义。运行这些工具花的时间越少,继续提高你的软件就越有可能。
  
  使用工具如CruiseControl、 Anthill是相当容易的,或者甚至是使用简单的cron 每晚寄出当作电子邮件给予你结果的构造,也是相当容易的。在建立了这样一个程序后,它就比GUI容易使用。
  
  让我们看看这七种工具:
  
  FindBugs
  
  PMD/CPD
  
  Checkstyle
  
  Jalopy/Jacobe
  
  JDepend
  
  JUnit
  
  Eclipse
  
  FindBugs
  
  FindBugs主要解决当前和潜伏故障。它寻找普通问题和常常显示某处出错的小处代码。
  
  FindBugs显示的一些故障案例包括:
  
  返回不稳定静态数据的方法
  
  Get方法不同步的地方显示Get方法;set方法同步的地方显示set方法
  
  Iterator类定义过程中出现的问题
  
  无意义的控制流程语句
  
  存在NullPointerException的地方;引用值与Null的多余比较的地方
  
  FindBugs 处于非常活跃的开发中,并且你可以扩展它,通过插入机制将自定义检查包括进来。
  
  FindBugs在DocTree找到了一个相当严重的潜伏故障:一个类定义了equals(),但没有定义hashcode()。这在当前配置中不会引起任何问题。但是,如果以后在DocTree迭代中,使用了Hashtable 或者HashMap中的类,就会出现假的结果。FindBugs也找到了一些次要的潜伏故障如异常上的信息流一直没有关闭直到出现碎片整理和其他次要问题。随着显示的问题的增长,你软件上的故障数就会减少。
  
  FindBugs使用字节码分析来生成他的故障报告。
  
  下面是创建FindBugs 报告的Ant 目标的DocTree项目片段:
  
  <target name="web.findbugs" depends="jar">
  <mkdir dir="${target.web}/findbugs"/>
  <taskdef name="findbugs"
    classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
   <classpath>
    <fileset dir="${support.tools}/findbugs066"
      includes="**/*.jar"/>
   </classpath>
  </taskdef>
  <findbugs home="${support.tools}/findbugs066"
    output="text"
    outputFile="${target.web}/findbugs/report.txt"
    reportLevel="low" sort="text">
   <class location="${target.jar}/${ant.project.name}.jar"/>
   <sourcePath path="${source.java}/main"/>
  </findbugs>
  </target>
  
  PMD/CPD
  
  PMD是非常可自定义的,并能找出这四种故障类的问题。但是,他最擅长于寻找组织故障和事故等待发生的故障。与FindBugs不同,PMD使用源代码分析,与编译器工作方式类似,除了它生成故障报告而不是字节码之外。PMD 是我为这篇文章测试的最可自定义的工具之一,主要是因为她有一个很酷的特征:允许你使用XPath引擎访问源代码解析器




 相关文章  热门文章
软件需求评审之五个案例和九条建议
细说软件工程的七条基本原理
如何有效的软件质量管理(下)
如何有效的软件质量管理(上)
开发技巧之"再用式"软件开发方法
开发技巧之如何在软件频繁改变时测试
细说微软软件开发过程与团队模型
五步走:软件需求的管理过程分析
教你组织软件开发过程中的评审会议
软件工程: 软件测试需要原则吗?

 文章评论


认证培训
热门专题       more
相关下载
论坛新帖
博 客