假設一個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