原創(chuàng)文章歡迎轉(zhuǎn)載,但請(qǐng)保留作者信息]
Justin 于 2010-01-03
這里我所說的“對(duì)異常免疫的代碼”,原文是exception-safe code。(侯捷的版本是“異常安全代碼”,不過我覺得自己的版本比較容易理解……)
對(duì)異常免疫的函數(shù)在異常發(fā)生的時(shí)候應(yīng)該具備兩個(gè)特征:
-
不泄漏任何資源(內(nèi)存、鎖等等)
-
不造成任何數(shù)據(jù)結(jié)構(gòu)的損壞
并能夠提供至少以下保證中的一項(xiàng):
-
基本的保證:當(dāng)異常拋出時(shí),程序中的對(duì)象、數(shù)據(jù)免遭破壞。
-
較強(qiáng)的保證:當(dāng)異常拋出時(shí),程序的狀態(tài)不會(huì)被改變。
從狀態(tài)機(jī)的角度來看,若成功調(diào)用函數(shù),則系統(tǒng)進(jìn)入成功后的狀態(tài);如果函數(shù)中因異常而出錯(cuò),系統(tǒng)應(yīng)該留在調(diào)用函數(shù)前的狀態(tài):也就是說,系統(tǒng)在調(diào)用函數(shù)后,只會(huì)有兩種狀態(tài)。這是比前一條更強(qiáng)的保證。(看來Scott也愛上了比喻:書中說這就好比女生懷孕,要么就是懷上了,要么就是沒中招,沒人能“半”懷孕的@#¥%)
-
最強(qiáng)的保證:不會(huì)有異常拋出。例如對(duì)內(nèi)置類型的操作就不會(huì)拋出異常。這是最理想的,但也很難做到。更多的函數(shù)只能在前兩者中做一選擇。
為了能夠提供較強(qiáng)的保證,也即系統(tǒng)的狀態(tài)不因異常拋出與否而變化,大師又重新提出了“先拷貝后交換”(copy-and-swap)這一方法論來。 用不那么嚴(yán)謹(jǐn)?shù)恼f法:為了避免在操作對(duì)象時(shí)觸發(fā)異常影響系統(tǒng)狀態(tài),“先拷貝后交換”先是創(chuàng)建了一個(gè)臨時(shí)對(duì)象,將所有的操作都施加在該臨時(shí)對(duì)象上。如果沒有出錯(cuò),把這個(gè)處理過的臨時(shí)對(duì)象和真正需要處理的對(duì)象交換一通,算是順利完成任務(wù);如果有錯(cuò)并拋出了異常,原系統(tǒng)狀態(tài)也不會(huì)被影響,因?yàn)檎嬲枰幚淼膶?duì)象根本沒有被動(dòng)過。 當(dāng)然,天下沒有免費(fèi)的午餐。 “先拷貝后交換”不僅耗費(fèi)了一個(gè)臨時(shí)對(duì)象的存儲(chǔ)代價(jià),同時(shí)支出的還有后面交換對(duì)象時(shí)的時(shí)間和資源開銷。因此,對(duì)異常免疫的較強(qiáng)保證是很好很強(qiáng)大,但是實(shí)際中并不是任何時(shí)候都需要做到那么高的保證。殺雞豈需用牛刀?
最后要提醒的是,對(duì)異常免疫的函數(shù)也符合“短板理論”:木桶能裝的水與其最短的那塊木板有關(guān),函數(shù)對(duì)異常免疫的程度也由函數(shù)中程度最低的代碼(包括其調(diào)用的函數(shù))決定。某個(gè)函數(shù)如果調(diào)用了另外一個(gè)一出現(xiàn)異常就崩潰的函數(shù),那么這個(gè)函數(shù)就不能提供基本的異常免疫保證。
|