您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 >
追求代碼質(zhì)量: 用AOP進(jìn)行防御性編程
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/2/25 14:10:13 ] 推薦標(biāo)簽:

很自然,我也會(huì)編寫(xiě)一個(gè)快速測(cè)試用例來(lái)驗(yàn)證我的檢驗(yàn)是否真能避免 NullPointerException,如清單 4 所示:

清單 4. 驗(yàn)證 null 檢驗(yàn)

    
@Test(expectedExceptions={RuntimeException.class})
public void verifyHierarchyNull() throws Exception{
 Class clzz = null;
 HierarchyBuilder.buildHierarchy(null);  
}   


在本例中,防御性編程似乎解決了問(wèn)題。但僅依靠這項(xiàng)策略會(huì)存在一些缺陷。

防御的缺陷
關(guān)于斷言

清單 3 使用一個(gè)條件來(lái)驗(yàn)證 clzz 的值,實(shí)際上 assert 也同樣好用。使用斷言,無(wú)需指定條件,也不需要指定異常語(yǔ)句。在啟用了斷言的情況下,防御性編程的關(guān)注點(diǎn)全部由 JVM 處理。

盡管防御性編程有效地保證了方法的輸入條件,但如果在一系列方法中使用它,不免過(guò)于重復(fù)。熟悉面向方面編程(或 AOP)的人們會(huì)把它認(rèn)為是橫切關(guān)注點(diǎn),這意味著防御性編程技術(shù)橫跨了代碼庫(kù)。許多不同的對(duì)象都采用這些語(yǔ)法,盡管從純面向?qū)ο蟮挠^點(diǎn)來(lái)看這些語(yǔ)法跟對(duì)象毫不相關(guān)。

而且,橫切關(guān)注點(diǎn)開(kāi)始滲入到契約式設(shè)計(jì)(DBC)的概念中。DBC 是這樣一項(xiàng)技術(shù),它通過(guò)在組件的接口顯式地陳述每個(gè)組件應(yīng)有的功能和客戶(hù)機(jī)的期望值來(lái)確保系統(tǒng)中所有的組件完成它們應(yīng)盡的職責(zé)。從 DBC 的角度講,組件應(yīng)有的功能被認(rèn)為是后置條件,本質(zhì)上是組件的責(zé)任,而客戶(hù)機(jī)的期望值則普遍被認(rèn)為是前置條件。另外,在純 DBC 術(shù)語(yǔ)中,遵循 DBC 規(guī)則的類(lèi)針對(duì)其將維護(hù)的內(nèi)部一致性與外部世界有一個(gè)契約,即人所共知的類(lèi)不變式。

契約式設(shè)計(jì)

我在以前的一篇關(guān)于用 Nice 編程的文章中介紹過(guò) DBC 的概念,Nice 是一門(mén)與 JRE 兼容的面向?qū)ο缶幊陶Z(yǔ)言,它的特點(diǎn)是側(cè)重于模塊性、可表達(dá)性和安全性。有趣的是,Nice 并入了功能性開(kāi)發(fā)技術(shù),其中包括了一些在面向方面編程中的技術(shù)。功能性開(kāi)發(fā)使得為方法指定前置條件和后置條件成為可能。

盡管 Nice 支持 DBC,但它與 Java™ 語(yǔ)言完全不同,因而很難將其用于開(kāi)發(fā)。幸運(yùn)的是,很多針對(duì) Java 語(yǔ)言的庫(kù)也都為 DBC 提供了方便。每個(gè)庫(kù)都有其優(yōu)點(diǎn)和缺點(diǎn),每個(gè)庫(kù)在 DBC 內(nèi)針對(duì) Java 語(yǔ)言進(jìn)行構(gòu)建的方法也不同;但近的一些新特性大都利用了 AOP 來(lái)更多地將 DBC 關(guān)注點(diǎn)包括進(jìn)來(lái),這些關(guān)注點(diǎn)基本上相當(dāng)于方法的包裝器。

前置條件在包裝過(guò)的方法執(zhí)行前擊發(fā),后置條件在該方法完成后擊發(fā)。使用 AOP 構(gòu)建 DBC 結(jié)構(gòu)的一個(gè)好處(請(qǐng)不要同該語(yǔ)言本身相混淆!)是:可以在不需要 DBC 關(guān)注點(diǎn)的環(huán)境中將這些結(jié)構(gòu)關(guān)掉(像斷言能被關(guān)掉一樣)。以橫切的方式對(duì)待安全性關(guān)注點(diǎn)的真正妙處是:可以有效地重用 這些關(guān)注點(diǎn)。眾所周知,重用是面向?qū)ο缶幊痰囊粋(gè)基本原則。AOP 如此完美地補(bǔ)充了 OOP 難道不是一件極好的事情嗎?

結(jié)合了 OVal 的 AOP

OVal 是一個(gè)通用的驗(yàn)證框架,它通過(guò) AOP 支持簡(jiǎn)單的 DBC 結(jié)構(gòu)并明確地允許:

    為類(lèi)字段和方法返回值指定約束條件
    為結(jié)構(gòu)參數(shù)指定約束條件
    為方法參數(shù)指定約束條件

此外,OVal 還帶來(lái)大量預(yù)定義的約束條件,這讓創(chuàng)建新條件變得相當(dāng)容易。

由于 OVal 使用 AspectJ 的 AOP 實(shí)現(xiàn)來(lái)為 DBC 概念定義建議,所以必須將 AspectJ 并入一個(gè)使用 OVal 的項(xiàng)目中。對(duì)于不熟悉 AOP 和 AspectJ 的人們來(lái)說(shuō),好消息是這不難實(shí)現(xiàn),且使用 OVal (甚至是創(chuàng)建新的約束條件)并不需要真正對(duì)方面進(jìn)行編碼,只需編寫(xiě)一個(gè)簡(jiǎn)單的自引導(dǎo)程序即可,該程序會(huì)使 OVal 所附帶的默認(rèn)方面植入您的代碼中。

在創(chuàng)建這個(gè)自引導(dǎo)程序方面前,要先下載 AspectJ。具體地說(shuō),您需要將 aspectjtools 和 aspectjrt JAR 文件并入您的構(gòu)建中來(lái)編譯所需的自引導(dǎo)程序方面并將其編入您的代碼中。

自引導(dǎo) AOP

下載了 AspectJ 后,下一步是創(chuàng)建一個(gè)可擴(kuò)展 OVal GuardAspect 的方面。它本身不需要做什么,如清單 5 所示。請(qǐng)確保文件的擴(kuò)展名以 .aj 結(jié)束,但不要試著用常規(guī)的 javac 對(duì)其進(jìn)行編譯。

清單 5. DefaultGuardAspect 自引導(dǎo)程序方面

    
import net.sf.oval.aspectj.GuardAspect;

public aspect DefaultGuardAspect extends GuardAspect{ 
 public DefaultGuardAspect(){
  super();  
 } 
}


AspectJ 引入了一個(gè) Ant 任務(wù),稱(chēng)為 iajc,充當(dāng)著 javac 的角色;此過(guò)程對(duì)方面進(jìn)行編譯并將其編入主體代碼中。在本例中,只要是我指定了 OVal 約束條件的地方,在 OVal 代碼中定義的邏輯會(huì)編入我的代碼,進(jìn)而充當(dāng)起前置條件和后置條件。

請(qǐng)記住 iajc 代替了 javac。例如,清單 6 是我的 Ant build.xml 文件的一個(gè)代碼片段,其中對(duì)代碼進(jìn)行了編譯并把通過(guò)代碼標(biāo)注發(fā)現(xiàn)的所有 OVal 方面編入進(jìn)來(lái),如下所示:

清單 6. 用 AOP 編譯的 Ant 構(gòu)建文件片段

    
<target name="aspectjc" depends="get-deps">

 <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
  <classpath>
   <path refid="build.classpath" />
  </classpath>
 </taskdef>

 <iajc destdir="${classesdir}" debug="on" source="1.5">
  <classpath>
   <path refid="build.classpath" />
  </classpath>
  <sourceroots>
   <pathelement location="src/java" />
   <pathelement location="test/java" />
  </sourceroots>
 </iajc>

</target>

上一頁(yè)1234下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd