提高代码可测试性的准则

Tags: 代码可测试性, 隔离依赖, 注入依赖

在用测试驱动开发的方式写代码时,我们实际上是在做设计,而这些设计会直接影响代码将来的友好程度。在编写代码前先写测试能够提高代码的可测试性。但如果遵循下列的设计准则,将能解决代码不可测试的问题。

  1. 多用组合少用继承
  2. 避免使用static关键字,以及Singleton模式
  3. 隔离依赖(Isolate dependencies)
  4. 注入依赖(Inject dependencies)

尽量使用组合而非继承

如何从各个独立的功能构建出复杂的对象,对代码的可测试性影响很大。在面向对象的语言中,继承以及组合都可以实现此功能。

继承是静态的、类级别上的责任的划分,在代码编译后不能改变。继承在设计的可测试性、可维护性、以及复杂性方面都有负面影响。

组合是动态的对象级别的责任划分,可以在运行时,替换不同的对象实现不同的职责。组合能够提高可测试性,适应性和可维护性,这些优点远大于几行代码带来的麻烦。

避免使用static关键字,以及Singleton模式

静态方法和Singleton模式会影响可测试性,这取决于待测试代码于静态方法或Singleton模式的纠葛程度。在测试中用测试替身替换静态方法可能及其困难。

隔离依赖(Isolate dependencies)

隔离依赖对可测试性及可维护性至关重要,为了能够方便的用测试替身替换依赖,隔离依赖使其更容易替换非常关键。有几种方法可以解决这个问题

1.把静态方法问访问移至成员方法

2.使用“接缝”技术

接缝(seams):不用修改直接影响行为的代码就能改变系统行为的那个点。换言之,在测试期间可以在某个点用一段代码替换另一段代码,而无需修改待测试代码,这个点就是接缝。

public class OrderProcessor{

    public void process(Order order){

        PrincingService service = getPricingService();

    }

    protected PricingServiece getPricingService(){

       return PrincingService.getInstance();

   }

}

上例中得getPricingService()方法实际就是接缝。

注入依赖(Inject dependencies)

依赖注入(DI)这种代码组织方式可以减少直接依赖,将其变为间接依赖。或者说把getter变成setter。

public class OrderProcessor{

    public void process(Order order){

        PrincingService service = getPricingService();

    }

    protected PricingServiece getPricingService(){

       return PrincingService.getInstance();

   }

}

这段代码展示了如歌隔离依赖,方便以后替换PrincingService实现。这里的getter是指getPrincingService的默认实现,使用PrincingService的静态方法主动获取PrincingService的实例。OrderProcessor类与PrincingService存在耦合关系。使用注入依赖可以解决这个问题。让OrderProcessor明确表示“我需要一个PrincingServie,使用我之前必须先满足我得需要”。具体实现如下:

public class OrderProcessor{

    private PrincingService  _princingService;

    public OrderProcessor(PrincingService princingService){

        _princingService = princingService;

    }

}

虽然依赖注入是代码的测试性大有改观,但也要付出一定的代价。必须把所有的依赖传递给各个组件。

 

Add a Comment