假设一个Java类名为Car
,其对象通过静态工厂初始化:最佳实践TDD - 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
=>没有意义。
所以,我们可以refactorate这样的:
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);
我应该选择哪种方法?
对不起,但我不同意。验证对象机制应该在领域类别之外进行描述,这一点毫无疑问。但为了始终保持一个对象处于内聚状态,特别是防止有人在事先不使用“外部”工厂的情况下创建它,必须在创建它之前验证它,因此验证应该通过域类来调用。我特别为不可改变的阶级而思考。 – Mik378 2013-05-05 20:43:53
我相信这里的一个好方法是使用Fluent Builder模式。这样,Car类本身可以不可变,Car.Builder类将包含所有必要的验证规则。 – Olaf 2013-05-07 20:46:15
@Olaf是的,但这并不能解决问题。您的解决方案的后果:违反SRP。如果我们想要解决SRP问题,即使有一位漂亮流利的建筑师,我们也会在帖子中回到我的问题。 – Mik378 2013-05-08 13:17:51