因為我用的是 OVal,所以我可以完成下列任務(wù):
對 fileSet 類成員指定一個約束條件,確保使用 @Size 標注時其大小總是至少為 1 或更大。
確保在使用 @PreValidateThis 標注調(diào)用 execute() 方法前 驗證這個約束條件。
這兩步讓我能夠有效地去除 validate() 方法中的條件檢驗,讓 OVal 為我完成這些,如清單 11 所示:
清單 11. 經(jīng)過改進、無條件檢驗的 HierarchyBuilderTask
@Guarded
public class HierarchyBuilderTask extends Task {
private Report report;
@Size(min = 1)
private List fileSet;
private void validate() throws BuildException {
if (this.report == null) {
this.log("no report defined, printing XML to System.out");
}
}
@PreValidateThis
public void execute() throws BuildException {
validate();
String[] classes = this.getQualifiedClassNames(this.fileSet);
Hierarchy[] hclz = new Hierarchy[classes.length];
try{
for(int x = 0; x < classes.length; x++){
hclz[x] = HierarchyBuilder.buildHierarchy(classes[x]);
}
BatchHierarchyXMLReport xmler = new BatchHierarchyXMLReport(new Date(), hclz);
this.handleReportCreation(xmler);
}catch(ClassNotFoundException e){
throw new BuildException("Unable to load class check classpath! " + e.getMessage());
}
}
//more methods below....
}
清單 11 中的 execute() 一經(jīng)調(diào)用(由 Ant 完成),OVal 會驗證 fileSet 成員。如果其為空,意味著沒有指定任何要評估的類,會拋出一個 ConstraintsViolatedException。這個異常會暫停這一過程,像初始代碼一樣,只不過初始代碼會拋出一個 BuildException。
結(jié)束語
防御性編程結(jié)構(gòu)阻止了一個又一個缺陷,但這些結(jié)構(gòu)本身卻不免為代碼添加了重復(fù)的邏輯。把防御性編程技術(shù)和面向方面編程(通過契約式設(shè)計)聯(lián)系起來是抵御所有重復(fù)性代碼的一道堅強防線。
OVal 并不是惟一可用的 DBC 庫,事實上其 DBC 結(jié)構(gòu)對比其他框架來說是相當有限的(例如,它未提供指定類不變式的簡易方法)。從另一方面講,OVal 很容易使用,對約束條件也有很大的選擇余地,若想要花少量力氣可向代碼添加驗證約束條件,它無疑是個上佳之選。另外,用 OVal 創(chuàng)建定制約束條件也相當簡單,所以請不要再添加條件檢驗了,盡情享用 AOP 吧!