追求代码质量: 用 AOP 进行防御性编程

发表于:2008-06-26来源:作者:点击数: 标签:代码质量防御性AOPaop
开发人员测试的主要缺点是:绝大部分测试都是在理想的场景中进行的。在这些情况下并不会出现 缺陷 —— 能导致出现问题的往往是那些边界情况。 什么是边界情况呢?比方说,把 null 值传入一个并未编写如何处理 null 值的方法中,这就是一种边界情况。大多数

开发人员测试的主要缺点是:绝大部分测试都是在理想的场景中进行的。在这些情况下并不会出现缺陷 —— 能导致出现问题的往往是那些边界情况。

什么是边界情况呢?比方说,把 null 值传入一个并未编写如何处理 null 值的方法中,这就是一种边界情况。大多数开发人员通常都不能成功测试这样的场景,因为这没多大意义。但不管有没有意义,发生了这样的情况,就会抛出一个 NullPointerException,然后整个程序就会崩溃。

本月,我将为您推荐一种多层面的方法,来处理代码中那些不易预料的缺陷。尝试为应用程序整合进防御性编程、契约式设计和一种叫做 OVal 的易用的通用验证框架。

 下载 OVal 和 AspectJ
要实现本文中描述的编程解决方案,需要下载 OVal 和 AspectJ。现在请从 参考资料 中下载这些技术,并照着那些例子做。 
 
将敌人暴露出来

清单 1 中的代码为给定的 Class 对象(省去了 java.lang.Object,因为所有对象都最终由它扩展)构建一个类层次。但如果仔细看的话,您会注意到一个有待发现的潜在缺陷,即该方法对对象值所做的假设。


清单 1. 不检验 null 的方法
    
public static Hierarchy buildHierarchy(Class clzz){

 Hierarchy hier = new Hierarchy();
 hier.setBaseClass(clzz);
 Class superclass = clzz.getSuperclass();

 if(superclass != null && superclass.getName().equals("java.lang.Object")){
  return hier;
 }else{     
  while((clzz.getSuperclass() != null) &&
    (!clzz.getSuperclass().getName().equals("java.lang.Object"))){
     clzz = clzz.getSuperclass();
     hier.addClass(clzz);
  }        
  return hier;
 }
}    
 


刚编好这个方法,我还没注意到这个缺陷,但由于我狂热地崇拜开发人员测试,于是我编写了一个使用 TestNG 的常规测试。而且,我还利用了 TestNG 方便的 DataProvider 特性,借助该特性,我创建了一个通用的测试用例并通过另一个方法来改变它的参数。运行清单 2 中定义的测试用例会产生两个通过结果!一切都运转良好,不是吗?


清单 2. 验证两个值的 TestNG 测试
    
import java.util.Vector;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class BuildHierarchyTest {

原文转自:http://www.ltesting.net