最佳实践TDD - Java对象验证和清洁代码

时间:2013-05-05 20:10:22

标签: java oop validation mocking tdd

假设一个名为Car的Java类,其对象通过静态工厂初始化:

public class Car {

    private String name;

    private Car(String name){//...}

    public static Car createCar(String name){
        //mechanism to validate the car attributes
        return new Car(name);
    }
}

当然,我想将验证过程提取到名为CarValidator的专用类中。

有两种方法可以为工厂提供此验证器:

不是stubbable / mockable验证器

public static Car createCar(String name){
     new CarValidator(name); // throw exception for instance if invalid cases
     return new Car(name);
}

Stubbable / mockable验证器:

public static Car createCar(CarValidator carValidator, String name){ //ideally being an interface instead
    carValidator.validate(); 
    return new Car(name);
}

它看起来像冗余:CarValidator已经包含name值,因为它将Car个参数存储为自己的字段(先验最简洁的方式),因此我们可以绕过第二个参数像这样:

public static Car createCar(CarValidator carValidator){ 
     carValidator.validate();  
     return new Car(carValidator.getName());
}

然而,这看起来不清楚......为什么Car会从Validator =>中找到其值?毫无意义。

所以,我们可以像这样重构:

public static Car createCar(CarValidator carValidator, String name){ 
                        carValidator.validate(name); // throwing exception for instance if invalid cases
                        return new Car(carValidator.name());
}

听起来不那么奇怪,但CarValidator失去了创建字段的好处,而不是将参数传递给每个必要的私有方法,如:

private checkForCarName(String name); 

我应该选择哪种方法?

1 个答案:

答案 0 :(得分:1)

我的主张如下: 我不会将域对象的验证与对象本身混合在一起。

如果域对象假定传递给它的数据有效,并且应该在其他地方执行验证(例如在工厂中,但不是必需的话),那将会更加清洁。

在“工厂”中,您将执行数据准备状态(验证,漏洞删除等),然后您将创建一个新对象。

您将能够测试工厂(如果它正确验证),而不是域对象本身。