l

2014年1月2日 星期四

你的汽車有多耐撞?談談例外安全性

Dec. 30 22:48~23:06

螢幕快照 2013-12-30 下午11.05.30

 

在購買新車的時候,除了考慮車的外型、顏色,性能以外,另外一個最重要的因素,應該就是安全性。翻成白話文就是:這輛車耐不耐撞?會不會車尾輕輕被A到一下,整個車屁股就解體了?一般而言,大家普遍的印象都是,歐洲車的板金比較厚,比較耐撞。日系車種為了表現出漂亮的油耗,車子都比較輕,也比較不耐撞。

北美和歐洲都有所謂的汽車耐撞測試,滿分五分,分數越高代表車輛在撞擊之後對於人員的安全性具有越高的保護。

那程式呢?有沒有程式在發生例外之後的安全性標準?

有的,有些研究學者可以用數學的方式來研究例外安全性。太理論的東西大部分的鄉民應該都「嘸呷意(不喜歡)」,這一章介紹一個比較沒那麼理論的標準:例外安全性(exception safety

***

Exception safety原本是C++社群在討論C++標準類別庫的實作,應該要達到怎樣的標準才可以稱為例外安全,可參考維基百科與其所列出之參考資料,或是以下書籍:H. Sutter, Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions, Addison-Wesley, 1999; S. Meyers, Effective C++: 55 Specific Ways to Improve Your Programs and Designs, 3rd, Addison-Wesley, 2005。雖然這個觀念起始於C++語言,但是同樣可以適用於其他支援例外處理的程式語言,像是Java、C#、Python、Ruby等。

Exception safety可區分為四個等級:

  • 不保證(no guarantee):一個函數丟出例外的時候,對於系統的狀態正確性沒有任何的保證。系統可能恰巧處於正確狀態,也極有可能處於錯誤狀態。
  • 基本保證(basic guarantee):又稱為無洩漏保證 (no-leak guarantee),發生例外的函數可能會造成一些副作用,但系統基本上處於正確狀態,而且沒有資源洩漏發生。例如,假設有一個函數drawPicture()負責在螢幕上重複輪流顯示圖(a)的大眼怪以及圖(b)的尤達大師。假設drawPicture()正在將尤達大師顯示在畫面上的時候發生例外,如果drawPicture()具備basic guarantee,則它會保證例外發生之後系統對於照片的資源使用沒有發生資源洩漏的問題,而且畫面上一定會有照片被顯示(系統狀態是對的)。但是,drawPicture()無法保證畫面上所顯示的是尤達大師,還是大眼怪。

clip_image002 clip_image004

a)大眼怪,(b)尤達大師

 

  • 強烈保證(strong guarantee):具備認可或復原(commit-or-rollback)或是全部或沒有(all-or-nothing)的語意,就好像資料庫交易處理一樣,一個函數執行,要就成功,否則就失敗,沒有模糊的空間,不會產生什麼副作用,也不會有資源洩漏的問題。假設drawPicture()具備strong guarantee,它目前正將尤達大師的照片替換掉大眼怪的照片。如果沒有例外發生,則drawPicture()執行結束之後會保證螢幕上一定是顯示尤達大師的照片。如果drawPicture()的執行發生例外,則它會保證螢幕上顯示的依然是大眼怪的照片。
  • 不丟擲保證(no-throw guarantee):又稱為失效透明(failure transparency),翻成白話文的意思是說函數的執行不會失敗,當然也不會丟出任何例外。No-throw guarantee並不是說函數在執行的時候不會遭遇例外,而是說即使遭遇到例外,也要在內部將例外狀況處理好,然後達成原本該函數被賦予的任務。所以從外部呼叫者的角度來看,這個函數保證一定會成功。

要做到no-throw guarantee其實是一件很困難的事情,因為程式要出錯的可能性實在是太多、太多了,而要讓一個函數保證永不出錯,實在是有點強人所難。但是,如果沒有依靠少數具備no-throw guarantee的函數來「撐場面」,就不可能達到strong guarantee與basic guarantee。在C++的標準類別庫中,也有只少數操作,例如基本型別、陣列、指標的指定、解構函數、swap()函數少數操作具備no-throw guarantee(請鄉民想一下,為什麼這幾個操作需要達到no-throw guarantee?)。

一個函數符合例外安全(exception safe如果這個函數具備了basic guarantee、strong guarantee、或是no-throw guarantee。

***

看到這邊請鄉民們回想一下:以前寫程式的時候,是否有留意到自己的程式達到哪一個exception safety等級?如果大部分的函數都是no guarantee,那就真的要多買幾包綠色乖乖,放到電腦旁邊,求神明保佑。在這種情況下,系統不出錯才是異常,出錯則反而是正常。

Exception safety的觀念,可以做為開發強健度系統的一種評估與驗收標準。在專案規畫階段,可以依據專案的特性,來判斷與規範程式所需要達到的exception safety。例如,如果這只是網頁查詢資料系統,而且時程很趕,客戶付的錢又很少,也許大部分的函數只要做到basic guarantee就可以了。如果是屬於系統共用或是核心元件,則應該儘量做到strong guarantee。如果是為了趕著讓業務明天可以展示給客戶看的雛型,則也許根本不需要考慮exception safety的問題,no guarantee就OK了。

***

友藏內心獨白:這一篇也是從新書中節錄出來的。

2 則留言:

  1. 台灣車商業務:『車子是買來開的,不是買來撞的』

    回覆刪除
  2. "假設drawPicture()具備strogn guarantee,"的 strong guarantee,小失誤。

    回覆刪除